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