Remove repeat sfree(state->nosehoover_xi)
[alexxy/gromacs.git] / src / ngmx / x11.c
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  *
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  *
30  * For more info, check our website at http://www.gromacs.org
31  *
32  * And Hey:
33  * Gyas ROwers Mature At Cryogenic Speed
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include "typedefs.h"
40 #include <Xstuff.h>
41 #include <x11.h>
42 #include "sysstuff.h"
43 #include <string.h>
44 #include "smalloc.h"
45 #include "string2.h"
46
47 /* These colours will be mapped to black on a monochrome screen */
48 unsigned long BLACK, BLUE, GREEN, CYAN, RED, BROWN, GREY, DARKGREY;
49
50 /* These colours will be mapped to white on a monochrome screen */
51 unsigned long LIGHTBLUE, LIGHTGREEN, LIGHTGREY, LIGHTCYAN, LIGHTRED, VIOLET, YELLOW, WHITE;
52
53 static XFontStruct *XLQF(FILE *err, Display *disp, const char *name)
54 {
55     XFontStruct *font = XLoadQueryFont(disp, name);
56 #ifdef DEBUG
57     if (font != NULL)
58     {
59         fprintf(err, "Loaded font %s\n", name);
60     }
61 #endif
62     return font;
63 }
64
65 static XFontStruct *GetFont(FILE *err, Display *disp, char *name)
66 {
67     static const char *fontnames[] = {
68         "sansb12", "8x13bold", "8x13",
69         "9x15", "6x13", "fixed"
70     };
71 #define MAXNAMES (sizeof(fontnames)/sizeof(fontnames[0]))
72     int                i;
73     XFontStruct       *font;
74     int                count;
75     char             **fontlist;
76     gmx_bool           bFont = FALSE;
77
78     if (name)
79     {
80         bFont = (gmx_bool) ((font = XLQF(err, disp, name)) != NULL);
81     }
82     else
83     {
84         font = NULL;
85     }
86
87     for (i = 0; (!bFont && (i < MAXNAMES)); i++)
88     {
89         bFont = (gmx_bool) ((font = XLQF(err, disp, fontnames[i])) != NULL);
90     }
91
92     if (!bFont)
93     {
94         fontlist = XListFonts(disp, "?", 1, &count);
95         if (count != 0)
96         {
97             bFont = (gmx_bool) ((font = XLQF(err, disp, fontlist[0])) != NULL);
98         }
99     }
100     if (!bFont)
101     {
102         fprintf (err, "Cannot load any suitable font\n");
103     }
104     return font;
105 }
106
107 static GC GetGC(Display *disp, XFontStruct *font)
108 {
109     XGCValues     values;
110
111     values.font       = font->fid;
112     values.foreground = WhitePixel(disp, DefaultScreen(disp));
113
114     return XCreateGC(disp, DefaultRootWindow(disp), GCForeground|GCFont, &values);
115 }
116
117 void GetNamedColor(t_x11 *x11, const char *name, unsigned long *col)
118 {
119     /* If name is found than col set to that colour else col is unchanged */
120     XColor exact, clr;
121
122     if (XAllocNamedColor(x11->disp, x11->cmap, name, &clr, &exact))
123     {
124         *col = clr.pixel;
125     }
126     else
127     {
128         fprintf(x11->console, "No colour %s\n", name);
129     }
130 }
131
132 static t_wlist *GetWList(t_x11 *x11, Window w)
133 {
134     t_wlist *curs;
135
136     curs = x11->wlist;
137     while (curs && (curs->w != w))
138     {
139         curs = curs->next;
140     }
141
142     return curs;
143 }
144
145 typedef struct {
146     Window     w;
147     gmx_bool   b;
148 } t_peek;
149
150 static Bool TestEvent(Display *disp, XEvent *event, char *arg)
151 {
152     t_peek *tp;
153
154     fprintf(stderr, "TestEvent\n");
155     tp = (t_peek *)arg;
156     if ((event->xany.window == tp->w) && (event->type == ConfigureNotify))
157     {
158         tp->b = TRUE;
159         return True;
160     }
161     return False;
162 }
163
164 static void MainLoop(t_x11 *x11)
165 {
166     gmx_bool    bReturn;
167     XEvent      event;
168     t_wlist    *curs;
169     Window      w;
170
171     for (bReturn = FALSE; (!bReturn); )
172     {
173         if (x11->wlist)
174         {
175             XNextEvent(x11->disp, &event);
176             w    = event.xany.window;
177             curs = GetWList(x11, w);
178             if (!curs)
179             {
180                 bReturn = TRUE;
181             }
182             if (!bReturn)
183             {
184                 switch (event.type)
185                 {
186                     case Expose:
187                         /* Filter out expose events with non-zero count field */
188                         if (event.xexpose.count != 0)
189                         {
190                             curs = NULL;
191                         }
192                         break;
193                     case ConfigureNotify:
194                         /* Check if more are coming...
195                            if (XCheckTypedWindowEvent(x11->disp,w,ConfigureNotify,&config))
196                            curs=NULL; */
197                         break;
198                     default:
199                         break;
200                 }
201                 if (curs)
202                 {
203                     bReturn = (*curs->cb)(x11, &event, w, curs->data);
204                 }
205             }
206         }
207     }
208 }
209
210 static void RegisterCallback(t_x11 *x11, Window w, Window Parent,
211                              CallBack cb, void *data)
212 {
213     t_wlist *curs, *item;
214
215     snew(item, 1);
216     item->w      = w;
217     item->Parent = Parent;
218     item->cb     = cb;
219     item->mask   = 0;
220     item->data   = data;
221     item->next   = NULL;
222
223     if (x11->wlist)
224     {
225         curs = x11->wlist;
226         while (curs->next)
227         {
228             curs = curs->next;
229         }
230         curs->next = item;
231     }
232     else
233     {
234         x11->wlist = item;
235     }
236 }
237
238 static void UnRegisterCallback(t_x11 *x11, Window w)
239 {
240     t_wlist *curs;
241
242     curs = x11->wlist;
243     if (curs)
244     {
245         if (curs->w == w)
246         {
247             x11->wlist = curs->next;
248             sfree(curs);
249         }
250         else
251         {
252             while (curs->next && (curs->next->w != w))
253             {
254                 curs = curs->next;
255             }
256             if (curs->next)
257             {
258                 t_wlist *tmp = curs->next;
259
260                 curs->next = curs->next->next;
261                 sfree(tmp);
262             }
263         }
264     }
265 }
266
267 static void SetInputMask(t_x11 *x11, Window w, unsigned long mask)
268 {
269     t_wlist *curs;
270
271     curs = GetWList(x11, w);
272     if (curs)
273     {
274         curs->mask = mask;
275         XSelectInput(x11->disp, w, (long)mask);
276     }
277     else
278     {
279         fprintf(x11->console, "No such window (%d)\n", (int)w);
280     }
281 }
282
283 static unsigned long GetInputMask(t_x11 *x11, Window w)
284 {
285     t_wlist *curs;
286
287     curs = GetWList(x11, w);
288     if (curs)
289     {
290         return curs->mask;
291     }
292     else
293     {
294         return 0;
295     }
296 }
297
298 static void CleanUp(t_x11 *x11)
299 {
300     t_wlist *curs;
301
302     curs = x11->wlist;
303     while (curs)
304     {
305         x11->wlist = curs->next;
306         XDestroyWindow(x11->disp, curs->w);
307         sfree(curs);
308         curs = x11->wlist;
309     }
310     XCloseDisplay(x11->disp);
311 }
312
313 static void Xrm(int *argc, char *argv[])
314 {
315     /*
316        static XrmOptionDescRec opTable[] = {
317        {"-background",   "*background",
318          XrmoptionSepArg, (caddr_t) NULL},
319        {"-bd",           "*borderColor",
320          XrmoptionSepArg, (caddr_t) NULL},
321        {"-bg",           "*background",
322          XrmoptionSepArg, (caddr_t) NULL},
323        {"-borderwidth",  "*TopLevelShell.borderwidth",
324          XrmoptionSepArg, (caddr_t) NULL},
325        {"-bordercolor",   "*borderColor",
326          XrmoptionSepArg, (caddr_t) NULL},
327        {"-bw",            "*TopLevelShell.borderColor",
328          XrmoptionSepArg, (caddr_t) NULL},
329        {"-display",       ".display",
330          XrmoptionSepArg, (caddr_t) NULL},
331        {"-fg",            "*foreground",
332          XrmoptionSepArg, (caddr_t) NULL},
333        {"-fn",            "*font",
334          XrmoptionSepArg, (caddr_t) NULL},
335        {"-font",          "*font",
336          XrmoptionSepArg, (caddr_t) NULL},
337        {"-foreground",    "*foreground",
338          XrmoptionSepArg, (caddr_t) NULL},
339        {"-geometry",      ".TopLevelShell.geometry",
340          XrmoptionSepArg, (caddr_t) NULL},
341        {"-iconic",        ".TopLevelShell.iconic",
342          XrmoptionNoArg,  (caddr_t) "on"},
343        {"-name",          ".name",
344          XrmoptionSepArg, (caddr_t) NULL},
345        {"-reverse",       "*reverseVideo",
346          XrmoptionNoArg,  (caddr_t) "on"},
347        {"-rv",            "*reverseVideo",
348          XrmoptionNoArg,  (caddr_t) "on"},
349        {"-synchronous",   ".synchronous",
350          XrmoptionNoArg,  (caddr_t) "on"},
351        {"-title",         ".TopLevelShell.title",
352          XrmoptionSepArg, (caddr_t) NULL},
353        {"-xrm",            NULL,
354          XrmoptionSepArg, (caddr_t) NULL},
355        };
356        #define TABLELENGTH (sizeof(opTable)/sizeof(opTable[0]))
357        XrmInitialize();*/
358 }
359
360 static void Flush(t_x11 *x11)
361 {
362     fflush(x11->console);
363 }
364
365 t_x11 *GetX11(int *argc, char *argv[])
366 {
367     static const char *v_name[] = {
368         "DirectColor", "TrueColor", "PseudoColor",
369         "StaticColor", "GrayScale", "StaticGray"
370     };
371     static int         v_class[] = {
372         DirectColor, TrueColor, PseudoColor,
373         StaticColor, GrayScale, StaticGray
374     };
375 #define NCLASS (sizeof(v_class)/sizeof(v_class[0]))
376
377     XVisualInfo     v_info;
378     t_x11          *x11;
379     int             ARGC;
380     char          **ARGV;
381     char           *display;
382     char           *fontname;
383     char           *title, *FG = NULL, *BG = NULL;
384     gmx_bool        bVerbose = FALSE;
385     int             i;
386
387     title = strdup(argv[0]);
388
389     /* First check environment */
390     fontname = getenv("GMXFONT");
391     display  = getenv("DISPLAY");
392
393     snew(ARGV, *argc);
394     ARGC = 1;
395     for (i = 1; (i < *argc); i++)
396     {
397         if (argv[i][0] == '-')
398         {
399             if (strlen(argv[i]) > 1)
400             {
401                 if ((*argc) > i+1)
402                 {
403                     switch (argv[i][1])
404                     {
405                         case 'b':
406                             BG = argv[++i];
407                             break;
408                         case 'd':
409                             display = argv[++i];
410                             break;
411                         case 'f':
412                             switch (argv[i][2])
413                             {
414                                 case 'o':
415                                     fontname = argv[++i];
416                                     break;
417                                 case 'g':
418                                     FG = argv[++i];
419                                     break;
420                             }
421                             break;
422                         case 't':
423                             sfree(title);
424                             title = strdup(argv[++i]);
425                             break;
426                         case 'v':
427                             bVerbose = TRUE;
428                             break;
429                         default:
430                             ARGV[ARGC++] = argv[i];
431                             break;
432                     }
433                 }
434             }
435         }
436         else
437         {
438             ARGV[ARGC++] = argv[i];
439         }
440     }
441     for (i = 1; (i < ARGC); i++)
442     {
443         argv[i] = ARGV[i];
444     }
445     *argc      = ARGC;
446     argv[ARGC] = NULL;
447
448     snew(x11, 1);
449     x11->dispname = display;
450     if (bVerbose)
451     {
452         x11->console = stderr;
453     }
454     else
455     if ((x11->console = fopen("/dev/null", "w")) == NULL)
456     {
457         x11->console = stderr;
458     }
459
460     if ((x11->disp = XOpenDisplay(display)) == NULL)
461     {
462         if (bVerbose)
463         {
464             fprintf(x11->console, "Display %s invalid\n", display);
465         }
466         return NULL;
467     }
468
469     if ((x11->font = GetFont(x11->console, x11->disp, fontname)) == NULL)
470     {
471         return NULL;
472     }
473     if ((x11->gc = GetGC(x11->disp, x11->font)) == NULL)
474     {
475         return NULL;
476     }
477
478     x11->root   = DefaultRootWindow(x11->disp);
479     x11->screen = DefaultScreen(x11->disp);
480     x11->depth  = DefaultDepth(x11->disp, x11->screen);
481     x11->cmap   = DefaultColormap(x11->disp, x11->screen);
482
483     /* These colours will be mapped to black on a monochrome screen */
484     x11->fg = BLACK = BLUE = GREEN = CYAN = RED = BROWN = GREY = DARKGREY =
485                                         BlackPixel(x11->disp, x11->screen);
486
487     /* These colours will be mapped to white on a monochrome screen */
488     x11->bg       =
489         LIGHTBLUE = LIGHTGREY = LIGHTGREEN = LIGHTCYAN = LIGHTRED = VIOLET = YELLOW = WHITE =
490                                         WhitePixel(x11->disp, x11->screen);
491
492     if (x11->depth > 1)
493     {
494         /* Not B & W, Look what kind of screen we've got... */
495         for (i = 0; (i < NCLASS); i++)
496         {
497             if (!XMatchVisualInfo(x11->disp, x11->screen, x11->depth,
498                                   v_class[i], &v_info))
499             {
500                 break;
501             }
502         }
503         if ((i == 4) || (i == 5))
504         {
505             fprintf(x11->console, "Greyscale screen, using B & W only\n");
506         }
507         else
508         {
509             /* We have real color! */
510             fprintf(x11->console, "%s screen with depth %d.\n",
511                     (i == NCLASS) ? "Unknown" : v_name[i], x11->depth);
512             GetNamedColor(x11, "midnight blue", &BLUE);
513             GetNamedColor(x11, "DarkGreen", &GREEN);
514             GetNamedColor(x11, "SeaGreen", &CYAN);
515             GetNamedColor(x11, "red4", &RED);
516             GetNamedColor(x11, "Gray", &GREY);
517             GetNamedColor(x11, "Gray", &DARKGREY);
518             GetNamedColor(x11, "LightGray", &LIGHTGREY);
519             GetNamedColor(x11, "green", &LIGHTGREEN);
520             GetNamedColor(x11, "cyan", &LIGHTCYAN);
521             GetNamedColor(x11, "tomato1", &LIGHTRED);
522             GetNamedColor(x11, "violet", &VIOLET);
523             GetNamedColor(x11, "yellow", &YELLOW);
524             GetNamedColor(x11, "brown", &BROWN);
525             GetNamedColor(x11, "CornFlowerBlue", &LIGHTBLUE);
526         }
527     }
528     else
529     {
530         fprintf(x11->console, "Monochrome screen.\n");
531     }
532
533     /* We should use Xrm here... */
534     if (FG)
535     {
536         GetNamedColor(x11, FG, &(x11->fg));
537     }
538     else
539     {
540         x11->fg = BLACK;
541     }
542     if (BG)
543     {
544         GetNamedColor(x11, BG, &(x11->bg));
545     }
546     else
547     {
548         x11->bg = LIGHTGREY;
549     }
550     x11->title = strdup(title);
551     sfree(title);
552     x11->wlist              = NULL;
553     x11->GetNamedColor      = &GetNamedColor;
554     x11->MainLoop           = &MainLoop;
555     x11->RegisterCallback   = &RegisterCallback;
556     x11->UnRegisterCallback = &UnRegisterCallback;
557     x11->SetInputMask       = &SetInputMask;
558     x11->GetInputMask       = &GetInputMask;
559     x11->CleanUp            = &CleanUp;
560     x11->Flush              = &Flush;
561
562     x11->Flush(x11);
563
564     return x11;
565 }