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