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