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