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