Merge branch release-5-1
[gromacs/AngularHB.git] / src / programs / view / x11.cpp
blob478bb5c9853fb2e7ad4d3b8effb490a5067e5049
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2013, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gmxpre.h"
39 #include "x11.h"
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
45 #include "gromacs/utility/cstringutil.h"
46 #include "gromacs/utility/smalloc.h"
48 #include "Xstuff.h"
50 /* These colours will be mapped to black on a monochrome screen */
51 unsigned long BLACK, BLUE, GREEN, CYAN, RED, BROWN, GREY, DARKGREY;
53 /* These colours will be mapped to white on a monochrome screen */
54 unsigned long LIGHTBLUE, LIGHTGREEN, LIGHTGREY, LIGHTCYAN, LIGHTRED, VIOLET, YELLOW, WHITE;
56 static XFontStruct *XLQF(FILE gmx_unused *err, Display *disp, const char *name)
58 XFontStruct *font = XLoadQueryFont(disp, name);
59 #ifdef DEBUG
60 if (font != NULL)
62 std::fprintf(err, "Loaded font %s\n", name);
64 #endif
65 return font;
68 static XFontStruct *GetFont(FILE *err, Display *disp, char *name)
70 static const char *fontnames[] = {
71 "sansb12", "8x13bold", "8x13",
72 "9x15", "6x13", "fixed"
74 #define MAXNAMES (sizeof(fontnames)/sizeof(fontnames[0]))
75 unsigned int i;
76 XFontStruct *font;
77 int count;
78 char **fontlist;
79 bool bFont = false;
81 if (name)
83 bFont = ((font = XLQF(err, disp, name)) != NULL);
85 else
87 font = NULL;
90 for (i = 0; (!bFont && (i < MAXNAMES)); i++)
92 bFont = ((font = XLQF(err, disp, fontnames[i])) != NULL);
95 if (!bFont)
97 fontlist = XListFonts(disp, "?", 1, &count);
98 if (count != 0)
100 bFont = ((font = XLQF(err, disp, fontlist[0])) != NULL);
103 if (!bFont)
105 fprintf (err, "Cannot load any suitable font\n");
107 return font;
110 static GC GetGC(Display *disp, XFontStruct *font)
112 XGCValues values;
114 values.font = font->fid;
115 values.foreground = WhitePixel(disp, DefaultScreen(disp));
117 return XCreateGC(disp, DefaultRootWindow(disp), GCForeground|GCFont, &values);
120 void GetNamedColor(t_x11 *x11, const char *name, unsigned long *col)
122 /* If name is found than col set to that colour else col is unchanged */
123 XColor exact, clr;
125 if (XAllocNamedColor(x11->disp, x11->cmap, name, &clr, &exact))
127 *col = clr.pixel;
129 else
131 std::fprintf(x11->console, "No colour %s\n", name);
135 static t_wlist *GetWList(t_x11 *x11, Window w)
137 t_wlist *curs;
139 curs = x11->wlist;
140 while (curs && (curs->w != w))
142 curs = curs->next;
145 return curs;
148 static void MainLoop(t_x11 *x11)
150 bool bReturn;
151 XEvent event;
152 t_wlist *curs;
153 Window w;
155 for (bReturn = false; (!bReturn); )
157 if (x11->wlist)
159 XNextEvent(x11->disp, &event);
160 w = event.xany.window;
161 curs = GetWList(x11, w);
162 if (!curs)
164 bReturn = true;
166 if (!bReturn)
168 switch (event.type)
170 case Expose:
171 /* Filter out expose events with non-zero count field */
172 if (event.xexpose.count != 0)
174 curs = NULL;
176 break;
177 case ConfigureNotify:
178 /* Check if more are coming...
179 if (XCheckTypedWindowEvent(x11->disp,w,ConfigureNotify,&config))
180 curs=NULL; */
181 break;
182 default:
183 break;
185 if (curs)
187 bReturn = (*curs->cb)(x11, &event, w, curs->data);
194 static void RegisterCallback(t_x11 *x11, Window w, Window Parent,
195 CallBack cb, void *data)
197 t_wlist *curs, *item;
199 snew(item, 1);
200 item->w = w;
201 item->Parent = Parent;
202 item->cb = cb;
203 item->mask = 0;
204 item->data = data;
205 item->next = NULL;
207 if (x11->wlist)
209 curs = x11->wlist;
210 while (curs->next)
212 curs = curs->next;
214 curs->next = item;
216 else
218 x11->wlist = item;
222 static void UnRegisterCallback(t_x11 *x11, Window w)
224 t_wlist *curs;
226 curs = x11->wlist;
227 if (curs)
229 if (curs->w == w)
231 x11->wlist = curs->next;
232 sfree(curs);
234 else
236 while (curs->next && (curs->next->w != w))
238 curs = curs->next;
240 if (curs->next)
242 t_wlist *tmp = curs->next;
244 curs->next = curs->next->next;
245 sfree(tmp);
251 static void SetInputMask(t_x11 *x11, Window w, unsigned long mask)
253 t_wlist *curs;
255 curs = GetWList(x11, w);
256 if (curs)
258 curs->mask = mask;
259 XSelectInput(x11->disp, w, (long)mask);
261 else
263 std::fprintf(x11->console, "No such window (%d)\n", (int)w);
267 static unsigned long GetInputMask(t_x11 *x11, Window w)
269 t_wlist *curs;
271 curs = GetWList(x11, w);
272 if (curs)
274 return curs->mask;
276 else
278 return 0;
282 static void CleanUp(t_x11 *x11)
284 t_wlist *curs;
286 curs = x11->wlist;
287 while (curs)
289 x11->wlist = curs->next;
290 XDestroyWindow(x11->disp, curs->w);
291 sfree(curs);
292 curs = x11->wlist;
294 XCloseDisplay(x11->disp);
297 static void Flush(t_x11 *x11)
299 std::fflush(x11->console);
302 t_x11 *GetX11(int *argc, char *argv[])
304 static const char *v_name[] = {
305 "DirectColor", "TrueColor", "PseudoColor",
306 "StaticColor", "GrayScale", "StaticGray"
308 static int v_class[] = {
309 DirectColor, TrueColor, PseudoColor,
310 StaticColor, GrayScale, StaticGray
312 #define NCLASS (sizeof(v_class)/sizeof(v_class[0]))
314 XVisualInfo v_info;
315 t_x11 *x11;
316 int ARGC;
317 char **ARGV;
318 char *display;
319 char *fontname;
320 char *title, *FG = NULL, *BG = NULL;
321 bool bVerbose = false;
322 int i;
324 title = gmx_strdup(argv[0]);
326 /* First check environment */
327 fontname = std::getenv("GMX_FONT");
328 display = std::getenv("DISPLAY");
330 snew(ARGV, *argc);
331 ARGC = 1;
332 for (i = 1; (i < *argc); i++)
334 if (argv[i][0] == '-')
336 if (strlen(argv[i]) > 1)
338 if ((*argc) > i+1)
340 switch (argv[i][1])
342 case 'b':
343 BG = argv[++i];
344 break;
345 case 'd':
346 display = argv[++i];
347 break;
348 case 'f':
349 switch (argv[i][2])
351 case 'o':
352 fontname = argv[++i];
353 break;
354 case 'g':
355 FG = argv[++i];
356 break;
358 break;
359 case 't':
360 sfree(title);
361 title = gmx_strdup(argv[++i]);
362 break;
363 case 'v':
364 bVerbose = true;
365 break;
366 default:
367 ARGV[ARGC++] = argv[i];
368 break;
373 else
375 ARGV[ARGC++] = argv[i];
378 for (i = 1; (i < ARGC); i++)
380 argv[i] = ARGV[i];
382 *argc = ARGC;
383 argv[ARGC] = NULL;
385 snew(x11, 1);
386 x11->dispname = display;
387 if (bVerbose)
389 x11->console = stderr;
391 else
392 if ((x11->console = std::fopen("/dev/null", "w")) == NULL)
394 x11->console = stderr;
397 if ((x11->disp = XOpenDisplay(display)) == NULL)
399 if (bVerbose)
401 std::fprintf(x11->console, "Display %s invalid\n", display);
403 return NULL;
406 if ((x11->font = GetFont(x11->console, x11->disp, fontname)) == NULL)
408 return NULL;
410 if ((x11->gc = GetGC(x11->disp, x11->font)) == NULL)
412 return NULL;
415 x11->root = DefaultRootWindow(x11->disp);
416 x11->screen = DefaultScreen(x11->disp);
417 x11->depth = DefaultDepth(x11->disp, x11->screen);
418 x11->cmap = DefaultColormap(x11->disp, x11->screen);
420 /* These colours will be mapped to black on a monochrome screen */
421 x11->fg = BLACK = BLUE = GREEN = CYAN = RED = BROWN = GREY = DARKGREY =
422 BlackPixel(x11->disp, x11->screen);
424 /* These colours will be mapped to white on a monochrome screen */
425 x11->bg =
426 LIGHTBLUE = LIGHTGREY = LIGHTGREEN = LIGHTCYAN = LIGHTRED = VIOLET = YELLOW = WHITE =
427 WhitePixel(x11->disp, x11->screen);
429 if (x11->depth > 1)
431 /* Not B & W, Look what kind of screen we've got... */
432 for (i = 0; (i < (int)NCLASS); i++)
434 if (!XMatchVisualInfo(x11->disp, x11->screen, x11->depth,
435 v_class[i], &v_info))
437 break;
440 if ((i == 4) || (i == 5))
442 std::fprintf(x11->console, "Greyscale screen, using B & W only\n");
444 else
446 /* We have real color! */
447 std::fprintf(x11->console, "%s screen with depth %d.\n",
448 (i == NCLASS) ? "Unknown" : v_name[i], x11->depth);
449 GetNamedColor(x11, "midnight blue", &BLUE);
450 GetNamedColor(x11, "DarkGreen", &GREEN);
451 GetNamedColor(x11, "SeaGreen", &CYAN);
452 GetNamedColor(x11, "red4", &RED);
453 GetNamedColor(x11, "Gray", &GREY);
454 GetNamedColor(x11, "Gray", &DARKGREY);
455 GetNamedColor(x11, "LightGray", &LIGHTGREY);
456 GetNamedColor(x11, "green", &LIGHTGREEN);
457 GetNamedColor(x11, "cyan", &LIGHTCYAN);
458 GetNamedColor(x11, "tomato1", &LIGHTRED);
459 GetNamedColor(x11, "violet", &VIOLET);
460 GetNamedColor(x11, "yellow", &YELLOW);
461 GetNamedColor(x11, "brown", &BROWN);
462 GetNamedColor(x11, "CornFlowerBlue", &LIGHTBLUE);
465 else
467 std::fprintf(x11->console, "Monochrome screen.\n");
470 /* We should use Xrm here... */
471 if (FG)
473 GetNamedColor(x11, FG, &(x11->fg));
475 else
477 x11->fg = BLACK;
479 if (BG)
481 GetNamedColor(x11, BG, &(x11->bg));
483 else
485 x11->bg = LIGHTGREY;
487 x11->title = gmx_strdup(title);
488 sfree(title);
489 x11->wlist = NULL;
490 x11->GetNamedColor = &GetNamedColor;
491 x11->MainLoop = &MainLoop;
492 x11->RegisterCallback = &RegisterCallback;
493 x11->UnRegisterCallback = &UnRegisterCallback;
494 x11->SetInputMask = &SetInputMask;
495 x11->GetInputMask = &GetInputMask;
496 x11->CleanUp = &CleanUp;
497 x11->Flush = &Flush;
499 x11->Flush(x11);
501 return x11;