f620d9b9a54edc1425a53a873842f6ebef8b74e3
[alexxy/gromacs.git] / src / ngmx / x11.c
1 /*
2  * $Id$
3  * 
4  *       This source code is part of
5  * 
6  *        G   R   O   M   A   C   S
7  * 
8  * GROningen MAchine for Chemical Simulations
9  * 
10  *               VERSION 2.0
11  * 
12  * Copyright (c) 1991-1999
13  * BIOSON Research Institute, Dept. of Biophysical Chemistry
14  * University of Groningen, The Netherlands
15  * 
16  * Please refer to:
17  * GROMACS: A message-passing parallel molecular dynamics implementation
18  * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19  * Comp. Phys. Comm. 91, 43-56 (1995)
20  * 
21  * Also check out our WWW page:
22  * http://md.chem.rug.nl/~gmx
23  * or e-mail to:
24  * gromacs@chem.rug.nl
25  * 
26  * And Hey:
27  * Great Red Oystrich Makes All Chemists Sane
28  */
29 static char *SRCID_x11_c = "$Id$";
30
31 #include <Xstuff.h>
32 #include <x11.h>
33 #include "sysstuff.h"
34 #include "string.h"
35 #include "assert.h"
36 #include "smalloc.h"
37 #include "typedefs.h"
38 #include "string2.h"
39
40 /* These colours will be mapped to black on a monochrome screen */
41 unsigned long BLACK,BLUE,GREEN,CYAN,RED,BROWN,GREY,DARKGREY;
42
43 /* These colours will be mapped to white on a monochrome screen */
44 unsigned long LIGHTBLUE,LIGHTGREEN,LIGHTGREY,LIGHTCYAN,LIGHTRED,VIOLET,YELLOW,WHITE;
45
46 static XFontStruct *XLQF(FILE *err, Display *disp, char *name)
47 {
48   XFontStruct *font=XLoadQueryFont(disp,name);
49 #ifdef DEBUG
50   if (font != NULL) 
51     fprintf(err, "Loaded font %s\n",name);
52 #endif
53   return font;
54 }
55   
56 static XFontStruct *GetFont(FILE *err, Display *disp, char *name)
57 {
58   static char *fontnames[] = { 
59     "sansb12","8x13bold","8x13",
60     "9x15","6x13","fixed" 
61     };
62 #define MAXNAMES (sizeof(fontnames)/sizeof(fontnames[0]))
63   int i;
64   XFontStruct *font;
65   int count;
66   char **fontlist;
67   bool bFont = FALSE;
68
69   if (name)
70     bFont=(bool) (font=XLQF(err,disp,name));
71   else
72     font=NULL;
73     
74   for (i=0; (!bFont && (i<MAXNAMES)); i++) 
75     bFont=(bool) (font=XLQF(err,disp,fontnames[i]));
76
77   if (!bFont) {
78     fontlist=XListFonts(disp,"?",1,&count);
79     if (count!=0) 
80       bFont=(bool) (font=XLQF(err,disp,fontlist[0]));
81   }
82   if (!bFont) 
83     fprintf (err, "Cannot load any suitable font\n");
84   return font;
85 }
86
87 static GC GetGC(Display *disp, XFontStruct *font)
88 {
89   XGCValues     values;
90
91   values.font = font->fid;
92   values.foreground = WhitePixel(disp,DefaultScreen(disp));
93
94   return XCreateGC(disp,DefaultRootWindow(disp),GCForeground|GCFont,&values);
95 }
96
97 void GetNamedColor(t_x11 *x11,char *name,unsigned long *col)
98 {
99   /* If name is found than col set to that colour else col is unchanged */
100   XColor exact,clr;
101
102   if (XAllocNamedColor(x11->disp,x11->cmap,name,&clr,&exact))
103     *col=clr.pixel;
104   else
105     fprintf(x11->console,"No colour %s\n",name);
106 }
107
108 static t_wlist *GetWList(t_x11 *x11, Window w)
109 {
110   t_wlist *curs;
111
112   curs=x11->wlist;
113   while (curs && (curs->w != w))
114     curs=curs->next;
115
116   return curs;
117 }
118
119 typedef struct {
120   Window w;
121   bool   b;
122 } t_peek;
123
124 static Bool TestEvent(Display *disp,XEvent *event,char *arg)
125 {
126   t_peek *tp;
127
128   fprintf(stderr,"TestEvent\n");
129   tp=(t_peek *)arg;
130   if ((event->xany.window==tp->w) && (event->type==ConfigureNotify)) {
131     tp->b=TRUE;
132     return True;
133   }
134   return False;
135 }
136
137 static void MainLoop(t_x11 *x11)
138 {
139   bool    bReturn;
140   XEvent  event;
141   t_wlist *curs;
142   Window  w;
143
144   for (bReturn=FALSE; (!bReturn); ) {
145     if (x11->wlist) {
146       XNextEvent(x11->disp,&event);
147       w=event.xany.window;
148       curs=GetWList(x11,w);
149       if (!curs)
150         bReturn=TRUE;
151       if (!bReturn) {
152         switch (event.type) {
153         case Expose:
154           /* Filter out expose events with non-zero count field */
155           if (event.xexpose.count != 0)
156             curs=NULL;
157           break;
158         case ConfigureNotify:
159           /* Check if more are coming... 
160           if (XCheckTypedWindowEvent(x11->disp,w,ConfigureNotify,&config))
161             curs=NULL; */
162           break;
163         default:
164           break;
165         }
166         if (curs)
167           bReturn=(*curs->cb)(x11,&event,w,curs->data);
168       }
169     }
170   }
171 }
172
173 static void RegisterCallback(t_x11 *x11,Window w,Window Parent,
174                              CallBack cb, void *data)
175 {
176   t_wlist *curs,*new;
177
178   snew(new,1);
179   new->w=w;
180   new->Parent=Parent;
181   new->cb=cb;
182   new->mask=0;
183   new->data=data;
184   new->next=NULL;
185
186   if (x11->wlist) {
187     curs=x11->wlist;
188     while(curs->next)
189       curs=curs->next;
190     curs->next=new;
191   }
192   else
193     x11->wlist=new;
194 }
195
196 static void UnRegisterCallback(t_x11 *x11, Window w)
197 {
198   t_wlist *curs;
199
200   curs=x11->wlist;
201   if (curs) {
202     if (curs->w==w) {
203       x11->wlist=curs->next;
204       sfree(curs);
205     }
206     else {
207       while (curs->next && (curs->next->w != w))
208         curs=curs->next;
209       if (curs->next) {
210         t_wlist *tmp=curs->next;
211
212         curs->next=curs->next->next;
213         sfree(tmp);
214       }
215     }
216   }
217 }
218
219 static void SetInputMask(t_x11 *x11, Window w, unsigned long mask)
220 {
221   t_wlist *curs;
222
223   curs=GetWList(x11,w);
224   if (curs) {
225     curs->mask=mask;
226     XSelectInput(x11->disp,w,(long)mask);
227   }
228   else 
229     fprintf(x11->console,"No such window (%d)\n",(int)w);
230 }
231
232 static unsigned long GetInputMask(t_x11 *x11, Window w)
233 {
234   t_wlist *curs;
235
236   curs=GetWList(x11,w);
237   if (curs)
238     return curs->mask;
239   else
240     return 0;
241 }
242
243 static void CleanUp(t_x11 *x11) 
244 {
245   t_wlist *curs;
246   
247   curs=x11->wlist;
248   while (curs) {
249     x11->wlist=curs->next;
250     XDestroyWindow(x11->disp,curs->w);
251     sfree(curs);
252     curs=x11->wlist;
253   }
254   XCloseDisplay(x11->disp);
255 }
256
257 static void Xrm(int *argc, char *argv[])
258 {
259   /*
260   static XrmOptionDescRec opTable[] = {
261     {"-background",   "*background",    
262        XrmoptionSepArg, (caddr_t) NULL},
263     {"-bd",           "*borderColor",   
264        XrmoptionSepArg, (caddr_t) NULL},
265     {"-bg",           "*background",    
266        XrmoptionSepArg, (caddr_t) NULL},
267     {"-borderwidth",  "*TopLevelShell.borderwidth",    
268        XrmoptionSepArg, (caddr_t) NULL},
269     {"-bordercolor",   "*borderColor",    
270        XrmoptionSepArg, (caddr_t) NULL},
271     {"-bw",            "*TopLevelShell.borderColor",    
272        XrmoptionSepArg, (caddr_t) NULL},
273     {"-display",       ".display",    
274        XrmoptionSepArg, (caddr_t) NULL},
275     {"-fg",            "*foreground",
276        XrmoptionSepArg, (caddr_t) NULL},
277     {"-fn",            "*font",
278        XrmoptionSepArg, (caddr_t) NULL},
279     {"-font",          "*font",
280        XrmoptionSepArg, (caddr_t) NULL},
281     {"-foreground",    "*foreground",
282        XrmoptionSepArg, (caddr_t) NULL},
283     {"-geometry",      ".TopLevelShell.geometry",
284        XrmoptionSepArg, (caddr_t) NULL},
285     {"-iconic",        ".TopLevelShell.iconic",
286        XrmoptionNoArg,  (caddr_t) "on"},
287     {"-name",          ".name",
288        XrmoptionSepArg, (caddr_t) NULL},
289     {"-reverse",       "*reverseVideo",
290        XrmoptionNoArg,  (caddr_t) "on"},
291     {"-rv",            "*reverseVideo",
292        XrmoptionNoArg,  (caddr_t) "on"},
293     {"-synchronous",   ".synchronous",
294        XrmoptionNoArg,  (caddr_t) "on"},
295     {"-title",         ".TopLevelShell.title",
296        XrmoptionSepArg, (caddr_t) NULL},
297     {"-xrm",            NULL,
298        XrmoptionSepArg, (caddr_t) NULL},
299   };
300 #define TABLELENGTH (sizeof(opTable)/sizeof(opTable[0]))
301   XrmInitialize();*/
302 }
303
304 static void Flush(t_x11 *x11)
305 {
306   fflush(x11->console);
307 }
308
309 t_x11 *GetX11(int *argc, char *argv[])
310 {
311   static char *v_name[] = {
312     "DirectColor","TrueColor", "PseudoColor",
313     "StaticColor","GrayScale", "StaticGray"
314     };
315   static int v_class[] = {
316     DirectColor,TrueColor, PseudoColor,
317     StaticColor,GrayScale, StaticGray
318     };
319 #define NCLASS (sizeof(v_class)/sizeof(v_class[0]))
320
321   XVisualInfo v_info;
322   t_x11       *x11;
323   int         ARGC;
324   char        **ARGV;
325   char        *display;
326   char        *fontname;
327   char        *title,*FG=NULL,*BG=NULL;
328   bool        bVerbose=FALSE;
329   int         i;
330
331   title=strdup(argv[0]);
332
333   /* First check environment */
334   fontname=getenv("GMXFONT");
335   display=getenv("DISPLAY");
336
337   snew(ARGV,*argc);
338   ARGC=1;
339   for(i=1; (i < *argc); i++) {
340     if (argv[i][0]=='-') {
341       if (strlen(argv[i]) > 1) {
342         if ((*argc)>i+1)
343           switch(argv[i][1]) {
344           case 'b':
345             BG=argv[++i];
346             break;
347           case 'd':
348             display=argv[++i];
349             break;
350           case 'f':
351             switch(argv[i][2]) {
352             case 'o':
353               fontname=argv[++i];
354               break;
355             case 'g':
356               FG=argv[++i];
357               break;
358             }
359             break;
360           case 't':
361             sfree(title);
362             title=strdup(argv[++i]);
363             break;
364           case 'v':
365             bVerbose=TRUE;
366             break;
367           default:
368             ARGV[ARGC++]=argv[i];
369             break;
370           }
371       }
372     }
373     else 
374       ARGV[ARGC++]=argv[i];
375   }
376   for (i=1; (i<ARGC); i++)
377     argv[i]=ARGV[i];
378   *argc=ARGC;
379   argv[ARGC]=NULL;
380
381   snew(x11,1);
382   x11->dispname=display;
383   if (bVerbose)
384     x11->console=stderr;
385   else
386     if ((x11->console=fopen("/dev/null","w"))== NULL)
387       x11->console=stderr;
388
389   if ((x11->disp=XOpenDisplay(display))==NULL) {
390     if (bVerbose)
391       fprintf(x11->console,"Display %s invalid\n",display);
392     return NULL;
393   }
394   
395   if ((x11->font=GetFont(x11->console,x11->disp,fontname))==NULL)
396     return NULL;
397   if ((x11->gc=GetGC(x11->disp,x11->font))==NULL)
398     return NULL;
399
400   x11->root=DefaultRootWindow(x11->disp);
401   x11->screen=DefaultScreen(x11->disp);
402   x11->depth=DefaultDepth(x11->disp,x11->screen);
403   x11->cmap=DefaultColormap(x11->disp,x11->screen);
404
405   /* These colours will be mapped to black on a monochrome screen */
406   x11->fg=BLACK=BLUE=GREEN=CYAN=RED=BROWN=GREY=DARKGREY=
407     BlackPixel(x11->disp,x11->screen);
408
409   /* These colours will be mapped to white on a monochrome screen */
410   x11->bg=
411     LIGHTBLUE=LIGHTGREY=LIGHTGREEN=LIGHTCYAN=LIGHTRED=VIOLET=YELLOW=WHITE=
412       WhitePixel(x11->disp,x11->screen);
413
414   if (x11->depth > 1) {
415     /* Not B & W, Look what kind of screen we've got... */
416     for (i=0; (i < NCLASS); i++)
417       if (!XMatchVisualInfo(x11->disp,x11->screen,x11->depth,
418                             v_class[i],&v_info))
419         break;
420     if ((i==4) || (i==5)) 
421       fprintf(x11->console,"Greyscale screen, using B & W only\n");
422     else {
423       /* We have real color! */
424       fprintf(x11->console,"%s screen with depth %d.\n",
425              (i==NCLASS)?"Unknown":v_name[i],x11->depth);
426       GetNamedColor(x11,"midnight blue",&BLUE);
427       GetNamedColor(x11,"DarkGreen",&GREEN);
428       GetNamedColor(x11,"SeaGreen",&CYAN);
429       GetNamedColor(x11,"red4",&RED);
430       GetNamedColor(x11,"Gray",&GREY);
431       GetNamedColor(x11,"Gray",&DARKGREY);
432       GetNamedColor(x11,"LightGray",&LIGHTGREY);
433       GetNamedColor(x11,"green",&LIGHTGREEN);
434       GetNamedColor(x11,"cyan",&LIGHTCYAN);
435       GetNamedColor(x11,"tomato1",&LIGHTRED);
436       GetNamedColor(x11,"violet",&VIOLET);
437       GetNamedColor(x11,"yellow",&YELLOW);
438       GetNamedColor(x11,"brown",&BROWN);
439       GetNamedColor(x11,"CornFlowerBlue",&LIGHTBLUE);
440     }
441   }
442   else
443     fprintf(x11->console,"Monochrome screen.\n");
444
445   /* We should use Xrm here... */
446   if (FG)
447     GetNamedColor(x11,FG,&(x11->fg));
448   else
449     x11->fg=BLACK;
450   if (BG)
451     GetNamedColor(x11,BG,&(x11->bg));
452   else
453     x11->bg=LIGHTGREY;
454   x11->title=strdup(title);
455   sfree(title);
456   x11->wlist=NULL;
457   x11->GetNamedColor=&GetNamedColor;
458   x11->MainLoop=&MainLoop;
459   x11->RegisterCallback=&RegisterCallback;
460   x11->UnRegisterCallback=&UnRegisterCallback;
461   x11->SetInputMask=&SetInputMask;
462   x11->GetInputMask=&GetInputMask;
463   x11->CleanUp=&CleanUp;
464   x11->Flush=&Flush;
465
466   x11->Flush(x11);
467
468   return x11;
469 }
470