Fix cppcheck-1.67 warnings
[alexxy/gromacs.git] / src / programs / view / xdlg.cpp
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  * Copyright (c) 2013,2014, 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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 #include "gmxpre.h"
38
39 #include "xdlg.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "gromacs/legacyheaders/macros.h"
46 #include "gromacs/utility/cstringutil.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/utility/smalloc.h"
49
50 #include "Xstuff.h"
51 #include "xmb.h"
52 #include "xutil.h"
53 /*****************************
54  *
55  * Helpful routines
56  *
57  ****************************/
58 t_dlgitem *FindItem(t_dlg *dlg, t_id id)
59 {
60     int i;
61
62     for (i = 0; (i < dlg->nitem); i++)
63     {
64         if (dlg->dlgitem[i]->ID == id)
65         {
66             return dlg->dlgitem[i];
67         }
68     }
69     return NULL;
70 }
71
72 t_dlgitem *FindWin(t_dlg *dlg, Window win)
73 {
74     int i;
75
76     for (i = 0; (i < dlg->nitem); i++)
77     {
78         if (dlg->dlgitem[i]->win.self == win)
79         {
80             return dlg->dlgitem[i];
81         }
82     }
83     return NULL;
84 }
85
86 /*****************************
87  *
88  * Routines to manipulate items on a dialog box
89  *
90  ****************************/
91 bool QueryDlgItemSize(t_dlg *dlg, t_id id, int *w, int *h)
92 {
93     t_dlgitem *dlgitem;
94
95     if ((dlgitem = FindItem(dlg, id)) != NULL)
96     {
97         *w = dlgitem->win.width;
98         *h = dlgitem->win.height;
99         return true;
100     }
101     return false;
102 }
103
104 bool QueryDlgItemPos(t_dlg *dlg, t_id id, int *x0, int *y0)
105 {
106     t_dlgitem *dlgitem;
107
108     if ((dlgitem = FindItem(dlg, id)) != NULL)
109     {
110         *x0 = dlgitem->win.x;
111         *y0 = dlgitem->win.y;
112         return true;
113     }
114     return false;
115 }
116
117 int QueryDlgItemX(t_dlg *dlg, t_id id)
118 {
119     t_dlgitem *dlgitem;
120
121     if ((dlgitem = FindItem(dlg, id)) != NULL)
122     {
123         return dlgitem->win.x;
124     }
125     return 0;
126 }
127
128 int QueryDlgItemY(t_dlg *dlg, t_id id)
129 {
130     t_dlgitem *dlgitem;
131
132     if ((dlgitem = FindItem(dlg, id)) != NULL)
133     {
134         return dlgitem->win.y;
135     }
136     return 0;
137 }
138
139 int QueryDlgItemW(t_dlg *dlg, t_id id)
140 {
141     t_dlgitem *dlgitem;
142
143     if ((dlgitem = FindItem(dlg, id)) != NULL)
144     {
145         return dlgitem->win.width;
146     }
147     return 0;
148 }
149
150 int QueryDlgItemH(t_dlg *dlg, t_id id)
151 {
152     t_dlgitem *dlgitem;
153
154     if ((dlgitem = FindItem(dlg, id)) != NULL)
155     {
156         return dlgitem->win.height;
157     }
158     return 0;
159 }
160
161 bool SetDlgItemSize(t_dlg *dlg, t_id id, int w, int h)
162 {
163     t_dlgitem *dlgitem;
164 #ifdef DEBUG
165     int        old_w, old_h;
166 #endif
167
168     if ((dlgitem = FindItem(dlg, id)) != NULL)
169     {
170 #ifdef DEBUG
171         old_w = dlgitem->win.width;
172         old_h = dlgitem->win.height;
173 #endif
174         if (w)
175         {
176             dlgitem->win.width = w;
177         }
178         if (h)
179         {
180             dlgitem->win.height = h;
181         }
182 #ifdef DEBUG
183         fprintf(dlg->x11->console,
184                 "Size window from: %dx%d to %dx%d\n", old_w, old_h,
185                 dlgitem->win.width, dlgitem->win.height);
186         dlg->x11->Flush(dlg->x11);
187 #endif
188         if (dlgitem->win.self)
189         {
190             XResizeWindow(dlg->x11->disp, dlgitem->win.self, dlgitem->win.width,
191                           dlgitem->win.height);
192         }
193         if ((w) && (dlgitem->type == edlgGB))
194         {
195             int  i;
196             t_id gid = dlgitem->GroupID;
197             t_id id  = dlgitem->ID;
198             for (i = 0; (i < dlg->nitem); i++)
199             {
200                 t_dlgitem *child = dlg->dlgitem[i];
201                 if ((child->GroupID == gid) && (child->ID != id))
202                 {
203                     SetDlgItemSize(dlg, child->ID, w-4*OFFS_X, 0);
204                 }
205             }
206         }
207         return true;
208     }
209     return false;
210 }
211
212 bool SetDlgItemPos(t_dlg *dlg, t_id id, int x0, int y0)
213 {
214     t_dlgitem *dlgitem;
215     int        old_x, old_y;
216
217     if ((dlgitem = FindItem(dlg, id)) != NULL)
218     {
219         old_x          = dlgitem->win.x;
220         old_y          = dlgitem->win.y;
221         dlgitem->win.x = x0;
222         dlgitem->win.y = y0;
223 #ifdef DEBUG
224         fprintf(dlg->x11->console,
225                 "Move window from: %d,%d to %d,%d\n", old_x, old_y, x0, y0);
226         dlg->x11->Flush(dlg->x11);
227 #endif
228         if (dlgitem->win.self)
229         {
230             XMoveWindow(dlg->x11->disp, dlgitem->win.self, x0, y0);
231         }
232         if (dlgitem->type == edlgGB)
233         {
234             int  i, x, y;
235             t_id gid = dlgitem->GroupID;
236             t_id id  = dlgitem->ID;
237             x = dlgitem->win.x+2*OFFS_X-old_x;
238             y = dlgitem->win.y+2*OFFS_Y-old_y;
239             for (i = 0; (i < dlg->nitem); i++)
240             {
241                 t_dlgitem *child = dlg->dlgitem[i];
242                 if ((child->GroupID == gid) && (child->ID != id))
243                 {
244                     SetDlgItemPos(dlg, child->ID, child->win.x+x, child->win.y+y);
245                 }
246             }
247         }
248         return true;
249     }
250     return false;
251 }
252
253 /*****************************
254  *
255  * Routines to extract information from the dlg proc
256  * after dlg is exec'ed
257  *
258  ****************************/
259 bool IsCBChecked(t_dlg *dlg, t_id id)
260 {
261     t_dlgitem *dlgitem;
262
263     if ((dlgitem = FindItem(dlg, id)) != NULL)
264     {
265         if (dlgitem->type == edlgCB)
266         {
267             return dlgitem->u.checkbox.bChecked;
268         }
269     }
270
271     return false;
272 }
273
274 t_id RBSelected(t_dlg *dlg, int gid)
275 {
276     int i;
277
278     for (i = 0; (i < dlg->nitem); i++)
279     {
280         if ((dlg->dlgitem[i]->type == edlgRB) &&
281             (dlg->dlgitem[i]->u.radiobutton.bSelect) &&
282             (dlg->dlgitem[i]->GroupID == gid))
283         {
284             return dlg->dlgitem[i]->ID;
285         }
286     }
287
288     return -1;
289 }
290
291 int EditTextLen(t_dlg *dlg, t_id id)
292 {
293     t_dlgitem *dlgitem;
294
295     if ((dlgitem = FindItem(dlg, id)) != NULL)
296     {
297         if (dlgitem->type == edlgET)
298         {
299             return strlen(dlgitem->u.edittext.buf);
300         }
301     }
302
303     return 0;
304 }
305
306 char *EditText(t_dlg *dlg, t_id id)
307 {
308     t_dlgitem *dlgitem;
309
310     if ((dlgitem = FindItem(dlg, id)) != NULL)
311     {
312         if (dlgitem->type == edlgET)
313         {
314             return dlgitem->u.edittext.buf;
315         }
316     }
317
318     return NULL;
319 }
320
321 /*****************************
322  *
323  * Exececute the dialog box procedure
324  * Returns when a button is pushed.
325  * return value is the ID of the button
326  *
327  ****************************/
328 void ShowDlg(t_dlg *dlg)
329 {
330     int        i;
331     t_dlgitem *dlgitem;
332
333     XMapWindow(dlg->x11->disp, dlg->win.self);
334     XMapSubwindows(dlg->x11->disp, dlg->win.self);
335     for (i = 0; (i < dlg->nitem); i++)
336     {
337         LightBorder(dlg->x11->disp, dlg->dlgitem[i]->win.self, dlg->bg);
338     }
339     XSetForeground(dlg->x11->disp, dlg->x11->gc, dlg->x11->fg);
340     for (i = 0; (i < dlg->nitem); i++)
341     {
342         dlgitem = dlg->dlgitem[i];
343         if ((dlgitem->type == edlgBN) &&
344             (dlgitem->u.button.bDefault))
345         {
346             PushMouse(dlg->x11->disp, dlgitem->win.self,
347                       dlgitem->win.width/2, dlgitem->win.height/2);
348             dlg->bPop = true;
349             break;
350         }
351     }
352     dlg->bGrab = false;
353 }
354
355 void HideDlg(t_dlg *dlg)
356 {
357     if (dlg->bPop)
358     {
359         PopMouse(dlg->x11->disp);
360     }
361
362     XUnmapSubwindows(dlg->x11->disp, dlg->win.self);
363     XUnmapWindow(dlg->x11->disp, dlg->win.self);
364 }
365
366 void NoHelp(t_dlg *dlg)
367 {
368     const char *lines[2] = {
369         "Error",
370         "No help for this item"
371     };
372     MessageBox(dlg->x11, dlg->wDad, "No Help", 2, lines,
373                MB_OK | MB_ICONSTOP | MB_APPLMODAL, NULL, NULL);
374 }
375
376 void HelpDlg(t_dlg *dlg)
377 {
378     const char *lines[] = {
379         "Place the cursor over one of the items",
380         "and press the F1 key to get more help.",
381         "First press the OK button."
382     };
383     MessageBox(dlg->x11, dlg->win.self, "Help Dialogbox",
384                3, lines, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL, NULL, NULL);
385 }
386
387 void HelpNow(t_dlg *dlg, t_dlgitem *dlgitem)
388 {
389     char     buf[80];
390     bool     bCont = true;
391     int      i, nlines = 0;
392     char   **lines = NULL;
393
394     if (!dlgitem->help)
395     {
396         NoHelp(dlg);
397         return;
398     }
399
400     printf("%s\n", dlgitem->help);
401     do
402     {
403         fgets2(buf, 79, stdin);
404 #ifdef DEBUG
405         fprintf(dlg->x11->console, "buffer: '%s'\n", buf);
406         dlg->x11->Flush(dlg->x11);
407 #endif
408         if (gmx_strcasecmp(buf, "nok") == 0)
409         {
410             /* An error occurred */
411             if (lines)
412             {
413                 for (i = 0; (i < nlines); i++)
414                 {
415                     sfree(lines[i]);
416                 }
417                 sfree(lines);
418             }
419             NoHelp(dlg);
420             return;
421         }
422         else
423         {
424             bCont = (gmx_strcasecmp(buf, "ok") != 0);
425             if (bCont)
426             {
427                 srenew(lines, ++nlines);
428                 lines[nlines-1] = gmx_strdup(buf);
429             }
430         }
431     }
432     while (bCont);
433     MessageBox(dlg->x11, dlg->wDad, "Help",
434                nlines, lines,
435                MB_OK | MB_ICONINFORMATION | MB_APPLMODAL, NULL, NULL);
436     for (i = 0; (i < nlines); i++)
437     {
438         sfree(lines[i]);
439     }
440     sfree(lines);
441 }
442
443 static void EnterDlg(t_dlg *dlg)
444 {
445     if (dlg->flags & DLG_APPLMODAL)
446     {
447         dlg->bGrab = GrabOK(dlg->x11->console,
448                             XGrabPointer(dlg->x11->disp, dlg->win.self,
449                                          True, 0, GrabModeAsync, GrabModeAsync,
450                                          dlg->win.self, None, CurrentTime));
451     }
452     dlg->x11->Flush(dlg->x11);
453 }
454
455 static void ExitDlg(t_dlg *dlg)
456 {
457     if (dlg->bGrab)
458     {
459         XUngrabPointer(dlg->x11->disp, CurrentTime);
460         dlg->bGrab = false;
461     }
462     HideDlg(dlg);
463     if (dlg->flags & DLG_FREEONBUTTON)
464     {
465         FreeDlg(dlg);
466     }
467 }
468
469 static bool DlgCB(t_x11 *x11, XEvent *event, Window w, void *data)
470 {
471     t_dlg     *dlg = (t_dlg *)data;
472     int        i, nWndProc;
473     t_dlgitem *dlgitem;
474
475     if ((dlgitem = FindWin(dlg, w)) != NULL)
476     {
477         nWndProc = (dlgitem->WndProc)(x11, dlgitem, event);
478 #ifdef DEBUG
479         fprintf(x11->console,
480                 "window: %s, nWndProc: %d\n", dlgitem->win.text, nWndProc);
481         x11->Flush(x11);
482 #endif
483         switch (nWndProc)
484         {
485             case ENTERPRESSED:
486                 if ((dlgitem->type == edlgBN) && (dlgitem->u.button.bDefault))
487                 {
488                     if (dlg->cb)
489                     {
490                         dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
491                     }
492                     else
493                     {
494                         ExitDlg(dlg);
495                     }
496                 }
497                 else
498                 {
499                     for (i = 0; (i < dlg->nitem); i++)
500                     {
501                         if ((dlg->dlgitem[i]->type == edlgBN) &&
502                             (dlg->dlgitem[i]->u.button.bDefault))
503                         {
504                             PushMouse(x11->disp, dlg->dlgitem[i]->win.self,
505                                       dlg->dlgitem[i]->win.width/2,
506                                       dlg->dlgitem[i]->win.height/2);
507                             break;
508                         }
509                     }
510                 }
511                 break;
512             case BNPRESSED:
513                 if (dlg->cb)
514                 {
515                     dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
516                 }
517                 else
518                 {
519                     ExitDlg(dlg);
520                 }
521                 break;
522             case RBPRESSED:
523             {
524                 int  gid = dlgitem->GroupID;
525                 t_id tid = RBSelected(dlg, gid);
526 #ifdef DEBUG
527                 fprintf(stderr, "RBPRESSED\n");
528 #endif
529                 if (tid != -1)
530                 {
531                     t_dlgitem *dit = FindItem(dlg, tid);
532                     dit->u.radiobutton.bSelect = false;
533                     ExposeWin(x11->disp, dit->win.self);
534                 }
535                 else
536                 {
537                     gmx_fatal(FARGS, "No RB Selected initially!\n");
538                 }
539                 dlgitem->u.radiobutton.bSelect = true;
540                 ExposeWin(x11->disp, dlgitem->win.self);
541                 if (dlg->cb)
542                 {
543                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->win.text, dlg->data);
544                 }
545                 break;
546             }
547             case CBPRESSED:
548                 ExposeWin(x11->disp, dlgitem->win.self);
549                 if (dlg->cb)
550                 {
551                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->set, dlg->data);
552                 }
553                 break;
554             case ETCHANGED:
555                 ExposeWin(x11->disp, dlgitem->win.self);
556                 if (dlg->cb)
557                 {
558                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->u.edittext.buf, dlg->data);
559                 }
560                 break;
561             case HELPPRESSED:
562                 HelpNow(dlg, dlgitem);
563                 break;
564             case ITEMOK:
565                 break;
566             default:
567                 gmx_fatal(FARGS, "Invalid return code (%d) from wndproc\n", nWndProc);
568         }
569     }
570     else if (w == dlg->win.self)
571     {
572         switch (event->type)
573         {
574             case Expose:
575                 EnterDlg(dlg);
576                 break;
577             case ButtonPress:
578             case KeyPress:
579                 if (HelpPressed(event))
580                 {
581                     HelpDlg(dlg);
582                 }
583                 else
584                 {
585                     XBell(x11->disp, 50);
586                 }
587                 break;
588             default:
589                 break;
590         }
591     }
592     return false;
593 }
594
595 /*****************************
596  *
597  * Routine to add an item to the dialog box
598  * The pointer to the item is copied to the dlg struct,
599  * the item itself may not be freed until the dlg is done with
600  *
601  ****************************/
602 void DoCreateDlg(t_dlg *dlg)
603 {
604     XSizeHints           hints;
605     XSetWindowAttributes attr;
606     unsigned long        Val;
607
608     attr.border_pixel      = dlg->x11->fg;
609     attr.background_pixel  = dlg->bg;
610     attr.override_redirect = False;
611     attr.save_under        = True;
612     attr.cursor            = XCreateFontCursor(dlg->x11->disp, XC_hand2);
613     Val                    = CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWSaveUnder |
614         CWCursor;
615     dlg->win.self = XCreateWindow(dlg->x11->disp, dlg->wDad,
616                                   dlg->win.x, dlg->win.y,
617                                   dlg->win.width, dlg->win.height,
618                                   dlg->win.bwidth, CopyFromParent,
619                                   InputOutput, CopyFromParent,
620                                   Val, &attr);
621     dlg->x11->RegisterCallback(dlg->x11, dlg->win.self, dlg->wDad,
622                                DlgCB, dlg);
623     dlg->x11->SetInputMask(dlg->x11, dlg->win.self,
624                            ExposureMask | ButtonPressMask | KeyPressMask);
625
626     if (!CheckWindow(dlg->win.self))
627     {
628         exit(1);
629     }
630     hints.x     = dlg->win.x;
631     hints.y     = dlg->win.y;
632     hints.flags = PPosition;
633     XSetStandardProperties(dlg->x11->disp, dlg->win.self, dlg->title,
634                            dlg->title, None, NULL, 0, &hints);
635 }
636
637 void AddDlgItem(t_dlg *dlg, t_dlgitem *item)
638 {
639 #define EnterLeaveMask (EnterWindowMask | LeaveWindowMask)
640 #define UserMask (ButtonPressMask | KeyPressMask)
641     static unsigned long InputMask[edlgNR] = {
642         ExposureMask | UserMask | EnterLeaveMask, /* edlgBN */
643         ExposureMask | UserMask | EnterLeaveMask, /* edlgRB */
644         ExposureMask,                             /* edlgGB */
645         ExposureMask | UserMask | EnterLeaveMask, /* edlgCB */
646         0,                                        /* edlgPM */
647         ExposureMask,                             /* edlgST */
648         ExposureMask | UserMask | EnterLeaveMask  /* edlgET */
649     };
650
651     if (!dlg->win.self)
652     {
653         DoCreateDlg(dlg);
654     }
655     srenew(dlg->dlgitem, dlg->nitem+1);
656     if (!item)
657     {
658         gmx_fatal(FARGS, "dlgitem not allocated");
659     }
660     item->win.self =
661         XCreateSimpleWindow(dlg->x11->disp, dlg->win.self, item->win.x, item->win.y,
662                             item->win.width, item->win.height,
663                             item->win.bwidth, dlg->x11->fg, dlg->x11->bg);
664     CheckWindow(item->win.self);
665
666     dlg->x11->RegisterCallback(dlg->x11, item->win.self, dlg->win.self,
667                                DlgCB, dlg);
668     dlg->x11->SetInputMask(dlg->x11, item->win.self, InputMask[item->type]);
669
670     switch (item->type)
671     {
672         case edlgPM:
673             XSetWindowBackgroundPixmap(dlg->x11->disp, item->win.self, item->u.pixmap.pm);
674             break;
675         default:
676             break;
677     }
678     dlg->dlgitem[dlg->nitem] = item;
679
680     dlg->nitem++;
681 }
682
683 void AddDlgItems(t_dlg *dlg, int nitem, t_dlgitem *item[])
684 {
685     int i;
686
687     for (i = 0; (i < nitem); i++)
688     {
689 #ifdef DEBUG
690         fprintf(dlg->x11->console,
691                 "Adding item: %d from group %d\n", item[i]->ID, item[i]->GroupID);
692         dlg->x11->Flush(dlg->x11);
693 #endif
694         AddDlgItem(dlg, item[i]);
695     }
696 }
697
698 void FreeDlgItem(t_dlg *dlg, t_id id)
699 {
700     t_dlgitem *dlgitem;
701     int        i;
702
703     if ((dlgitem = FindItem(dlg, id)) != NULL)
704     {
705         dlg->x11->UnRegisterCallback(dlg->x11, dlgitem->win.self);
706         if (dlgitem->win.self)
707         {
708             XDestroyWindow(dlg->x11->disp, dlgitem->win.self);
709         }
710         FreeWin(dlg->x11->disp, &(dlgitem->win));
711         switch (dlgitem->type)
712         {
713             case edlgBN:
714             case edlgRB:
715                 break;
716             case edlgGB:
717                 sfree(dlgitem->u.groupbox.item);
718                 break;
719             case edlgCB:
720                 break;
721             case edlgPM:
722                 XFreePixmap(dlg->x11->disp, dlgitem->u.pixmap.pm);
723                 break;
724             case edlgST:
725                 for (i = 0; (i < dlgitem->u.statictext.nlines); i++)
726                 {
727                     sfree(dlgitem->u.statictext.lines[i]);
728                 }
729                 sfree(dlgitem->u.statictext.lines);
730                 break;
731             case edlgET:
732                 sfree(dlgitem->u.edittext.buf);
733                 break;
734             default:
735                 break;
736         }
737     }
738 }
739
740 void FreeDlg(t_dlg *dlg)
741 {
742     int i;
743
744     if (dlg->dlgitem)
745     {
746         HideDlg(dlg);
747         dlg->x11->UnRegisterCallback(dlg->x11, dlg->win.self);
748         for (i = 0; (i < dlg->nitem); i++)
749         {
750             FreeDlgItem(dlg, dlg->dlgitem[i]->ID);
751             if (dlg->dlgitem[i])
752             {
753                 sfree(dlg->dlgitem[i]);
754             }
755         }
756         sfree(dlg->dlgitem);
757         if (dlg->win.self)
758         {
759             XDestroyWindow(dlg->x11->disp, dlg->win.self);
760         }
761         dlg->dlgitem = NULL;
762     }
763 }
764
765 /*****************************
766  *
767  * Routine to create the DLG structure, returns NULL on failure
768  *
769  ****************************/
770 t_dlg *CreateDlg(t_x11 *x11, Window Parent, const char *title,
771                  int x0, int y0, int w, int h, int bw,
772                  DlgCallback *cb, void *data)
773 {
774     t_dlg   *dlg;
775     int      x = 0, y = 0;
776
777     snew(dlg, 1);
778     dlg->x11  = x11;
779     dlg->cb   = cb;
780     dlg->data = data;
781     if (title)
782     {
783         dlg->title = gmx_strdup(title);
784     }
785     else
786     {
787         dlg->title = NULL;
788     }
789     if (w == 0)
790     {
791         w = 1;
792     }
793     if (h == 0)
794     {
795         h = 1;
796     }
797     if (!Parent)
798     {
799         Parent    = x11->root;
800         dlg->xmax = DisplayWidth(x11->disp, x11->screen);
801         dlg->ymax = DisplayHeight(x11->disp, x11->screen);
802     }
803     else
804     {
805         Window         root;
806         unsigned int   dum;
807
808         XGetGeometry(x11->disp, Parent, &root, &x, &y,
809                      &(dlg->xmax), &(dlg->ymax), &dum, &dum);
810 #ifdef DEBUG
811         fprintf(x11->console,
812                 "Daddy is %d x %d at %d, %d\n", dlg->xmax, dlg->ymax, x, y);
813         dlg->x11->Flush(dlg->x11);
814 #endif
815     }
816     if (x0)
817     {
818         x = x0;
819     }
820     if (y0)
821     {
822         y = y0;
823     }
824     InitWin(&(dlg->win), x, y, w, h, bw, NULL);
825     SetDlgSize(dlg, w, h, x0 || y0);
826
827     dlg->wDad    = Parent;
828     dlg->fg      = x11->fg;
829     dlg->bg      = x11->bg;
830     dlg->nitem   = 0;
831     dlg->dlgitem = NULL;
832
833     DoCreateDlg(dlg);
834     return dlg;
835 }
836
837 void SetDlgSize(t_dlg *dlg, int w, int h, bool bAutoPosition)
838 {
839     if (bAutoPosition)
840     {
841         int x, y;
842
843         x          = (dlg->xmax-w)/2;
844         y          = (dlg->ymax-h)/2;
845         dlg->win.x = x;
846         dlg->win.y = y;
847     }
848     dlg->win.width  = w;
849     dlg->win.height = h;
850
851 #ifdef DEBUG
852     fprintf(dlg->x11->console, "SetDlgSize: Dialog is %dx%d, at %d,%d\n",
853             dlg->win.width, dlg->win.height, dlg->win.x, dlg->win.y);
854     dlg->x11->Flush(dlg->x11);
855 #endif
856     if (dlg->win.self)
857     {
858         XMoveWindow(dlg->x11->disp, dlg->win.self, dlg->win.x, dlg->win.y);
859         XResizeWindow(dlg->x11->disp, dlg->win.self, w, h);
860     }
861 }