Remove repeat sfree(state->nosehoover_xi)
[alexxy/gromacs.git] / src / ngmx / xdlghi.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 <string.h>
40
41 #include "gmx_fatal.h"
42 #include "string2.h"
43 #include "sysstuff.h"
44 #include "smalloc.h"
45 #include "macros.h"
46 #include "xdlghi.h"
47 #include "fgrid.h"
48
49 t_dlgitem **CreateRadioButtonGroup(t_x11 *x11, char *szTitle,
50                                    t_id GroupID, int nrb, t_id rb[],
51                                    int nSelect,
52                                    char *szRB[], int x0, int y0)
53 /* This routine creates a radio button group at the
54  * specified position. The return values is a pointer to an
55  * array of dlgitems, the array has length (nrb+1) with the +1
56  * because of the groupbox.
57  * nSelect is the ordinal of the selected button.
58  */
59 {
60     t_dlgitem **dlgitem;
61     int         x, y, w;
62     int         i;
63
64     snew(dlgitem, nrb+1);
65     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nrb, rb, x0, y0, 0, 0, 0);
66     x          = x0+2*OFFS_X;
67     y          = dlgitem[0]->win.y+dlgitem[0]->win.height;
68     w          = 0;
69     for (i = 0; (i < nrb); i++)
70     {
71         dlgitem[i+1] = CreateRadioButton(x11, szRB[i], (i == nSelect),
72                                          rb[i], GroupID, x, y, 0, 0, 0);
73         y += dlgitem[i+1]->win.height+OFFS_Y;
74         w  = max(w, dlgitem[i+1]->win.width);
75     }
76     for (i = 0; (i < nrb); i++)
77     {
78         dlgitem[i+1]->win.width = w;
79     }
80     dlgitem[0]->win.width  = w+4*OFFS_X;
81     dlgitem[0]->win.height = y-y0;
82
83     return dlgitem;
84 }
85
86 t_dlgitem **CreateDlgitemGroup(t_x11 *x11, const char *szTitle,
87                                t_id GroupID, int x0, int y0,
88                                int nitem, ...)
89 /* This routine creates a dlgitem group at the
90  * specified position. The return values is a pointer to an
91  * array of dlgitems, the array has length (nitem+1) with the +1
92  * because of the groupbox.
93  */
94 {
95     va_list       ap;
96
97     t_dlgitem   **dlgitem;
98     t_id         *ids;
99     edlgitem      edlg;
100     char         *name;
101     gmx_bool      bBool;
102     Pixmap        pm;
103     int           nlines, buflen;
104     char         *buf, **lines;
105     int           x, y, w, i;
106
107     va_start(ap, nitem);
108
109     snew(dlgitem, nitem+1);
110     snew(ids, nitem);
111     x          = x0+2*OFFS_X;
112     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nitem, ids, x0, y0, 0, 0, 0);
113     y          = dlgitem[0]->win.y+dlgitem[0]->win.height;
114     w          = 0;
115     for (i = 0; (i < nitem); i++)
116     {
117         edlg   = (edlgitem)va_arg(ap, int);
118         ids[i] = va_arg(ap, int);
119         switch (edlg)
120         {
121             case edlgBN:
122                 name         = va_arg(ap, char *);
123                 bBool        = va_arg(ap, int);
124                 dlgitem[i+1] = CreateButton(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
125                 break;
126             case edlgRB:
127                 name         = va_arg(ap, char *);
128                 bBool        = va_arg(ap, int);
129                 dlgitem[i+1] = CreateRadioButton(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
130                 break;
131             case edlgCB:
132                 name         = va_arg(ap, char *);
133                 bBool        = va_arg(ap, int);
134                 dlgitem[i+1] = CreateCheckBox(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
135                 break;
136             case edlgPM:
137                 pm           = va_arg(ap, Pixmap);
138                 dlgitem[i+1] = CreatePixmap(x11, pm, ids[i], GroupID, x, y, 0, 0, 0);
139                 break;
140             case edlgST:
141                 nlines       = va_arg(ap, int);
142                 lines        = va_arg(ap, char **);
143                 dlgitem[i+1] = CreateStaticText(x11, nlines, lines, ids[i], GroupID,
144                                                 x, y, 0, 0, 0);
145                 break;
146             case edlgET:
147                 name         = va_arg(ap, char *);
148                 buflen       = va_arg(ap, int);
149                 buf          = va_arg(ap, char *);
150                 dlgitem[i+1] = CreateEditText(x11, name, buflen, buf, ids[i],
151                                               GroupID, x, y, 0, 0, 0);
152                 break;
153             case edlgGB:
154             default:
155                 gmx_fatal(FARGS, "Invalid dlgitem type: %d\n", edlg);
156         }
157         y += dlgitem[i+1]->win.height+OFFS_Y;
158         w  = max(w, dlgitem[i+1]->win.width);
159     }
160     va_end(ap);
161     sfree(dlgitem[0]->u.groupbox.item);
162     sfree(dlgitem[0]->win.text);
163     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nitem, ids, x0, y0, 0, 0, 0);
164     for (i = 0; (i < nitem); i++)
165     {
166         dlgitem[i+1]->win.width = w;
167     }
168     dlgitem[0]->win.width  = w+4*OFFS_X;
169     dlgitem[0]->win.height = y-y0;
170     return dlgitem;
171 }
172
173 static void AddDlgItemGroups(t_dlg *dlg, int gridx, int gridy,
174                              t_dlgitemlist **grid, gmx_bool bAutoPosition)
175 {
176     t_dlgitemlist *item;
177     int            x1, y1, w1, h1;
178     int            x, y, dw, dh;
179     float          w, h;
180
181     w = h = 0;
182     for (x = 0; (x < gridx); x++)
183     {
184         for (y = 0; (y < gridy); y++)
185         {
186             item = &(grid[x][y]);
187             if (item->nitem)
188             {
189                 if (!item->list)
190                 {
191                     printf("Error: empty list with non-empty nitem (%d)\n", item->nitem);
192                     printf("       at grid point: %d,%d\n", x, y);
193                     printf("       with size: %dx%d\n", item->w, item->h);
194                     exit(1);
195                 }
196                 else
197                 {
198                     AddDlgItems(dlg, item->nitem, item->list);
199                     dw = item->w;
200                     dh = item->h;
201                     w  = max(w, ((float) QueryDlgItemW(dlg, item->list[0]->ID))/dw);
202                     h  = max(h, ((float) QueryDlgItemH(dlg, item->list[0]->ID))/dh);
203                 }
204             }
205         }
206     }
207     w1 = gridx*w;
208     h1 = gridy*h;
209     SetDlgSize(dlg, w1, h1, bAutoPosition);
210 #ifdef DEBUG
211     printf("Dimensions of grid cell: %8.3f x %8.3f\n", w, h);
212     printf("Dimensions of window:    %d x %d\n", w1, h1);
213 #endif
214
215     for (x = 0; (x < gridx); x++)
216     {
217         for (y = 0; (y < gridy); y++)
218         {
219             item = &(grid[x][y]);
220             if (item->nitem)
221             {
222                 x1 = x*w;
223                 y1 = y*h;
224                 w1 = item->w*w;
225                 h1 = item->h*h;
226 #ifdef DEBUG
227                 printf("New size: %d x %d at %d, %d\n", w1, h1, x1, y1);
228 #endif
229                 SetDlgItemSize(dlg, item->list[0]->ID, w1, h1);
230                 SetDlgItemPos(dlg, item->list[0]->ID, x1, y1);
231             }
232         }
233     }
234 }
235
236 static t_dlgitemlist **NewDlgitemList(int w, int h)
237 {
238     int             i, j;
239     t_dlgitemlist **grid;
240
241     snew(grid, w);
242     for (i = 0; (i < w); i++)
243     {
244         snew(grid[i], h);
245         for (j = 0; (j < h); j++)
246         {
247             grid[i][j].nitem = 0;
248             grid[i][j].list  = NULL;
249         }
250     }
251     return grid;
252 }
253
254 static void AddListItem(t_dlgitemlist *list, t_dlgitem *item)
255 {
256     srenew(list->list, ++list->nitem);
257     list->list[list->nitem-1] = item;
258 }
259
260 static void AddListFItem(t_x11 *x11, t_dlgitemlist *list,
261                          t_fitem *fitem, t_id GroupID, t_id *ID,
262                          int x, int *y, int *w, gmx_bool bUseMon)
263 {
264     int  i, iSel, slen;
265     char buf[STRLEN];
266
267     switch (fitem->edlg)
268     {
269         case edlgBN:
270             AddListItem
271                 (list, CreateButton(x11, fitem->name[0], fitem->bDef, (*ID)++, GroupID,
272                                     x, (*y), 0, 0, 0));
273             break;
274         case edlgRB:
275             strcpy(buf, fitem->def);
276             iSel = -1;
277             for (i = 0; (i < fitem->nname); i++)
278             {
279                 char buf2[100];
280
281                 strcpy(buf2, fitem->name[i]);
282                 buf2[strlen(buf)] = '\0'; /* truncate itemname */
283                 if (gmx_strcasecmp(buf2, buf) == 0)
284                 {
285                     iSel = i;
286                 }
287             }
288
289             for (i = 0; (i < fitem->nname); i++)
290             {
291                 AddListItem(list,
292                             CreateRadioButton(x11, fitem->name[i], (iSel == i),
293                                               (*ID)++, GroupID, x, (*y), 0, 0, 0));
294                 (*y) += list->list[list->nitem-1]->win.height+OFFS_Y;
295                 (*w)  = max((*w), list->list[list->nitem-1]->win.width);
296                 SetDlgitemOpts(list->list[list->nitem-1], bUseMon,
297                                fitem->set, fitem->get, fitem->help);
298             }
299             break;
300         case edlgCB:
301         {
302             gmx_bool bCheck;
303
304             bCheck = gmx_strcasecmp(fitem->def, "TRUE") == 0;
305             AddListItem(list, CreateCheckBox(x11, fitem->name[0], bCheck,
306                                              (*ID)++, GroupID, x, (*y), 0, 0, 0));
307             break;
308         }
309         case edlgST:
310             AddListItem(list,
311                         CreateStaticText(x11, fitem->nname, fitem->name, (*ID)++,
312                                          GroupID, x, (*y), 0, 0, 0));
313             break;
314         case edlgET:
315             slen = strlen(fitem->name[0])+strlen(fitem->def);
316             AddListItem(list, CreateEditText(x11, fitem->name[0], slen, fitem->def,
317                                              (*ID)++, GroupID, x, (*y), 0, 0, 0));
318             break;
319         case edlgPM:
320         case edlgGB:
321         default:
322             gmx_fatal(FARGS, "Invalid list->list type: %d\n", fitem->edlg);
323     }
324     SetDlgitemOpts(list->list[list->nitem-1], bUseMon,
325                    fitem->set, fitem->get, fitem->help);
326
327     if (fitem->edlg != edlgRB)
328     {
329         (*y) += list->list[list->nitem-1]->win.height+OFFS_Y;
330         (*w)  = max((*w), list->list[list->nitem-1]->win.width);
331     }
332 }
333
334 static void AddListFGroup(t_x11 *x11, t_dlgitemlist **grid,
335                           t_fgroup *fgroup, t_id *ID, gmx_bool bUseMon)
336 {
337     int            i;
338     t_id           GroupID, *ids;
339     t_dlgitemlist *item;
340     int            x, y, w;
341
342     GroupID = (*ID)++;
343     item    = &(grid[fgroup->x][fgroup->y]);
344     AddListItem(item, CreateGroupBox(x11, fgroup->name, GroupID,
345                                      0, NULL, 0, 0, 0, 0, 0));
346     x = 2*OFFS_X;
347     y = item->list[0]->win.y+item->list[0]->win.height;
348     w = 0;
349     for (i = 0; (i < fgroup->nfitem); i++)
350     {
351         AddListFItem(x11, item, fgroup->fitem[i], GroupID, ID, x, &y, &w, bUseMon);
352     }
353
354     w = max(w, item->list[0]->win.width+4*OFFS_X);
355     sfree(item->list[0]->u.groupbox.item);
356     sfree(item->list[0]->win.text);
357     snew(ids, item->nitem);
358     for (i = 0; (i < item->nitem-1); i++)
359     {
360         ids[i] = GroupID+i+1;
361     }
362     item->list[0] =
363         CreateGroupBox(x11, fgroup->name, GroupID, item->nitem-1, ids,
364                        2*OFFS_X, 2*OFFS_Y, w+2*OFFS_X, y, 0);
365     sfree(ids);
366     item->w = fgroup->w;
367     item->h = fgroup->h;
368 }
369
370 static void AddListFSimple(t_x11 *x11, t_dlgitemlist **grid,
371                            t_fsimple *fsimple, t_id *ID, gmx_bool bUseMon)
372 {
373     t_dlgitemlist *item;
374     int            x, y, w;
375
376     item = &(grid[fsimple->x][fsimple->y]);
377     x    = 0;
378     y    = 0;
379     w    = 0;
380     AddListFItem(x11, item, fsimple->fitem, *ID, ID, x, &y, &w, bUseMon);
381     item->w = fsimple->w;
382     item->h = fsimple->h;
383 }
384
385 t_dlg *ReadDlg(t_x11 *x11, Window Parent, const char *title,
386                unsigned long fg, unsigned long bg, const char *infile,
387                int x0, int y0, gmx_bool bAutoPosition, gmx_bool bUseMon,
388                DlgCallback *cb, void *data)
389 {
390     t_fgrid        *fgrid;
391     t_dlgitemlist **grid;
392     t_dlg          *dlg;
393     int             i;
394     t_id            ID;
395
396     fgrid = FGridFromFile(infile);
397     dlg   = CreateDlg(x11, Parent, title, x0, y0, 0, 0, 0, fg, bg, cb, data);
398     grid  = NewDlgitemList(fgrid->w, fgrid->h);
399     ID    = 0;
400
401     for (i = 0; (i < fgrid->nfgroup); i++)
402     {
403         AddListFGroup(x11, grid, fgrid->fgroup[i], &ID, bUseMon);
404     }
405     for (i = 0; (i < fgrid->nfsimple); i++)
406     {
407         AddListFSimple(x11, grid, fgrid->fsimple[i], &ID, bUseMon);
408     }
409     AddDlgItemGroups(dlg, fgrid->w, fgrid->h, grid, bAutoPosition);
410
411     DoneFGrid(fgrid);
412
413     return dlg;
414 }