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