SYCL: Avoid using no_init read accessor in rocFFT
[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,2015,2017,2019,2020, 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 <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44
45 #include "gromacs/utility/cstringutil.h"
46 #include "gromacs/utility/fatalerror.h"
47 #include "gromacs/utility/smalloc.h"
48
49 #include "Xstuff.h"
50 #include "xmb.h"
51 #include "xutil.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 nullptr;
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 nullptr;
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)) != nullptr)
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)) != nullptr)
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)) != nullptr)
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)) != nullptr)
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)) != nullptr)
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)) != nullptr)
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)) != nullptr)
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         std::fprintf(dlg->x11->console,
183                      "Size window from: %dx%d to %dx%d\n",
184                      old_w,
185                      old_h,
186                      dlgitem->win.width,
187                      dlgitem->win.height);
188         dlg->x11->Flush(dlg->x11);
189 #endif
190         if (dlgitem->win.self)
191         {
192             XResizeWindow(dlg->x11->disp, dlgitem->win.self, dlgitem->win.width, dlgitem->win.height);
193         }
194         if ((w) && (dlgitem->type == edlgGB))
195         {
196             int  i;
197             t_id gid = dlgitem->GroupID;
198             t_id id  = dlgitem->ID;
199             for (i = 0; (i < dlg->nitem); i++)
200             {
201                 t_dlgitem* child = dlg->dlgitem[i];
202                 if ((child->GroupID == gid) && (child->ID != id))
203                 {
204                     SetDlgItemSize(dlg, child->ID, w - 4 * OFFS_X, 0);
205                 }
206             }
207         }
208         return true;
209     }
210     return false;
211 }
212
213 bool SetDlgItemPos(t_dlg* dlg, t_id id, int x0, int y0)
214 {
215     t_dlgitem* dlgitem;
216     int        old_x, old_y;
217
218     if ((dlgitem = FindItem(dlg, id)) != nullptr)
219     {
220         old_x          = dlgitem->win.x;
221         old_y          = dlgitem->win.y;
222         dlgitem->win.x = x0;
223         dlgitem->win.y = y0;
224 #ifdef DEBUG
225         std::fprintf(dlg->x11->console, "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)) != nullptr)
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) && (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)) != nullptr)
295     {
296         if (dlgitem->type == edlgET)
297         {
298             return std::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)) != nullptr)
310     {
311         if (dlgitem->type == edlgET)
312         {
313             return dlgitem->u.edittext.buf;
314         }
315     }
316
317     return nullptr;
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) && (dlgitem->u.button.bDefault))
343         {
344             PushMouse(dlg->x11->disp, dlgitem->win.self, 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] = { "Error", "No help for this item" };
366     MessageBox(dlg->x11, dlg->wDad, "No Help", 2, lines, MB_OK | MB_ICONSTOP | MB_APPLMODAL, nullptr, nullptr);
367 }
368
369 void HelpDlg(t_dlg* dlg)
370 {
371     const char* lines[] = { "Place the cursor over one of the items",
372                             "and press the F1 key to get more help.",
373                             "First press the OK button." };
374     MessageBox(dlg->x11, dlg->win.self, "Help Dialogbox", 3, lines, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL, nullptr, nullptr);
375 }
376
377 void HelpNow(t_dlg* dlg, t_dlgitem* dlgitem)
378 {
379     char   buf[80];
380     bool   bCont = true;
381     int    i, nlines = 0;
382     char** lines = nullptr;
383
384     if (!dlgitem->help)
385     {
386         NoHelp(dlg);
387         return;
388     }
389
390     std::printf("%s\n", dlgitem->help);
391     do
392     {
393         fgets2(buf, 79, stdin);
394 #ifdef DEBUG
395         std::fprintf(dlg->x11->console, "buffer: '%s'\n", buf);
396         dlg->x11->Flush(dlg->x11);
397 #endif
398         if (gmx_strcasecmp(buf, "nok") == 0)
399         {
400             /* An error occurred */
401             if (lines)
402             {
403                 for (i = 0; (i < nlines); i++)
404                 {
405                     sfree(lines[i]);
406                 }
407                 sfree(lines);
408             }
409             NoHelp(dlg);
410             return;
411         }
412         else
413         {
414             bCont = (gmx_strcasecmp(buf, "ok") != 0);
415             if (bCont)
416             {
417                 srenew(lines, ++nlines);
418                 lines[nlines - 1] = gmx_strdup(buf);
419             }
420         }
421     } while (bCont);
422     MessageBox(dlg->x11, dlg->wDad, "Help", nlines, lines, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL, nullptr, nullptr);
423     for (i = 0; (i < nlines); i++)
424     {
425         sfree(lines[i]);
426     }
427     sfree(lines);
428 }
429
430 static void EnterDlg(t_dlg* dlg)
431 {
432     if (dlg->flags & DLG_APPLMODAL)
433     {
434         dlg->bGrab = GrabOK(
435                 dlg->x11->console,
436                 XGrabPointer(
437                         dlg->x11->disp, dlg->win.self, True, 0, GrabModeAsync, GrabModeAsync, dlg->win.self, None, CurrentTime));
438     }
439     dlg->x11->Flush(dlg->x11);
440 }
441
442 static void ExitDlg(t_dlg* dlg)
443 {
444     if (dlg->bGrab)
445     {
446         XUngrabPointer(dlg->x11->disp, CurrentTime);
447         dlg->bGrab = false;
448     }
449     HideDlg(dlg);
450     if (dlg->flags & DLG_FREEONBUTTON)
451     {
452         FreeDlg(dlg);
453     }
454 }
455
456 static bool DlgCB(t_x11* x11, XEvent* event, Window w, void* data)
457 {
458     t_dlg*     dlg = (t_dlg*)data;
459     int        i, nWndProc;
460     t_dlgitem* dlgitem;
461
462     if ((dlgitem = FindWin(dlg, w)) != nullptr)
463     {
464         nWndProc = (dlgitem->WndProc)(x11, dlgitem, event);
465 #ifdef DEBUG
466         std::fprintf(x11->console, "window: %s, nWndProc: %d\n", dlgitem->win.text, nWndProc);
467         x11->Flush(x11);
468 #endif
469         switch (nWndProc)
470         {
471             case ENTERPRESSED:
472                 if ((dlgitem->type == edlgBN) && (dlgitem->u.button.bDefault))
473                 {
474                     if (dlg->cb)
475                     {
476                         dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
477                     }
478                     else
479                     {
480                         ExitDlg(dlg);
481                     }
482                 }
483                 else
484                 {
485                     for (i = 0; (i < dlg->nitem); i++)
486                     {
487                         if ((dlg->dlgitem[i]->type == edlgBN) && (dlg->dlgitem[i]->u.button.bDefault))
488                         {
489                             PushMouse(x11->disp,
490                                       dlg->dlgitem[i]->win.self,
491                                       dlg->dlgitem[i]->win.width / 2,
492                                       dlg->dlgitem[i]->win.height / 2);
493                             break;
494                         }
495                     }
496                 }
497                 break;
498             case BNPRESSED:
499                 if (dlg->cb)
500                 {
501                     dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
502                 }
503                 else
504                 {
505                     ExitDlg(dlg);
506                 }
507                 break;
508             case RBPRESSED:
509             {
510                 int  gid = dlgitem->GroupID;
511                 t_id tid = RBSelected(dlg, gid);
512 #ifdef DEBUG
513                 std::fprintf(stderr, "RBPRESSED\n");
514 #endif
515                 if (tid != -1)
516                 {
517                     t_dlgitem* dit             = FindItem(dlg, tid);
518                     dit->u.radiobutton.bSelect = false;
519                     ExposeWin(x11->disp, dit->win.self);
520                 }
521                 else
522                 {
523                     gmx_fatal(FARGS, "No RB Selected initially!\n");
524                 }
525                 dlgitem->u.radiobutton.bSelect = true;
526                 ExposeWin(x11->disp, dlgitem->win.self);
527                 if (dlg->cb)
528                 {
529                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->win.text, dlg->data);
530                 }
531                 break;
532             }
533             case CBPRESSED:
534                 ExposeWin(x11->disp, dlgitem->win.self);
535                 if (dlg->cb)
536                 {
537                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->set, dlg->data);
538                 }
539                 break;
540             case ETCHANGED:
541                 ExposeWin(x11->disp, dlgitem->win.self);
542                 if (dlg->cb)
543                 {
544                     dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->u.edittext.buf, dlg->data);
545                 }
546                 break;
547             case HELPPRESSED: HelpNow(dlg, dlgitem); break;
548             case ITEMOK: break;
549             default: gmx_fatal(FARGS, "Invalid return code (%d) from wndproc\n", nWndProc);
550         }
551     }
552     else if (w == dlg->win.self)
553     {
554         switch (event->type)
555         {
556             case Expose: EnterDlg(dlg); break;
557             case ButtonPress:
558             case KeyPress:
559                 if (HelpPressed(event))
560                 {
561                     HelpDlg(dlg);
562                 }
563                 else
564                 {
565                     XBell(x11->disp, 50);
566                 }
567                 break;
568             default: break;
569         }
570     }
571     return false;
572 }
573
574 /*****************************
575  *
576  * Routine to add an item to the dialog box
577  * The pointer to the item is copied to the dlg struct,
578  * the item itself may not be freed until the dlg is done with
579  *
580  ****************************/
581 static void DoCreateDlg(t_dlg* dlg)
582 {
583     XSizeHints           hints;
584     XSetWindowAttributes attr;
585     unsigned long        Val;
586
587     attr.border_pixel      = dlg->x11->fg;
588     attr.background_pixel  = dlg->bg;
589     attr.override_redirect = False;
590     attr.save_under        = True;
591     attr.cursor            = XCreateFontCursor(dlg->x11->disp, XC_hand2);
592     Val           = CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWSaveUnder | CWCursor;
593     dlg->win.self = XCreateWindow(dlg->x11->disp,
594                                   dlg->wDad,
595                                   dlg->win.x,
596                                   dlg->win.y,
597                                   dlg->win.width,
598                                   dlg->win.height,
599                                   dlg->win.bwidth,
600                                   CopyFromParent,
601                                   InputOutput,
602                                   CopyFromParent,
603                                   Val,
604                                   &attr);
605     dlg->x11->RegisterCallback(dlg->x11, dlg->win.self, dlg->wDad, DlgCB, dlg);
606     dlg->x11->SetInputMask(dlg->x11, dlg->win.self, ExposureMask | ButtonPressMask | KeyPressMask);
607
608     if (!CheckWindow(dlg->win.self))
609     {
610         std::exit(1);
611     }
612     hints.x     = dlg->win.x;
613     hints.y     = dlg->win.y;
614     hints.flags = PPosition;
615     XSetStandardProperties(dlg->x11->disp, dlg->win.self, dlg->title, dlg->title, None, nullptr, 0, &hints);
616 }
617
618 void AddDlgItem(t_dlg* dlg, t_dlgitem* item)
619 {
620 #define EnterLeaveMask (EnterWindowMask | LeaveWindowMask)
621 #define UserMask (ButtonPressMask | KeyPressMask)
622     static unsigned long InputMask[edlgNR] = {
623         ExposureMask | UserMask | EnterLeaveMask, /* edlgBN */
624         ExposureMask | UserMask | EnterLeaveMask, /* edlgRB */
625         ExposureMask,                             /* edlgGB */
626         ExposureMask | UserMask | EnterLeaveMask, /* edlgCB */
627         0,                                        /* edlgPM */
628         ExposureMask,                             /* edlgST */
629         ExposureMask | UserMask | EnterLeaveMask  /* edlgET */
630     };
631
632     if (!dlg->win.self)
633     {
634         DoCreateDlg(dlg);
635     }
636     srenew(dlg->dlgitem, dlg->nitem + 1);
637     if (!item)
638     {
639         gmx_fatal(FARGS, "dlgitem not allocated");
640     }
641     item->win.self = XCreateSimpleWindow(dlg->x11->disp,
642                                          dlg->win.self,
643                                          item->win.x,
644                                          item->win.y,
645                                          item->win.width,
646                                          item->win.height,
647                                          item->win.bwidth,
648                                          dlg->x11->fg,
649                                          dlg->x11->bg);
650     CheckWindow(item->win.self);
651
652     dlg->x11->RegisterCallback(dlg->x11, item->win.self, dlg->win.self, DlgCB, dlg);
653     dlg->x11->SetInputMask(dlg->x11, item->win.self, InputMask[item->type]);
654
655     switch (item->type)
656     {
657         case edlgPM:
658             XSetWindowBackgroundPixmap(dlg->x11->disp, item->win.self, item->u.pixmap.pm);
659             break;
660         default: break;
661     }
662     dlg->dlgitem[dlg->nitem] = item;
663
664     dlg->nitem++;
665 }
666
667 void AddDlgItems(t_dlg* dlg, int nitem, t_dlgitem* item[])
668 {
669     int i;
670
671     for (i = 0; (i < nitem); i++)
672     {
673 #ifdef DEBUG
674         std::fprintf(dlg->x11->console, "Adding item: %d from group %d\n", item[i]->ID, item[i]->GroupID);
675         dlg->x11->Flush(dlg->x11);
676 #endif
677         AddDlgItem(dlg, item[i]);
678     }
679 }
680
681 void FreeDlgItem(t_dlg* dlg, t_id id)
682 {
683     t_dlgitem* dlgitem;
684     int        i;
685
686     if ((dlgitem = FindItem(dlg, id)) != nullptr)
687     {
688         dlg->x11->UnRegisterCallback(dlg->x11, dlgitem->win.self);
689         if (dlgitem->win.self)
690         {
691             XDestroyWindow(dlg->x11->disp, dlgitem->win.self);
692         }
693         FreeWin(dlg->x11->disp, &(dlgitem->win));
694         switch (dlgitem->type)
695         {
696             case edlgBN:
697             case edlgRB: break;
698             case edlgGB: sfree(dlgitem->u.groupbox.item); break;
699             case edlgCB: break;
700             case edlgPM: XFreePixmap(dlg->x11->disp, dlgitem->u.pixmap.pm); break;
701             case edlgST:
702                 for (i = 0; (i < dlgitem->u.statictext.nlines); i++)
703                 {
704                     sfree(dlgitem->u.statictext.lines[i]);
705                 }
706                 sfree(dlgitem->u.statictext.lines);
707                 break;
708             case edlgET: sfree(dlgitem->u.edittext.buf); break;
709             default: break;
710         }
711     }
712 }
713
714 void FreeDlg(t_dlg* dlg)
715 {
716     int i;
717
718     if (dlg->dlgitem)
719     {
720         HideDlg(dlg);
721         dlg->x11->UnRegisterCallback(dlg->x11, dlg->win.self);
722         for (i = 0; (i < dlg->nitem); i++)
723         {
724             FreeDlgItem(dlg, dlg->dlgitem[i]->ID);
725             if (dlg->dlgitem[i])
726             {
727                 sfree(dlg->dlgitem[i]);
728             }
729         }
730         sfree(dlg->dlgitem);
731         if (dlg->win.self)
732         {
733             XDestroyWindow(dlg->x11->disp, dlg->win.self);
734         }
735         dlg->dlgitem = nullptr;
736     }
737 }
738
739 /*****************************
740  *
741  * Routine to create the DLG structure, returns NULL on failure
742  *
743  ****************************/
744 t_dlg* CreateDlg(t_x11* x11, Window Parent, const char* title, int x0, int y0, int w, int h, int bw, DlgCallback* cb, void* data)
745 {
746     t_dlg* dlg;
747     int    x = 0, y = 0;
748
749     snew(dlg, 1);
750     dlg->x11  = x11;
751     dlg->cb   = cb;
752     dlg->data = data;
753     if (title)
754     {
755         dlg->title = gmx_strdup(title);
756     }
757     else
758     {
759         dlg->title = nullptr;
760     }
761     if (w == 0)
762     {
763         w = 1;
764     }
765     if (h == 0)
766     {
767         h = 1;
768     }
769     if (!Parent)
770     {
771         Parent    = x11->root;
772         dlg->xmax = DisplayWidth(x11->disp, x11->screen);
773         dlg->ymax = DisplayHeight(x11->disp, x11->screen);
774     }
775     else
776     {
777         Window       root;
778         unsigned int dum;
779
780         XGetGeometry(x11->disp, Parent, &root, &x, &y, &(dlg->xmax), &(dlg->ymax), &dum, &dum);
781 #ifdef DEBUG
782         std::fprintf(x11->console, "Daddy is %d x %d at %d, %d\n", dlg->xmax, dlg->ymax, x, y);
783         dlg->x11->Flush(dlg->x11);
784 #endif
785     }
786     if (x0)
787     {
788         x = x0;
789     }
790     if (y0)
791     {
792         y = y0;
793     }
794     InitWin(&(dlg->win), x, y, w, h, bw, nullptr);
795     SetDlgSize(dlg, w, h, x0 || y0);
796
797     dlg->wDad    = Parent;
798     dlg->fg      = x11->fg;
799     dlg->bg      = x11->bg;
800     dlg->nitem   = 0;
801     dlg->dlgitem = nullptr;
802
803     DoCreateDlg(dlg);
804     return dlg;
805 }
806
807 void SetDlgSize(t_dlg* dlg, int w, int h, bool bAutoPosition)
808 {
809     if (bAutoPosition)
810     {
811         int x, y;
812
813         x          = (dlg->xmax - w) / 2;
814         y          = (dlg->ymax - h) / 2;
815         dlg->win.x = x;
816         dlg->win.y = y;
817     }
818     dlg->win.width  = w;
819     dlg->win.height = h;
820
821 #ifdef DEBUG
822     std::fprintf(dlg->x11->console,
823                  "SetDlgSize: Dialog is %dx%d, at %d,%d\n",
824                  dlg->win.width,
825                  dlg->win.height,
826                  dlg->win.x,
827                  dlg->win.y);
828     dlg->x11->Flush(dlg->x11);
829 #endif
830     if (dlg->win.self)
831     {
832         XMoveWindow(dlg->x11->disp, dlg->win.self, dlg->win.x, dlg->win.y);
833         XResizeWindow(dlg->x11->disp, dlg->win.self, w, h);
834     }
835 }