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