Merge release-4-6 into release-5-0
[alexxy/gromacs.git] / src / programs / view / fgrid.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 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include "gromacs/utility/cstringutil.h"
46 #include "gromacs/utility/smalloc.h"
47 #include "fgrid.h"
48 #include "gromacs/fileio/futil.h"
49
50 static const char *type[] = {
51     "button", "radiobuttons", "groupbox", "checkbox",
52     "pixmap", "statictext",   "edittext", "defbutton"
53 };
54
55 void ReadDlgError(const char *infile, eDLGERR err, const char *s,
56                   const char *file, int line)
57 {
58     fprintf(stderr, "Error: ");
59     switch (err)
60     {
61         case eNOVALS:
62             fprintf(stderr, "Not enough values for %s", s);
63             break;
64         case eGRIDEXP:
65             fprintf(stderr, "'grid' expected instead of %s", s);
66             break;
67         case eACCOEXP:
68             fprintf(stderr, "'{' expected instead of %s", s);
69             break;
70         case eACCCEXP:
71             fprintf(stderr, "'}' expected instead of %s", s);
72             break;
73         case eGRPEXP:
74             fprintf(stderr, "'group' expected instead of %s", s);
75             break;
76         case eITEMEXP:
77             fprintf(stderr, "item expected instead of %s", s);
78             break;
79         case eSAMEPOINT:
80             fprintf(stderr, "grid point for %s already in use", s);
81             break;
82         case eTOOWIDE:
83             fprintf(stderr, "grid too wide for %s", s);
84             break;
85         case eTOOHIGH:
86             fprintf(stderr, "grid too high for %s", s);
87             break;
88         case eQUOTE:
89             fprintf(stderr, "quote expected instead of %s", s);
90             break;
91         default:
92             fprintf(stderr, "????");
93             break;
94     }
95     fprintf(stderr, " in file %s\n", infile);
96     fprintf(stderr, "source file: %s, line: %d\n", file, line);
97     exit(1);
98 }
99
100 #define ReadDlgErr(in, er, es) ReadDlgError(in, er, es, __FILE__, __LINE__)
101
102 static void ReadAccOpen(const char *infile, FILE *in)
103 {
104     char buf[STRLEN];
105
106     fscanf(in, "%4s", buf);
107     if (strcmp(buf, "{") != 0)
108     {
109         ReadDlgErr(infile, eACCOEXP, buf);
110     }
111 }
112
113 static void ReadAccClose(const char *infile, FILE *in)
114 {
115     char buf[STRLEN];
116
117     fscanf(in, "%4s", buf);
118     if (strcmp(buf, "}") != 0)
119     {
120         ReadDlgErr(infile, eACCCEXP, buf);
121     }
122 }
123
124 void ReadQuoteString(const char *infile, FILE *in, char *buf)
125 {
126     char c[2];
127     int  i = 0;
128
129     /* Read until first quote */
130     while ((c[0] = fgetc(in)) != '"')
131     {
132         if (!isspace(c[0]))
133         {
134             c[1] = '\0';
135             ReadDlgErr(infile, eQUOTE, c);
136         }
137     }
138     /* Read until second quote */
139     while ((c[0] = fgetc(in)) != '"')
140     {
141         buf[i++] = c[0];
142     }
143     buf[i] = '\0';
144 }
145
146 static void ReadQuoteStringOrAccClose(FILE *in, char *buf)
147 {
148     char c;
149     int  i = 0;
150
151     /* Read until first quote */
152     do
153     {
154         c = fgetc(in);
155         if (c == '}')
156         {
157             buf[0] = c;
158             buf[1] = '\0';
159             return;
160         }
161     }
162     while (c != '"');
163
164     /* Read until second quote */
165     while ((c = fgetc(in)) != '"')
166     {
167         buf[i++] = c;
168     }
169     buf[i] = '\0';
170 }
171
172 static bool bNotAccClose(const char *buf)
173 {
174     return (strcmp(buf, "}") != 0);
175 }
176
177 static t_fitem *NewFItem(void)
178 {
179     t_fitem *fitem;
180
181     snew(fitem, 1);
182     fitem->nname = 0;
183     fitem->name  = NULL;
184     fitem->set   = NULL;
185     fitem->get   = NULL;
186     fitem->def   = NULL;
187     fitem->help  = NULL;
188
189     return fitem;
190 }
191
192 static t_fsimple *NewFSimple(void)
193 {
194     t_fsimple *fsimple;
195
196     snew(fsimple, 1);
197
198     return fsimple;
199 }
200
201 static void AddFItemName(t_fitem *fitem, char *name)
202 {
203     srenew(fitem->name, ++fitem->nname);
204     fitem->name[fitem->nname-1] = strdup(name);
205 }
206
207 static t_fgroup *NewFGroup(void)
208 {
209     t_fgroup *fgroup;
210
211     snew(fgroup, 1);
212     fgroup->name   = NULL;
213     fgroup->nfitem = 0;
214     fgroup->fitem  = NULL;
215
216     return fgroup;
217 }
218
219 static void AddFGroupFItem(t_fgroup *fgroup, t_fitem *fitem)
220 {
221     srenew(fgroup->fitem, ++fgroup->nfitem);
222     fgroup->fitem[fgroup->nfitem-1] = fitem;
223 }
224
225 static t_fgroup *AddFGridFGroup(t_fgrid *fgrid)
226 {
227     srenew(fgrid->fgroup, ++fgrid->nfgroup);
228     fgrid->fgroup[fgrid->nfgroup-1] = NewFGroup();
229     return fgrid->fgroup[fgrid->nfgroup-1];
230 }
231
232 static t_fsimple *AddFGridFSimple(t_fgrid *fgrid)
233 {
234     srenew(fgrid->fsimple, ++fgrid->nfsimple);
235     fgrid->fsimple[fgrid->nfsimple-1] = NewFSimple();
236     return fgrid->fsimple[fgrid->nfsimple-1];
237 }
238
239 static t_fgrid *NewFGrid(void)
240 {
241     t_fgrid *fgrid;
242
243     snew(fgrid, 1);
244     fgrid->w        = 0;
245     fgrid->h        = 0;
246     fgrid->nfgroup  = 0;
247     fgrid->fgroup   = NULL;
248     fgrid->nfsimple = 0;
249     fgrid->fsimple  = NULL;
250
251     return fgrid;
252 }
253
254 static void DoneFItem(t_fitem *fitem)
255 {
256     int i;
257
258     for (i = 0; (i < fitem->nname); i++)
259     {
260         sfree(fitem->name[i]);
261     }
262     sfree(fitem->name);
263     sfree(fitem->set);
264     sfree(fitem->get);
265     sfree(fitem->def);
266     sfree(fitem->help);
267 }
268
269 static void DoneFGroup(t_fgroup *fgroup)
270 {
271     int i;
272
273     sfree(fgroup->name);
274     for (i = 0; (i < fgroup->nfitem); i++)
275     {
276         DoneFItem(fgroup->fitem[i]);
277     }
278     sfree(fgroup->fitem);
279 }
280
281 static void DoneFSimple(t_fsimple *fsimple)
282 {
283     DoneFItem(fsimple->fitem);
284     sfree(fsimple->fitem);
285 }
286
287 void DoneFGrid(t_fgrid *fgrid)
288 {
289     int i;
290
291     for (i = 0; (i < fgrid->nfgroup); i++)
292     {
293         DoneFGroup(fgrid->fgroup[i]);
294     }
295     sfree(fgrid->fgroup);
296     for (i = 0; (i < fgrid->nfsimple); i++)
297     {
298         DoneFSimple(fgrid->fsimple[i]);
299     }
300     sfree(fgrid->fsimple);
301 }
302
303 static t_fitem *ScanFItem(const char *infile, FILE *in, char *buf)
304 {
305     char     set[STRLEN], get[STRLEN], help[STRLEN], def[STRLEN];
306     int      edlg;
307     t_fitem *fitem;
308
309     fitem = NewFItem();
310
311     for (edlg = 0; (edlg < edlgNR+1); edlg++)
312     {
313         if (strcmp(buf, type[edlg]) == 0)
314         {
315             break;
316         }
317     }
318     if (edlg == edlgNR)
319     {
320         /* Special case */
321         edlg        = edlgBN;
322         fitem->bDef = true;
323     }
324     if (edlg == edlgNR+1)
325     {
326         ReadDlgErr(infile, eITEMEXP, buf);
327     }
328
329     fitem->edlg = (edlgitem)edlg;
330     switch (edlg)
331     {
332         case edlgBN:
333         case edlgCB:
334         case edlgET:
335             ReadQuoteString(infile, in, buf);
336             AddFItemName(fitem, buf);
337             break;
338         case edlgST:
339         case edlgRB:
340             ReadAccOpen(infile, in);
341             ReadQuoteStringOrAccClose(in, buf);
342             while (bNotAccClose(buf))
343             {
344                 AddFItemName(fitem, buf);
345                 ReadQuoteStringOrAccClose(in, buf);
346             }
347             break;
348         case edlgPM:
349         case edlgGB:
350             ReadDlgErr(infile, eITEMEXP, type[edlg]);
351             break;
352         default:
353             break;
354     }
355     ReadQuoteString(infile, in, set);
356     ReadQuoteString(infile, in, get);
357     ReadQuoteString(infile, in, def);
358     ReadQuoteString(infile, in, help);
359     fitem->set  = strdup(set);
360     fitem->get  = strdup(get);
361     fitem->def  = strdup(def);
362     fitem->help = strdup(help);
363
364     return fitem;
365 }
366
367 t_fgrid *FGridFromFile(const char *infile)
368 {
369     FILE      *in;
370     char       buf[STRLEN];
371
372     t_fgrid   *fgrid;
373     t_fgroup  *fgroup;
374     t_fsimple *fsimple;
375     int        gridx, gridy;
376
377     in = libopen(infile);
378     fscanf(in, "%6s", buf);
379     if (strcmp(buf, "grid") != 0)
380     {
381         ReadDlgErr(infile, eGRIDEXP, buf);
382     }
383     fgrid = NewFGrid();
384     if ((fscanf(in, "%5d%5d", &gridx, &gridy)) != 2)
385     {
386         ReadDlgErr(infile, eNOVALS, "grid w,h");
387     }
388     fgrid->w = gridx;
389     fgrid->h = gridy;
390     ReadAccOpen(infile, in);
391     fscanf(in, "%15s", buf);
392     while (bNotAccClose(buf))
393     {
394         if (strcmp(buf, "group") == 0)
395         {
396             fgroup = AddFGridFGroup(fgrid);
397             ReadQuoteString(infile, in, buf);
398             fgroup->name = strdup(buf);
399             if ((fscanf(in, "%5d%5d%5d%5d", &fgroup->x, &fgroup->y, &fgroup->w, &fgroup->h)) != 4)
400             {
401                 ReadDlgErr(infile, eNOVALS, "group x,y,w,h");
402             }
403             if (fgroup->x+fgroup->w > gridx)
404             {
405                 ReadDlgErr(infile, eTOOWIDE, buf);
406             }
407             if (fgroup->y+fgroup->h > gridy)
408             {
409                 ReadDlgErr(infile, eTOOHIGH, buf);
410             }
411             ReadAccOpen(infile, in);
412             fscanf(in, "%15s", buf);
413             while (bNotAccClose(buf))
414             {
415                 AddFGroupFItem(fgroup, ScanFItem(infile, in, buf));
416                 fscanf(in, "%15s", buf);
417             }
418         }
419         else if (strcmp(buf, "simple") == 0)
420         {
421             fsimple = AddFGridFSimple(fgrid);
422             if ((fscanf(in, "%5d%5d%5d%5d", &fsimple->x, &fsimple->y, &fsimple->w, &fsimple->h)) != 4)
423             {
424                 ReadDlgErr(infile, eNOVALS, "simple x,y,w,h");
425             }
426             if (fsimple->x+fsimple->w > gridx)
427             {
428                 ReadDlgErr(infile, eTOOWIDE, "simple");
429             }
430             if (fsimple->y+fsimple->h > gridy)
431             {
432                 ReadDlgErr(infile, eTOOHIGH, "simple");
433             }
434             ReadAccOpen(infile, in);
435             fscanf(in, "%15s", buf);
436             fsimple->fitem = ScanFItem(infile, in, buf);
437             ReadAccClose(infile, in);
438         }
439         fscanf(in, "%15s", buf);
440     }
441     gmx_ffclose(in);
442
443     return fgrid;
444 }
445
446 static void DumpFItem(t_fitem *fitem)
447 {
448     int i;
449
450     printf("  type: %s, set: '%s', get: '%s', def: '%s', help: '%s'\n  {",
451            type[fitem->edlg], fitem->set, fitem->get, fitem->def, fitem->help);
452     for (i = 0; (i < fitem->nname); i++)
453     {
454         printf("  '%s'", fitem->name[i]);
455     }
456     printf("  }\n");
457 }
458
459 static void DumpFSimple(t_fsimple *fsimple)
460 {
461     printf("Simple %dx%d at %d,%d\n", fsimple->w, fsimple->h, fsimple->x, fsimple->y);
462     DumpFItem(fsimple->fitem);
463 }
464
465 static void DumpFGroup(t_fgroup *fgroup)
466 {
467     int i;
468
469     printf("Group %dx%d at %d,%d\n", fgroup->w, fgroup->h, fgroup->x, fgroup->y);
470     for (i = 0; (i < fgroup->nfitem); i++)
471     {
472         DumpFItem(fgroup->fitem[i]);
473     }
474 }
475
476 void DumpFGrid(t_fgrid *fgrid)
477 {
478     int i;
479
480     printf("Grid %dx%d\n", fgrid->w, fgrid->h);
481     for (i = 0; (i < fgrid->nfgroup); i++)
482     {
483         DumpFGroup(fgrid->fgroup[i]);
484     }
485     for (i = 0; (i < fgrid->nfsimple); i++)
486     {
487         DumpFSimple(fgrid->fsimple[i]);
488     }
489 }