Sort includes outside src/gromacs
[alexxy/gromacs.git] / src / programs / view / xdlgitem.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-2013, 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 "xdlgitem.h"
40
41 #include <ctype.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include <algorithm>
47
48 #include "gromacs/legacyheaders/macros.h"
49 #include "gromacs/utility/cstringutil.h"
50 #include "gromacs/utility/fatalerror.h"
51 #include "gromacs/utility/smalloc.h"
52
53 #include "Xstuff.h"
54
55 #define BUFSIZE 16
56
57 static t_dlgitem *newitem(void)
58 {
59     t_dlgitem *item;
60
61     snew(item, 1);
62
63     return item;
64 }
65
66 /*****************************
67  *
68  * Window Procedures and helpful functions
69  *
70  ****************************/
71 static void ShowCaret(t_x11 *x11, t_dlgitem *dlgitem)
72 {
73     t_edittext *et;
74
75     if (dlgitem->type == edlgET)
76     {
77         int x, y1, y2;
78
79         et = &(dlgitem->u.edittext);
80         x  = XTextWidth(x11->font, dlgitem->win.text, strlen(dlgitem->win.text))+XCARET+
81             XTextWidth(x11->font, (char*) &(et->buf[et->strbegin]), et->pos);
82         y1 = (dlgitem->win.height-XTextHeight(x11->font))/2;
83         y2 = (dlgitem->win.height-y1);
84         y1--, y2++;
85         XDrawLine(x11->disp, dlgitem->win.self, x11->gc, x-XCARET, y1, x+XCARET, y1);
86         XDrawLine(x11->disp, dlgitem->win.self, x11->gc, x, y1, x, y2);
87         XDrawLine(x11->disp, dlgitem->win.self, x11->gc, x-XCARET, y2, x+XCARET, y2);
88     }
89 }
90
91 static void HideCaret(t_x11 *x11, t_dlgitem *dlgitem)
92 {
93     XSetForeground(x11->disp, x11->gc, x11->bg);
94     ShowCaret(x11, dlgitem);
95     XSetForeground(x11->disp, x11->gc, x11->fg);
96 }
97
98 static int DefWndProc(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
99 {
100     XComposeStatus status;
101     KeySym         keysym;
102     char           c[BUFSIZE+1];
103
104 #ifdef DEBUG
105     printf("DefWndProc\n");
106 #endif
107     switch (event->type)
108     {
109         case Expose:
110         case ButtonPress:
111         case KeyPress:
112             if (HelpPressed(event))
113             {
114                 return HELPPRESSED;
115             }
116             else
117             {
118                 XLookupString(&(event->xkey), c, BUFSIZE, &keysym, &status);
119                 if ((keysym == XK_Return) || (keysym == XK_KP_Enter))
120                 {
121                     return ENTERPRESSED;
122                 }
123             }
124             break;
125         case EnterNotify:
126             dlgitem->win.bFocus = true;
127             ShowCaret(x11, dlgitem);
128             /*    LightBorder(x11->disp,dlgitem->win.self,x11->fg); */
129             break;
130         case LeaveNotify:
131             dlgitem->win.bFocus = false;
132             HideCaret(x11, dlgitem);
133             /*    LightBorder(x11->disp,dlgitem->win.self,x11->bg); */
134             break;
135         default:
136             XBell(x11->disp, 50);
137     }
138     return ITEMOK;
139 }
140
141 static int WndProcBN(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
142 {
143     t_windata *win;
144     int        x, w, th;
145
146     if (dlgitem->type != edlgBN)
147     {
148         gmx_incons("button processing");
149     }
150     win = &(dlgitem->win);
151     w   = XTextWidth(x11->font, win->text, strlen(win->text));
152     x   = (win->width-w)/2;
153     th  = XTextHeight(x11->font)+OFFS_Y;
154     switch (event->type)
155     {
156         case Expose:
157             RectWin(x11->disp, x11->gc, win, x11->fg);
158             TextInRect(x11, win->self, win->text, 0, 0, win->width, th, eXCenter, eYCenter);
159             break;
160         case ButtonPress:
161             return BNPRESSED;
162         case EnterNotify:
163             XDrawLine(x11->disp, win->self, x11->gc, x-1, th, x+w, th);
164             break;
165         case LeaveNotify:
166             XSetForeground(x11->disp, x11->gc, x11->bg);
167             XDrawLine(x11->disp, win->self, x11->gc, x-1, th, x+w, th);
168             XSetForeground(x11->disp, x11->gc, x11->fg);
169             break;
170         default:
171             return DefWndProc(x11, dlgitem, event);
172     }
173     return ITEMOK;
174 }
175
176 static int WndProcRB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
177 {
178     t_radiobutton *rb;
179     t_windata     *win;
180     int            x, y, rad;
181
182     if (dlgitem->type != edlgRB)
183     {
184         gmx_incons("radiobutton processing");
185     }
186     rb  = &(dlgitem->u.radiobutton);
187     win = &(dlgitem->win);
188
189     rad = win->height/3;
190     x   = rad;
191     y   = win->height/2;
192     switch (event->type)
193     {
194         case Expose:
195             XClearArea(x11->disp, win->self, x-rad, y-rad, x+rad, y+rad, False);
196             if (rb->bSelect)
197             {
198                 /* Filled */
199                 XFillCircle(x11->disp, win->self, x11->gc, x, y, rad);
200             }
201             XDrawCircle(x11->disp, win->self, x11->gc, x, y, rad);
202             x += rad+OFFS_X;
203             TextInRect(x11, win->self, win->text, x, 0, win->width-x, win->height,
204                        eXLeft, eYCenter);
205             break;
206         case ButtonPress:
207             if (!rb->bSelect)
208             {
209                 return RBPRESSED;
210             }
211             XBell(x11->disp, 50);
212             break;
213         case EnterNotify:
214         case LeaveNotify:
215             break;
216         default:
217             return DefWndProc(x11, dlgitem, event);
218     }
219     return ITEMOK;
220 }
221
222 static int WndProcGB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
223 {
224     t_windata *win;
225     int        x, y;
226
227     if (dlgitem->type != edlgGB)
228     {
229         gmx_incons("gb processing");
230     }
231     win = &(dlgitem->win);
232
233     x = XTextWidth(x11->font, win->text, strlen(win->text));
234     y = XTextHeight(x11->font);
235     switch (event->type)
236     {
237         case Expose:
238             XSetForeground(x11->disp, x11->gc, x11->fg);
239             XDrawRoundRect(x11->disp, win->self, x11->gc, 0, y/2,
240                            win->width-1, win->height-y/2-1);
241             XClearArea(x11->disp, win->self, OFFS_X, 0, x+OFFS_X, y, False);
242             TextInRect(x11, win->self, win->text, 2*OFFS_X, 0, x, y, eXCenter, eYCenter);
243             break;
244         case EnterNotify:
245         case LeaveNotify:
246             break;
247         default:
248             return DefWndProc(x11, dlgitem, event);
249     }
250     return ITEMOK;
251 }
252
253 static int WndProcCB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
254 {
255     t_checkbox *cb;
256     t_windata  *win;
257     int         x, y, w, h;
258
259     if (dlgitem->type != edlgCB)
260     {
261         gmx_incons("check box processing");
262     }
263     cb  = &(dlgitem->u.checkbox);
264     win = &(dlgitem->win);
265
266     x = 0;
267     y = win->height/7;
268     w = 5*y;
269     h = 5*y;
270     switch (event->type)
271     {
272         case Expose:
273             XSetForeground(x11->disp, x11->gc, x11->fg);
274             XClearArea(x11->disp, win->self, x, y, w, h, False);
275             XDrawRectangle(x11->disp, win->self, x11->gc, x, y, w, h);
276             if (cb->bChecked)
277             {
278                 XDrawLine(x11->disp, win->self, x11->gc, x, y, x+w, y+h);
279                 XDrawLine(x11->disp, win->self, x11->gc, x+w, y, x, y+h);
280             }
281             x = w+OFFS_X;
282             TextInRect(x11, win->self, win->text, x, 0, win->width-x, win->height,
283                        eXLeft, eYCenter);
284             break;
285         case ButtonPress:
286             cb->bChecked = !cb->bChecked;
287             return CBPRESSED;
288         case EnterNotify:
289         case LeaveNotify:
290             break;
291         default:
292             return DefWndProc(x11, dlgitem, event);
293     }
294     return ITEMOK;
295 }
296
297 static int WndProcST(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
298 {
299     t_statictext *st;
300     t_windata    *win;
301     int           i, dy;
302
303     if (dlgitem->type != edlgST)
304     {
305         gmx_incons("st processing");
306     }
307     st  = &(dlgitem->u.statictext);
308     win = &(dlgitem->win);
309
310     switch (event->type)
311     {
312         case Expose:
313             dy = XTextHeight(x11->font)+OFFS_Y;
314             for (i = 0; (i < st->nlines); i++)
315             {
316                 TextInRect(x11, win->self, st->lines[i],
317                            0, OFFS_Y+i*dy, win->width, dy, eXLeft, eYCenter);
318             }
319             break;
320         default:
321             return DefWndProc(x11, dlgitem, event);
322     }
323     return ITEMOK;
324 }
325
326 static bool insert(char *s, char c, int *pos)
327 {
328     int i, sl;
329
330     if (isprint(c))
331     {
332         sl = strlen(s);
333         /* +1 for zero termination */
334         for (i = sl+1; (i > *pos); i--)
335         {
336             s[i+1] = s[i];
337         }
338         s[*pos] = c;
339         (*pos)++;
340         return true;
341     }
342     return false;
343 }
344
345 static bool my_backspace(char *s, int *pos)
346 {
347     int i, sl;
348
349     sl = strlen(s);
350     if ((sl > 0) && ((*pos) > 0))
351     {
352         for (i = *pos-1; (i < sl); i++)
353         {
354             s[i] = s[i+1];
355         }
356         (*pos) = std::max(0, (*pos)-1);
357         return true;
358     }
359     return false;
360 }
361
362 static bool my_delete(char *s, int *pos)
363 {
364     int i, sl;
365
366     sl = strlen(s);
367     if ((sl > 0) && ((*pos) < sl))
368     {
369         for (i = *pos; (i < sl); i++)
370         {
371             s[i] = s[i+1];
372         }
373         return true;
374     }
375     return false;
376 }
377
378 static int WndProcET(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
379 {
380     t_edittext  *et;
381     t_windata   *win;
382     KeySym       keysym;
383     char         c[BUFSIZE+1], *bp;
384     char         scrbuf[STRLEN];
385     int          i;
386     int          xp, xtitle, ewidth;
387
388     if (dlgitem->type != edlgET)
389     {
390         gmx_incons("st processing");
391     }
392     et  = &(dlgitem->u.edittext);
393     win = &(dlgitem->win);
394
395     /* Copy string part that is visible into screen buffer */
396     for (i = 0; (i < et->buflen); i++)
397     {
398         scrbuf[i] = et->buf[i+et->strbegin];
399     }
400     scrbuf[i] = '\0';
401
402     switch (event->type)
403     {
404         case Expose:
405             XSetForeground(x11->disp, x11->gc, x11->fg);
406             xtitle = XTextWidth(x11->font, win->text, strlen(win->text));
407             ewidth = win->width-xtitle;
408             TextInRect(x11, win->self, win->text,
409                        0, 0, xtitle-1, win->height, eXLeft, eYCenter);
410             XClearArea(x11->disp, win->self, xtitle, 0, ewidth+XCARET, win->height, False);
411             TextInRect(x11, win->self, scrbuf,
412                        xtitle+XCARET, 0, ewidth, win->height, eXLeft, eYCenter);
413 #ifdef DEBUG
414             printf("Expose\n");
415 #endif
416             if (win->bFocus)
417             {
418                 ShowCaret(x11, dlgitem);
419             }
420             break;
421         case ButtonPress:
422             /* Calculate new position for caret */
423             et->pos = strlen(et->buf);
424             bp      = gmx_strdup(et->buf);
425             xp      = event->xbutton.x-XTextWidth(x11->font, win->text, strlen(win->text))-
426                 XCARET;
427             while ((et->pos > 0) && (XTextWidth(x11->font, bp, strlen(bp)) > xp))
428             {
429                 et->pos--;
430                 bp[et->pos] = '\0';
431             }
432             sfree(bp);
433             et->bChanged = true;
434             return ETCHANGED;
435         case KeyPress:
436             /* Check for HelpKey */
437             if (HelpPressed(event))
438             {
439                 return DefWndProc(x11, dlgitem, event);
440             }
441             XLookupString(&(event->xkey), c, BUFSIZE, &keysym, NULL);
442 #ifdef DEBUG
443             printf("Keysym: %x\n", keysym);
444 #endif
445             switch (keysym)
446             {
447                 case XK_Delete:
448                     if (my_delete(et->buf, &(et->pos)))
449                     {
450                         et->bChanged = true;
451                         return ETCHANGED;
452                     }
453                     else
454                     {
455                         XBell(x11->disp, 50);
456                     }
457                     break;
458                 case XK_BackSpace:
459                     if (my_backspace(et->buf, &(et->pos)))
460                     {
461                         et->bChanged = true;
462                         return ETCHANGED;
463                     }
464                     else
465                     {
466                         XBell(x11->disp, 50);
467                     }
468                     break;
469                 case XK_KP_Enter:
470                 case XK_Return:
471                     return ENTERPRESSED;
472                 case XK_Home:
473                     et->pos      = 0;
474                     et->strbegin = 0;
475                     et->bChanged = true;
476                     return ETCHANGED;
477                 case XK_End:
478                     if (strlen(et->buf) <= (unsigned int)et->buflen)
479                     {
480                         et->pos = strlen(et->buf);
481                     }
482                     else
483                     {
484                         et->pos      = et->buflen;
485                         et->strbegin = strlen(et->buf)-et->buflen;
486                     }
487                     et->bChanged = true;
488                     return ETCHANGED;
489                 case XK_Left:
490                     et->pos      = std::max(0, et->pos-1);
491                     et->strbegin = std::min(et->strbegin, et->pos);
492                     et->bChanged = true;
493                     return ETCHANGED;
494                 case XK_Right:
495                     if ((et->pos < et->buflen) &&
496                         (et->strbegin+et->buflen > (int)strlen(et->buf)))
497                     {
498                         et->pos++;
499                     }
500                     else if ((et->buflen   < (int)strlen(et->buf)) &&
501                              (et->strbegin < (int)strlen(et->buf)-et->buflen))
502                     {
503                         et->strbegin++;
504                     }
505                     else
506                     {
507                         break;
508                     }
509                     et->bChanged = true;
510                     return ETCHANGED;
511                 default:
512                     if (keysym < 256)
513                     {
514                         if (insert(et->buf, c[0], &(et->pos)))
515                         {
516                             et->bChanged = true;
517                             return ETCHANGED;
518                         }
519                     }
520                     XBell(x11->disp, 50);
521                     break;
522             }
523             break;
524         case LeaveNotify:
525             win->bFocus = false;
526             HideCaret(x11, dlgitem);
527             if (et->bChanged)
528             {
529                 et->bChanged = false;
530             }
531             break;
532         default:
533             return DefWndProc(x11, dlgitem, event);
534     }
535     return ITEMOK;
536 }
537
538 /*****************************
539  *
540  * Routines to create dialog items, all items have an id
541  * which you can use to extract info. It is possible to have
542  * multiple items with the same id but it may then not be possible
543  * to extract information.
544  * All routines take the position relative to the parent dlg
545  * and the size and border width.
546  * If the width and height are set to zero initially, they will
547  * be calculated and set by the routine. With the dlgitem manipulation
548  * routines listed below, the application can then move the items around
549  * on the dlg box, and if wished resize them.
550  *
551  ****************************/
552 t_dlgitem *CreateButton(t_x11 *x11,
553                         const char *szLab, bool bDef, t_id id, t_id groupid,
554                         int x0, int y0, int w, int h, int bw)
555 {
556     t_dlgitem *dlgitem;
557     char      *lab;
558
559     dlgitem = newitem();
560     if (h == 0)
561     {
562         h = XTextHeight(x11->font)+2*OFFS_Y;
563     }
564     if (w == 0)
565     {
566         w = XTextWidth(x11->font, szLab, strlen(szLab))+2*OFFS_X;
567     }
568     if (bDef)
569     {
570         snew(lab, strlen(szLab)+7); /* 6 for >> << and 1 for \0 */
571         sprintf(lab, ">> %s <<", szLab);
572     }
573     else
574     {
575         lab = gmx_strdup(szLab);
576     }
577     InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
578     sfree(lab);
579     dlgitem->ID                = id;
580     dlgitem->GroupID           = groupid;
581     dlgitem->type              = edlgBN;
582     dlgitem->u.button.bDefault = bDef;
583     dlgitem->WndProc           = WndProcBN;
584
585     return dlgitem;
586 }
587
588 t_dlgitem *CreateRadioButton(t_x11 *x11,
589                              const char *szLab, bool bSet, t_id id,
590                              t_id groupid,
591                              int x0, int y0, int w, int h, int bw)
592 {
593     t_dlgitem *dlgitem;
594
595     dlgitem = newitem();
596     if (h == 0)
597     {
598         h = XTextHeight(x11->font)+OFFS_Y;
599     }
600     if (w == 0)
601     {
602         w = XTextWidth(x11->font, szLab, strlen(szLab))+OFFS_X+h;
603     }
604     InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
605     dlgitem->ID                    = id;
606     dlgitem->GroupID               = groupid;
607     dlgitem->type                  = edlgRB;
608     dlgitem->u.radiobutton.bSelect = bSet;
609     dlgitem->WndProc               = WndProcRB;
610
611     return dlgitem;
612 }
613
614 t_dlgitem *CreateGroupBox(t_x11 *x11,
615                           const char *szLab, t_id id,
616                           int nitems, t_id items[],
617                           int x0, int y0, int w, int h, int bw)
618 {
619     t_dlgitem *dlgitem;
620
621     dlgitem = newitem();
622     if (h == 0)
623     {
624         h = XTextHeight(x11->font)+OFFS_Y;
625     }
626     if (w == 0)
627     {
628         w = XTextWidth(x11->font, szLab, strlen(szLab))+2*OFFS_X;
629     }
630     InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
631     dlgitem->GroupID           = id;
632     dlgitem->ID                = id;
633     dlgitem->type              = edlgGB;
634     dlgitem->u.groupbox.nitems = nitems;
635     snew(dlgitem->u.groupbox.item, nitems);
636     memcpy((char *)dlgitem->u.groupbox.item, (char *)items,
637            nitems*sizeof(items[0]));
638     dlgitem->WndProc = WndProcGB;
639
640     return dlgitem;
641 }
642
643 t_dlgitem *CreateCheckBox(t_x11 *x11,
644                           const char *szLab, bool bCheckedInitial, t_id id,
645                           t_id groupid,
646                           int x0, int y0, int w, int h, int bw)
647 {
648     t_dlgitem *dlgitem;
649
650     dlgitem = newitem();
651     if (h == 0)
652     {
653         h = XTextHeight(x11->font)+OFFS_Y;
654     }
655     if (w == 0)
656     {
657         w = XTextWidth(x11->font, szLab, strlen(szLab))+OFFS_X+h;
658     }
659     InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
660     dlgitem->ID                  = id;
661     dlgitem->GroupID             = groupid;
662     dlgitem->type                = edlgCB;
663     dlgitem->u.checkbox.bChecked = bCheckedInitial;
664     dlgitem->WndProc             = WndProcCB;
665
666     return dlgitem;
667 }
668
669 t_dlgitem *CreatePixmap(Pixmap pm, t_id id,
670                         t_id /*groupid*/, int x0, int y0, int w, int h, int bw)
671 {
672     t_dlgitem *dlgitem;
673
674     dlgitem = newitem();
675     InitWin(&(dlgitem->win), x0, y0, w, h, bw, NULL);
676     dlgitem->ID          = id;
677     dlgitem->type        = edlgPM;
678     dlgitem->u.pixmap.pm = pm;
679     dlgitem->WndProc     = DefWndProc;
680
681     return dlgitem;
682 }
683
684 t_dlgitem *CreateStaticText(t_x11 *x11,
685                             int nlines, const char * const *lines, t_id id,
686                             t_id groupid,
687                             int x0, int y0, int w, int h, int bw)
688 {
689     t_dlgitem *dlgitem;
690     int        i;
691
692     dlgitem = newitem();
693     if (h == 0)
694     {
695         h = (XTextHeight(x11->font)+OFFS_Y)*nlines+OFFS_Y;
696     }
697     if (w == 0)
698     {
699         for (i = 0; (i < nlines); i++)
700         {
701             w = std::max(w, XTextWidth(x11->font, lines[i], strlen(lines[i])));
702         }
703         w += 2*OFFS_X;
704     }
705     InitWin(&(dlgitem->win), x0, y0, w, h, bw, NULL);
706     dlgitem->ID                  = id;
707     dlgitem->GroupID             = groupid;
708     dlgitem->type                = edlgST;
709     dlgitem->u.statictext.nlines = nlines;
710     snew(dlgitem->u.statictext.lines, nlines);
711     for (i = 0; (i < nlines); i++)
712     {
713         dlgitem->u.statictext.lines[i] = gmx_strdup(lines[i]);
714     }
715     dlgitem->WndProc = WndProcST;
716
717     return dlgitem;
718 }
719
720 t_dlgitem *CreateEditText(t_x11 *x11,
721                           const char *title,
722                           int screenbuf, char *buf, t_id id, t_id groupid,
723                           int x0, int y0, int w, int h, int bw)
724 {
725     t_dlgitem  *dlgitem;
726     t_edittext *et;
727
728     dlgitem = newitem();
729     if (h == 0)
730     {
731         h = XTextHeight(x11->font)+OFFS_Y;
732     }
733     if (w == 0)
734     {
735         char *test;
736
737         snew(test, screenbuf);
738         memset(test, 'w', screenbuf);
739         w = XTextWidth(x11->font, test, screenbuf)+
740             XTextWidth(x11->font, title, strlen(title))+
741             2*XCARET+2*OFFS_X;
742         sfree(test);
743     }
744     InitWin(&(dlgitem->win), x0, y0, w, h, bw, title);
745     dlgitem->ID      = id;
746     dlgitem->GroupID = groupid;
747     dlgitem->type    = edlgET;
748     et               = &(dlgitem->u.edittext);
749     snew(et->buf, STRLEN);
750     strcpy(et->buf, buf);
751     et->buflen       = screenbuf;
752     et->strbegin     = 0;
753     et->bChanged     = false;
754     dlgitem->WndProc = WndProcET;
755
756     return dlgitem;
757 }
758
759 #define SC(src) (strlen(src) ? gmx_strdup(src) : NULL)
760
761 void SetDlgitemOpts(t_dlgitem *dlgitem, bool bUseMon,
762                     char *set, char *get, char *help)
763 {
764     dlgitem->bUseMon = bUseMon;
765     dlgitem->set     = SC(set);
766     dlgitem->get     = SC(get);
767     dlgitem->help    = SC(help);
768 #ifdef DEBUG
769     printf("Help is: '%s'\n", dlgitem->help);
770 #endif
771 }