Sort includes outside src/gromacs
[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             for (i = 0; (i < nlines); i++)
412             {
413                 sfree(lines[i]);
414             }
415             sfree(lines);
416             NoHelp(dlg);
417             return;
418         }
419         else
420         {
421             bCont = (gmx_strcasecmp(buf, "ok") != 0);
422             if (bCont)
423             {
424                 srenew(lines, ++nlines);
425                 lines[nlines-1] = gmx_strdup(buf);
426             }
427         }
428     }
429     while (bCont);
430     MessageBox(dlg->x11, dlg->wDad, "Help",
431                nlines, lines,
432                MB_OK | MB_ICONINFORMATION | MB_APPLMODAL, NULL, NULL);
433     for (i = 0; (i < nlines); i++)
434     {
435         sfree(lines[i]);
436     }
437     sfree(lines);
438 }
439
440 static void EnterDlg(t_dlg *dlg)
441 {
442     if (dlg->flags & DLG_APPLMODAL)
443     {
444         dlg->bGrab = GrabOK(dlg->x11->console,
445                             XGrabPointer(dlg->x11->disp, dlg->win.self,
446                                          True, 0, GrabModeAsync, GrabModeAsync,
447                                          dlg->win.self, None, CurrentTime));
448     }
449     dlg->x11->Flush(dlg->x11);
450 }
451
452 static void ExitDlg(t_dlg *dlg)
453 {
454     if (dlg->bGrab)
455     {
456         XUngrabPointer(dlg->x11->disp, CurrentTime);
457         dlg->bGrab = false;
458     }
459     HideDlg(dlg);
460     if (dlg->flags & DLG_FREEONBUTTON)
461     {
462         FreeDlg(dlg);
463     }
464 }
465
466 static bool DlgCB(t_x11 *x11, XEvent *event, Window w, void *data)
467 {
468     t_dlg     *dlg = (t_dlg *)data;
469     int        i, nWndProc;
470     t_dlgitem *dlgitem;
471
472     if ((dlgitem = FindWin(dlg, w)) != NULL)
473     {
474         nWndProc = (dlgitem->WndProc)(x11, dlgitem, event);
475 #ifdef DEBUG
476         fprintf(x11->console,
477                 "window: %s, nWndProc: %d\n", dlgitem->win.text, nWndProc);
478         x11->Flush(x11);
479 #endif
480         switch (nWndProc)
481         {
482             case ENTERPRESSED:
483                 if ((dlgitem->type == edlgBN) && (dlgitem->u.button.bDefault))
484                 {
485                     if (dlg->cb)
486                     {
487                         dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
488                     }
489                     else
490                     {
491                         ExitDlg(dlg);
492                     }
493                 }
494                 else
495                 {
496                     for (i = 0; (i < dlg->nitem); i++)
497                     {
498                         if ((dlg->dlgitem[i]->type == edlgBN) &&
499                             (dlg->dlgitem[i]->u.button.bDefault))
500                         {
501                             PushMouse(x11->disp, dlg->dlgitem[i]->win.self,
502                                       dlg->dlgitem[i]->win.width/2,
503                                       dlg->dlgitem[i]->win.height/2);
504                             break;
505                         }
506                     }
507                 }
508                 break;
509             case BNPRESSED:
510                 if (dlg->cb)
511                 {
512                     dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
513                 }
514                 else
515                 {
516                     ExitDlg(dlg);
517                 }
518                 break;
519             case RBPRESSED:
520             {
521                 int  gid = dlgitem->GroupID;
522                 t_id tid = RBSelected(dlg, gid);
523 #ifdef DEBUG
524                 fprintf(stderr, "RBPRESSED\n");
525 #endif
526                 if (tid != -1)
527                 {
528                     t_dlgitem *dit = FindItem(dlg, tid);
529                     dit->u.radiobutton.bSelect = false;
530                     ExposeWin(x11->disp, dit->win.self);
531                 }
532                 else
533                 {
534                     gmx_fatal(FARGS, "No RB Selected initially!\n");
535                 }
536                 dlgitem->u.radiobutton.bSelect = true;
537                 ExposeWin(x11->disp, dlgitem->win.self);
538                 if (dlg->cb)
539                 {
540                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->win.text, dlg->data);
541                 }
542                 break;
543             }
544             case CBPRESSED:
545                 ExposeWin(x11->disp, dlgitem->win.self);
546                 if (dlg->cb)
547                 {
548                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->set, dlg->data);
549                 }
550                 break;
551             case ETCHANGED:
552                 ExposeWin(x11->disp, dlgitem->win.self);
553                 if (dlg->cb)
554                 {
555                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->u.edittext.buf, dlg->data);
556                 }
557                 break;
558             case HELPPRESSED:
559                 HelpNow(dlg, dlgitem);
560                 break;
561             case ITEMOK:
562                 break;
563             default:
564                 gmx_fatal(FARGS, "Invalid return code (%d) from wndproc\n", nWndProc);
565         }
566     }
567     else if (w == dlg->win.self)
568     {
569         switch (event->type)
570         {
571             case Expose:
572                 EnterDlg(dlg);
573                 break;
574             case ButtonPress:
575             case KeyPress:
576                 if (HelpPressed(event))
577                 {
578                     HelpDlg(dlg);
579                 }
580                 else
581                 {
582                     XBell(x11->disp, 50);
583                 }
584                 break;
585             default:
586                 break;
587         }
588     }
589     return false;
590 }
591
592 /*****************************
593  *
594  * Routine to add an item to the dialog box
595  * The pointer to the item is copied to the dlg struct,
596  * the item itself may not be freed until the dlg is done with
597  *
598  ****************************/
599 void DoCreateDlg(t_dlg *dlg)
600 {
601     XSizeHints           hints;
602     XSetWindowAttributes attr;
603     unsigned long        Val;
604
605     attr.border_pixel      = dlg->x11->fg;
606     attr.background_pixel  = dlg->bg;
607     attr.override_redirect = False;
608     attr.save_under        = True;
609     attr.cursor            = XCreateFontCursor(dlg->x11->disp, XC_hand2);
610     Val                    = CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWSaveUnder |
611         CWCursor;
612     dlg->win.self = XCreateWindow(dlg->x11->disp, dlg->wDad,
613                                   dlg->win.x, dlg->win.y,
614                                   dlg->win.width, dlg->win.height,
615                                   dlg->win.bwidth, CopyFromParent,
616                                   InputOutput, CopyFromParent,
617                                   Val, &attr);
618     dlg->x11->RegisterCallback(dlg->x11, dlg->win.self, dlg->wDad,
619                                DlgCB, dlg);
620     dlg->x11->SetInputMask(dlg->x11, dlg->win.self,
621                            ExposureMask | ButtonPressMask | KeyPressMask);
622
623     if (!CheckWindow(dlg->win.self))
624     {
625         exit(1);
626     }
627     hints.x     = dlg->win.x;
628     hints.y     = dlg->win.y;
629     hints.flags = PPosition;
630     XSetStandardProperties(dlg->x11->disp, dlg->win.self, dlg->title,
631                            dlg->title, None, NULL, 0, &hints);
632 }
633
634 void AddDlgItem(t_dlg *dlg, t_dlgitem *item)
635 {
636 #define EnterLeaveMask (EnterWindowMask | LeaveWindowMask)
637 #define UserMask (ButtonPressMask | KeyPressMask)
638     static unsigned long InputMask[edlgNR] = {
639         ExposureMask | UserMask | EnterLeaveMask, /* edlgBN */
640         ExposureMask | UserMask | EnterLeaveMask, /* edlgRB */
641         ExposureMask,                             /* edlgGB */
642         ExposureMask | UserMask | EnterLeaveMask, /* edlgCB */
643         0,                                        /* edlgPM */
644         ExposureMask,                             /* edlgST */
645         ExposureMask | UserMask | EnterLeaveMask  /* edlgET */
646     };
647
648     if (!dlg->win.self)
649     {
650         DoCreateDlg(dlg);
651     }
652     srenew(dlg->dlgitem, dlg->nitem+1);
653     if (!item)
654     {
655         gmx_fatal(FARGS, "dlgitem not allocated");
656     }
657     item->win.self =
658         XCreateSimpleWindow(dlg->x11->disp, dlg->win.self, item->win.x, item->win.y,
659                             item->win.width, item->win.height,
660                             item->win.bwidth, dlg->x11->fg, dlg->x11->bg);
661     CheckWindow(item->win.self);
662
663     dlg->x11->RegisterCallback(dlg->x11, item->win.self, dlg->win.self,
664                                DlgCB, dlg);
665     dlg->x11->SetInputMask(dlg->x11, item->win.self, InputMask[item->type]);
666
667     switch (item->type)
668     {
669         case edlgPM:
670             XSetWindowBackgroundPixmap(dlg->x11->disp, item->win.self, item->u.pixmap.pm);
671             break;
672         default:
673             break;
674     }
675     dlg->dlgitem[dlg->nitem] = item;
676
677     dlg->nitem++;
678 }
679
680 void AddDlgItems(t_dlg *dlg, int nitem, t_dlgitem *item[])
681 {
682     int i;
683
684     for (i = 0; (i < nitem); i++)
685     {
686 #ifdef DEBUG
687         fprintf(dlg->x11->console,
688                 "Adding item: %d from group %d\n", item[i]->ID, item[i]->GroupID);
689         dlg->x11->Flush(dlg->x11);
690 #endif
691         AddDlgItem(dlg, item[i]);
692     }
693 }
694
695 void FreeDlgItem(t_dlg *dlg, t_id id)
696 {
697     t_dlgitem *dlgitem;
698     int        i;
699
700     if ((dlgitem = FindItem(dlg, id)) != NULL)
701     {
702         dlg->x11->UnRegisterCallback(dlg->x11, dlgitem->win.self);
703         if (dlgitem->win.self)
704         {
705             XDestroyWindow(dlg->x11->disp, dlgitem->win.self);
706         }
707         FreeWin(dlg->x11->disp, &(dlgitem->win));
708         switch (dlgitem->type)
709         {
710             case edlgBN:
711             case edlgRB:
712                 break;
713             case edlgGB:
714                 sfree(dlgitem->u.groupbox.item);
715                 break;
716             case edlgCB:
717                 break;
718             case edlgPM:
719                 XFreePixmap(dlg->x11->disp, dlgitem->u.pixmap.pm);
720                 break;
721             case edlgST:
722                 for (i = 0; (i < dlgitem->u.statictext.nlines); i++)
723                 {
724                     sfree(dlgitem->u.statictext.lines[i]);
725                 }
726                 sfree(dlgitem->u.statictext.lines);
727                 break;
728             case edlgET:
729                 sfree(dlgitem->u.edittext.buf);
730                 break;
731             default:
732                 break;
733         }
734     }
735 }
736
737 void FreeDlg(t_dlg *dlg)
738 {
739     int i;
740
741     if (dlg->dlgitem)
742     {
743         HideDlg(dlg);
744         dlg->x11->UnRegisterCallback(dlg->x11, dlg->win.self);
745         for (i = 0; (i < dlg->nitem); i++)
746         {
747             FreeDlgItem(dlg, dlg->dlgitem[i]->ID);
748             if (dlg->dlgitem[i])
749             {
750                 sfree(dlg->dlgitem[i]);
751             }
752         }
753         sfree(dlg->dlgitem);
754         if (dlg->win.self)
755         {
756             XDestroyWindow(dlg->x11->disp, dlg->win.self);
757         }
758         dlg->dlgitem = NULL;
759     }
760 }
761
762 /*****************************
763  *
764  * Routine to create the DLG structure, returns NULL on failure
765  *
766  ****************************/
767 t_dlg *CreateDlg(t_x11 *x11, Window Parent, const char *title,
768                  int x0, int y0, int w, int h, int bw,
769                  DlgCallback *cb, void *data)
770 {
771     t_dlg   *dlg;
772     int      x = 0, y = 0;
773
774     snew(dlg, 1);
775     dlg->x11  = x11;
776     dlg->cb   = cb;
777     dlg->data = data;
778     if (title)
779     {
780         dlg->title = gmx_strdup(title);
781     }
782     else
783     {
784         dlg->title = NULL;
785     }
786     if (w == 0)
787     {
788         w = 1;
789     }
790     if (h == 0)
791     {
792         h = 1;
793     }
794     if (!Parent)
795     {
796         Parent    = x11->root;
797         dlg->xmax = DisplayWidth(x11->disp, x11->screen);
798         dlg->ymax = DisplayHeight(x11->disp, x11->screen);
799     }
800     else
801     {
802         Window         root;
803         unsigned int   dum;
804
805         XGetGeometry(x11->disp, Parent, &root, &x, &y,
806                      &(dlg->xmax), &(dlg->ymax), &dum, &dum);
807 #ifdef DEBUG
808         fprintf(x11->console,
809                 "Daddy is %d x %d at %d, %d\n", dlg->xmax, dlg->ymax, x, y);
810         dlg->x11->Flush(dlg->x11);
811 #endif
812     }
813     if (x0)
814     {
815         x = x0;
816     }
817     if (y0)
818     {
819         y = y0;
820     }
821     InitWin(&(dlg->win), x, y, w, h, bw, NULL);
822     SetDlgSize(dlg, w, h, x0 || y0);
823
824     dlg->wDad    = Parent;
825     dlg->fg      = x11->fg;
826     dlg->bg      = x11->bg;
827     dlg->nitem   = 0;
828     dlg->dlgitem = NULL;
829
830     DoCreateDlg(dlg);
831     return dlg;
832 }
833
834 void SetDlgSize(t_dlg *dlg, int w, int h, bool bAutoPosition)
835 {
836     if (bAutoPosition)
837     {
838         int x, y;
839
840         x          = (dlg->xmax-w)/2;
841         y          = (dlg->ymax-h)/2;
842         dlg->win.x = x;
843         dlg->win.y = y;
844     }
845     dlg->win.width  = w;
846     dlg->win.height = h;
847
848 #ifdef DEBUG
849     fprintf(dlg->x11->console, "SetDlgSize: Dialog is %dx%d, at %d,%d\n",
850             dlg->win.width, dlg->win.height, dlg->win.x, dlg->win.y);
851     dlg->x11->Flush(dlg->x11);
852 #endif
853     if (dlg->win.self)
854     {
855         XMoveWindow(dlg->x11->disp, dlg->win.self, dlg->win.x, dlg->win.y);
856         XResizeWindow(dlg->x11->disp, dlg->win.self, w, h);
857     }
858 }