Apply re-formatting to C++ in src/ tree.
[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,2015,2017,2018 by the GROMACS development team.
7  * Copyright (c) 2019,2020, by the GROMACS development team, led by
8  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9  * and including many others, as listed in the AUTHORS file in the
10  * top-level source directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 #include "gmxpre.h"
39
40 #include "fgrid.h"
41
42 #include <cctype>
43 #include <cstdio>
44 #include <cstdlib>
45 #include <cstring>
46
47 #include "gromacs/utility/cstringutil.h"
48 #include "gromacs/utility/futil.h"
49 #include "gromacs/utility/smalloc.h"
50
51 static const char* type[] = { "button", "radiobuttons", "groupbox", "checkbox",
52                               "pixmap", "statictext",   "edittext", "defbutton" };
53
54 static void ReadDlgError(const char* infile, eDLGERR err, const char* s, const char* file, int line)
55 {
56     std::fprintf(stderr, "Error: ");
57     switch (err)
58     {
59         case eNOVALS: std::fprintf(stderr, "Not enough values for %s", s); break;
60         case eGRIDEXP: std::fprintf(stderr, "'grid' expected instead of %s", s); break;
61         case eACCOEXP: std::fprintf(stderr, "'{' expected instead of %s", s); break;
62         case eACCCEXP: std::fprintf(stderr, "'}' expected instead of %s", s); break;
63         case eGRPEXP: std::fprintf(stderr, "'group' expected instead of %s", s); break;
64         case eITEMEXP: std::fprintf(stderr, "item expected instead of %s", s); break;
65         case eSAMEPOINT: std::fprintf(stderr, "grid point for %s already in use", s); break;
66         case eTOOWIDE: std::fprintf(stderr, "grid too wide for %s", s); break;
67         case eTOOHIGH: std::fprintf(stderr, "grid too high for %s", s); break;
68         case eQUOTE: std::fprintf(stderr, "quote expected instead of %s", s); break;
69         default: std::fprintf(stderr, "????"); break;
70     }
71     std::fprintf(stderr, " in file %s\n", infile);
72     std::fprintf(stderr, "source file: %s, line: %d\n", file, line);
73     std::exit(1);
74 }
75
76 #define ReadDlgErr(in, er, es) ReadDlgError(in, er, es, __FILE__, __LINE__)
77
78 static void ReadAccOpen(const char* infile, FILE* in)
79 {
80     char buf[STRLEN];
81     int  result;
82
83     result = std::fscanf(in, "%4s", buf);
84     if ((1 != result) || std::strcmp(buf, "{") != 0)
85     {
86         ReadDlgErr(infile, eACCOEXP, buf);
87     }
88 }
89
90 static void ReadAccClose(const char* infile, FILE* in)
91 {
92     char buf[STRLEN];
93     int  result;
94
95     result = std::fscanf(in, "%4s", buf);
96     if ((1 != result) || std::strcmp(buf, "}") != 0)
97     {
98         ReadDlgErr(infile, eACCCEXP, buf);
99     }
100 }
101
102 void ReadQuoteString(const char* infile, FILE* in, char* buf)
103 {
104     char c[2];
105     int  i = 0;
106
107     /* Read until first quote */
108     while ((c[0] = std::fgetc(in)) != '"')
109     {
110         if (!std::isspace(c[0]))
111         {
112             c[1] = '\0';
113             ReadDlgErr(infile, eQUOTE, c);
114         }
115     }
116     /* Read until second quote */
117     while ((c[0] = std::fgetc(in)) != '"')
118     {
119         buf[i++] = c[0];
120     }
121     buf[i] = '\0';
122 }
123
124 static void ReadQuoteStringOrAccClose(FILE* in, char* buf)
125 {
126     char c;
127     int  i = 0;
128
129     /* Read until first quote */
130     do
131     {
132         c = std::fgetc(in);
133         if (c == '}')
134         {
135             buf[0] = c;
136             buf[1] = '\0';
137             return;
138         }
139     } while (c != '"');
140
141     /* Read until second quote */
142     while ((c = std::fgetc(in)) != '"')
143     {
144         buf[i++] = c;
145     }
146     buf[i] = '\0';
147 }
148
149 static bool bNotAccClose(const char* buf)
150 {
151     return (std::strcmp(buf, "}") != 0);
152 }
153
154 static t_fitem* NewFItem(void)
155 {
156     t_fitem* fitem;
157
158     snew(fitem, 1);
159     fitem->nname = 0;
160     fitem->name  = nullptr;
161     fitem->set   = nullptr;
162     fitem->get   = nullptr;
163     fitem->def   = nullptr;
164     fitem->help  = nullptr;
165
166     return fitem;
167 }
168
169 static t_fsimple* NewFSimple(void)
170 {
171     t_fsimple* fsimple;
172
173     snew(fsimple, 1);
174
175     return fsimple;
176 }
177
178 static void AddFItemName(t_fitem* fitem, char* name)
179 {
180     srenew(fitem->name, ++fitem->nname);
181     fitem->name[fitem->nname - 1] = gmx_strdup(name);
182 }
183
184 static t_fgroup* NewFGroup(void)
185 {
186     t_fgroup* fgroup;
187
188     snew(fgroup, 1);
189     fgroup->name   = nullptr;
190     fgroup->nfitem = 0;
191     fgroup->fitem  = nullptr;
192
193     return fgroup;
194 }
195
196 static void AddFGroupFItem(t_fgroup* fgroup, t_fitem* fitem)
197 {
198     srenew(fgroup->fitem, ++fgroup->nfitem);
199     fgroup->fitem[fgroup->nfitem - 1] = fitem;
200 }
201
202 static t_fgroup* AddFGridFGroup(t_fgrid* fgrid)
203 {
204     srenew(fgrid->fgroup, ++fgrid->nfgroup);
205     fgrid->fgroup[fgrid->nfgroup - 1] = NewFGroup();
206     return fgrid->fgroup[fgrid->nfgroup - 1];
207 }
208
209 static t_fsimple* AddFGridFSimple(t_fgrid* fgrid)
210 {
211     srenew(fgrid->fsimple, ++fgrid->nfsimple);
212     fgrid->fsimple[fgrid->nfsimple - 1] = NewFSimple();
213     return fgrid->fsimple[fgrid->nfsimple - 1];
214 }
215
216 static t_fgrid* NewFGrid(void)
217 {
218     t_fgrid* fgrid;
219
220     snew(fgrid, 1);
221     fgrid->w        = 0;
222     fgrid->h        = 0;
223     fgrid->nfgroup  = 0;
224     fgrid->fgroup   = nullptr;
225     fgrid->nfsimple = 0;
226     fgrid->fsimple  = nullptr;
227
228     return fgrid;
229 }
230
231 static void DoneFItem(t_fitem* fitem)
232 {
233     int i;
234
235     for (i = 0; (i < fitem->nname); i++)
236     {
237         sfree(fitem->name[i]);
238     }
239     sfree(fitem->name);
240     sfree(fitem->set);
241     sfree(fitem->get);
242     sfree(fitem->def);
243     sfree(fitem->help);
244 }
245
246 static void DoneFGroup(t_fgroup* fgroup)
247 {
248     int i;
249
250     sfree(fgroup->name);
251     for (i = 0; (i < fgroup->nfitem); i++)
252     {
253         DoneFItem(fgroup->fitem[i]);
254     }
255     sfree(fgroup->fitem);
256 }
257
258 static void DoneFSimple(t_fsimple* fsimple)
259 {
260     DoneFItem(fsimple->fitem);
261     sfree(fsimple->fitem);
262 }
263
264 void DoneFGrid(t_fgrid* fgrid)
265 {
266     int i;
267
268     for (i = 0; (i < fgrid->nfgroup); i++)
269     {
270         DoneFGroup(fgrid->fgroup[i]);
271     }
272     sfree(fgrid->fgroup);
273     for (i = 0; (i < fgrid->nfsimple); i++)
274     {
275         DoneFSimple(fgrid->fsimple[i]);
276     }
277     sfree(fgrid->fsimple);
278 }
279
280 static t_fitem* ScanFItem(const char* infile, FILE* in, char* buf)
281 {
282     char     set[STRLEN], get[STRLEN], help[STRLEN], def[STRLEN];
283     int      edlg;
284     t_fitem* fitem;
285
286     fitem = NewFItem();
287
288     for (edlg = 0; (edlg < edlgNR + 1); edlg++)
289     {
290         if (std::strcmp(buf, type[edlg]) == 0)
291         {
292             break;
293         }
294     }
295     if (edlg == edlgNR)
296     {
297         /* Special case */
298         edlg        = edlgBN;
299         fitem->bDef = true;
300     }
301     if (edlg == edlgNR + 1)
302     {
303         ReadDlgErr(infile, eITEMEXP, buf);
304     }
305
306     fitem->edlg = (edlgitem)edlg;
307     switch (edlg)
308     {
309         case edlgBN:
310         case edlgCB:
311         case edlgET:
312             ReadQuoteString(infile, in, buf);
313             AddFItemName(fitem, buf);
314             break;
315         case edlgST:
316         case edlgRB:
317             ReadAccOpen(infile, in);
318             ReadQuoteStringOrAccClose(in, buf);
319             while (bNotAccClose(buf))
320             {
321                 AddFItemName(fitem, buf);
322                 ReadQuoteStringOrAccClose(in, buf);
323             }
324             break;
325         case edlgPM:
326         case edlgGB: ReadDlgErr(infile, eITEMEXP, type[edlg]); break;
327         default: break;
328     }
329     ReadQuoteString(infile, in, set);
330     ReadQuoteString(infile, in, get);
331     ReadQuoteString(infile, in, def);
332     ReadQuoteString(infile, in, help);
333     fitem->set  = gmx_strdup(set);
334     fitem->get  = gmx_strdup(get);
335     fitem->def  = gmx_strdup(def);
336     fitem->help = gmx_strdup(help);
337
338     return fitem;
339 }
340
341 t_fgrid* FGridFromFile(const char* infile)
342 {
343     char buf[STRLEN];
344     int  result;
345
346     t_fgrid*   fgrid;
347     t_fgroup*  fgroup;
348     t_fsimple* fsimple;
349     int        gridx, gridy;
350
351     gmx::FilePtr inGuard = gmx::openLibraryFile(infile);
352     FILE*        in      = inGuard.get();
353     result               = std::fscanf(in, "%6s", buf);
354     if ((1 != result) || std::strcmp(buf, "grid") != 0)
355     {
356         ReadDlgErr(infile, eGRIDEXP, buf);
357     }
358     fgrid = NewFGrid();
359     if ((fscanf(in, "%5d%5d", &gridx, &gridy)) != 2)
360     {
361         ReadDlgErr(infile, eNOVALS, "grid w,h");
362     }
363     fgrid->w = gridx;
364     fgrid->h = gridy;
365     ReadAccOpen(infile, in);
366     result = std::fscanf(in, "%15s", buf);
367     while ((1 == result) && bNotAccClose(buf))
368     {
369         if (strcmp(buf, "group") == 0)
370         {
371             fgroup = AddFGridFGroup(fgrid);
372             ReadQuoteString(infile, in, buf);
373             fgroup->name = gmx_strdup(buf);
374             if ((fscanf(in, "%5d%5d%5d%5d", &fgroup->x, &fgroup->y, &fgroup->w, &fgroup->h)) != 4)
375             {
376                 ReadDlgErr(infile, eNOVALS, "group x,y,w,h");
377             }
378             if (fgroup->x + fgroup->w > gridx)
379             {
380                 ReadDlgErr(infile, eTOOWIDE, buf);
381             }
382             if (fgroup->y + fgroup->h > gridy)
383             {
384                 ReadDlgErr(infile, eTOOHIGH, buf);
385             }
386             ReadAccOpen(infile, in);
387             result = std::fscanf(in, "%15s", buf);
388             while ((1 == result) && bNotAccClose(buf))
389             {
390                 AddFGroupFItem(fgroup, ScanFItem(infile, in, buf));
391                 result = std::fscanf(in, "%15s", buf);
392             }
393         }
394         else if (strcmp(buf, "simple") == 0)
395         {
396             fsimple = AddFGridFSimple(fgrid);
397             if ((fscanf(in, "%5d%5d%5d%5d", &fsimple->x, &fsimple->y, &fsimple->w, &fsimple->h)) != 4)
398             {
399                 ReadDlgErr(infile, eNOVALS, "simple x,y,w,h");
400             }
401             if (fsimple->x + fsimple->w > gridx)
402             {
403                 ReadDlgErr(infile, eTOOWIDE, "simple");
404             }
405             if (fsimple->y + fsimple->h > gridy)
406             {
407                 ReadDlgErr(infile, eTOOHIGH, "simple");
408             }
409             ReadAccOpen(infile, in);
410             result = std::fscanf(in, "%15s", buf);
411             if (1 == result)
412             {
413                 fsimple->fitem = ScanFItem(infile, in, buf);
414                 ReadAccClose(infile, in);
415             }
416         }
417         if (1 == result)
418         {
419             result = std::fscanf(in, "%15s", buf);
420         }
421     }
422     /* Since we always read one variable at a time the result from
423      * fscanf should always be 1.
424      */
425     if (1 != result)
426     {
427         ReadDlgErr(infile, eNOVALS, "fgrid");
428     }
429
430     return fgrid;
431 }
432
433 static void DumpFItem(t_fitem* fitem)
434 {
435     int i;
436
437     std::printf("  type: %s, set: '%s', get: '%s', def: '%s', help: '%s'\n  {",
438                 type[fitem->edlg],
439                 fitem->set,
440                 fitem->get,
441                 fitem->def,
442                 fitem->help);
443     for (i = 0; (i < fitem->nname); i++)
444     {
445         std::printf("  '%s'", fitem->name[i]);
446     }
447     std::printf("  }\n");
448 }
449
450 static void DumpFSimple(t_fsimple* fsimple)
451 {
452     std::printf("Simple %dx%d at %d,%d\n", fsimple->w, fsimple->h, fsimple->x, fsimple->y);
453     DumpFItem(fsimple->fitem);
454 }
455
456 static void DumpFGroup(t_fgroup* fgroup)
457 {
458     int i;
459
460     std::printf("Group %dx%d at %d,%d\n", fgroup->w, fgroup->h, fgroup->x, fgroup->y);
461     for (i = 0; (i < fgroup->nfitem); i++)
462     {
463         DumpFItem(fgroup->fitem[i]);
464     }
465 }
466
467 void DumpFGrid(t_fgrid* fgrid)
468 {
469     int i;
470
471     std::printf("Grid %dx%d\n", fgrid->w, fgrid->h);
472     for (i = 0; (i < fgrid->nfgroup); i++)
473     {
474         DumpFGroup(fgrid->fgroup[i]);
475     }
476     for (i = 0; (i < fgrid->nfsimple); i++)
477     {
478         DumpFSimple(fgrid->fsimple[i]);
479     }
480 }