2 * This file is part of the GROMACS molecular simulation package.
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,2019, 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.
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.
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.
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.
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.
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.
46 #include "gromacs/utility/cstringutil.h"
47 #include "gromacs/utility/futil.h"
48 #include "gromacs/utility/smalloc.h"
50 static const char* type[] = { "button", "radiobuttons", "groupbox", "checkbox",
51 "pixmap", "statictext", "edittext", "defbutton" };
53 static void ReadDlgError(const char* infile, eDLGERR err, const char* s, const char* file, int line)
55 std::fprintf(stderr, "Error: ");
58 case eNOVALS: std::fprintf(stderr, "Not enough values for %s", s); break;
59 case eGRIDEXP: std::fprintf(stderr, "'grid' expected instead of %s", s); break;
60 case eACCOEXP: std::fprintf(stderr, "'{' expected instead of %s", s); break;
61 case eACCCEXP: std::fprintf(stderr, "'}' expected instead of %s", s); break;
62 case eGRPEXP: std::fprintf(stderr, "'group' expected instead of %s", s); break;
63 case eITEMEXP: std::fprintf(stderr, "item expected instead of %s", s); break;
64 case eSAMEPOINT: std::fprintf(stderr, "grid point for %s already in use", s); break;
65 case eTOOWIDE: std::fprintf(stderr, "grid too wide for %s", s); break;
66 case eTOOHIGH: std::fprintf(stderr, "grid too high for %s", s); break;
67 case eQUOTE: std::fprintf(stderr, "quote expected instead of %s", s); break;
68 default: std::fprintf(stderr, "????"); break;
70 std::fprintf(stderr, " in file %s\n", infile);
71 std::fprintf(stderr, "source file: %s, line: %d\n", file, line);
75 #define ReadDlgErr(in, er, es) ReadDlgError(in, er, es, __FILE__, __LINE__)
77 static void ReadAccOpen(const char* infile, FILE* in)
82 result = std::fscanf(in, "%4s", buf);
83 if ((1 != result) || std::strcmp(buf, "{") != 0)
85 ReadDlgErr(infile, eACCOEXP, buf);
89 static void ReadAccClose(const char* infile, FILE* in)
94 result = std::fscanf(in, "%4s", buf);
95 if ((1 != result) || std::strcmp(buf, "}") != 0)
97 ReadDlgErr(infile, eACCCEXP, buf);
101 void ReadQuoteString(const char* infile, FILE* in, char* buf)
106 /* Read until first quote */
107 while ((c[0] = std::fgetc(in)) != '"')
109 if (!std::isspace(c[0]))
112 ReadDlgErr(infile, eQUOTE, c);
115 /* Read until second quote */
116 while ((c[0] = std::fgetc(in)) != '"')
123 static void ReadQuoteStringOrAccClose(FILE* in, char* buf)
128 /* Read until first quote */
140 /* Read until second quote */
141 while ((c = std::fgetc(in)) != '"')
148 static bool bNotAccClose(const char* buf)
150 return (std::strcmp(buf, "}") != 0);
153 static t_fitem* NewFItem(void)
159 fitem->name = nullptr;
160 fitem->set = nullptr;
161 fitem->get = nullptr;
162 fitem->def = nullptr;
163 fitem->help = nullptr;
168 static t_fsimple* NewFSimple(void)
177 static void AddFItemName(t_fitem* fitem, char* name)
179 srenew(fitem->name, ++fitem->nname);
180 fitem->name[fitem->nname - 1] = gmx_strdup(name);
183 static t_fgroup* NewFGroup(void)
188 fgroup->name = nullptr;
190 fgroup->fitem = nullptr;
195 static void AddFGroupFItem(t_fgroup* fgroup, t_fitem* fitem)
197 srenew(fgroup->fitem, ++fgroup->nfitem);
198 fgroup->fitem[fgroup->nfitem - 1] = fitem;
201 static t_fgroup* AddFGridFGroup(t_fgrid* fgrid)
203 srenew(fgrid->fgroup, ++fgrid->nfgroup);
204 fgrid->fgroup[fgrid->nfgroup - 1] = NewFGroup();
205 return fgrid->fgroup[fgrid->nfgroup - 1];
208 static t_fsimple* AddFGridFSimple(t_fgrid* fgrid)
210 srenew(fgrid->fsimple, ++fgrid->nfsimple);
211 fgrid->fsimple[fgrid->nfsimple - 1] = NewFSimple();
212 return fgrid->fsimple[fgrid->nfsimple - 1];
215 static t_fgrid* NewFGrid(void)
223 fgrid->fgroup = nullptr;
225 fgrid->fsimple = nullptr;
230 static void DoneFItem(t_fitem* fitem)
234 for (i = 0; (i < fitem->nname); i++)
236 sfree(fitem->name[i]);
245 static void DoneFGroup(t_fgroup* fgroup)
250 for (i = 0; (i < fgroup->nfitem); i++)
252 DoneFItem(fgroup->fitem[i]);
254 sfree(fgroup->fitem);
257 static void DoneFSimple(t_fsimple* fsimple)
259 DoneFItem(fsimple->fitem);
260 sfree(fsimple->fitem);
263 void DoneFGrid(t_fgrid* fgrid)
267 for (i = 0; (i < fgrid->nfgroup); i++)
269 DoneFGroup(fgrid->fgroup[i]);
271 sfree(fgrid->fgroup);
272 for (i = 0; (i < fgrid->nfsimple); i++)
274 DoneFSimple(fgrid->fsimple[i]);
276 sfree(fgrid->fsimple);
279 static t_fitem* ScanFItem(const char* infile, FILE* in, char* buf)
281 char set[STRLEN], get[STRLEN], help[STRLEN], def[STRLEN];
287 for (edlg = 0; (edlg < edlgNR + 1); edlg++)
289 if (std::strcmp(buf, type[edlg]) == 0)
300 if (edlg == edlgNR + 1)
302 ReadDlgErr(infile, eITEMEXP, buf);
305 fitem->edlg = (edlgitem)edlg;
311 ReadQuoteString(infile, in, buf);
312 AddFItemName(fitem, buf);
316 ReadAccOpen(infile, in);
317 ReadQuoteStringOrAccClose(in, buf);
318 while (bNotAccClose(buf))
320 AddFItemName(fitem, buf);
321 ReadQuoteStringOrAccClose(in, buf);
325 case edlgGB: ReadDlgErr(infile, eITEMEXP, type[edlg]); break;
328 ReadQuoteString(infile, in, set);
329 ReadQuoteString(infile, in, get);
330 ReadQuoteString(infile, in, def);
331 ReadQuoteString(infile, in, help);
332 fitem->set = gmx_strdup(set);
333 fitem->get = gmx_strdup(get);
334 fitem->def = gmx_strdup(def);
335 fitem->help = gmx_strdup(help);
340 t_fgrid* FGridFromFile(const char* infile)
350 gmx::FilePtr inGuard = gmx::openLibraryFile(infile);
351 FILE* in = inGuard.get();
352 result = std::fscanf(in, "%6s", buf);
353 if ((1 != result) || std::strcmp(buf, "grid") != 0)
355 ReadDlgErr(infile, eGRIDEXP, buf);
358 if ((fscanf(in, "%5d%5d", &gridx, &gridy)) != 2)
360 ReadDlgErr(infile, eNOVALS, "grid w,h");
364 ReadAccOpen(infile, in);
365 result = std::fscanf(in, "%15s", buf);
366 while ((1 == result) && bNotAccClose(buf))
368 if (strcmp(buf, "group") == 0)
370 fgroup = AddFGridFGroup(fgrid);
371 ReadQuoteString(infile, in, buf);
372 fgroup->name = gmx_strdup(buf);
373 if ((fscanf(in, "%5d%5d%5d%5d", &fgroup->x, &fgroup->y, &fgroup->w, &fgroup->h)) != 4)
375 ReadDlgErr(infile, eNOVALS, "group x,y,w,h");
377 if (fgroup->x + fgroup->w > gridx)
379 ReadDlgErr(infile, eTOOWIDE, buf);
381 if (fgroup->y + fgroup->h > gridy)
383 ReadDlgErr(infile, eTOOHIGH, buf);
385 ReadAccOpen(infile, in);
386 result = std::fscanf(in, "%15s", buf);
387 while ((1 == result) && bNotAccClose(buf))
389 AddFGroupFItem(fgroup, ScanFItem(infile, in, buf));
390 result = std::fscanf(in, "%15s", buf);
393 else if (strcmp(buf, "simple") == 0)
395 fsimple = AddFGridFSimple(fgrid);
396 if ((fscanf(in, "%5d%5d%5d%5d", &fsimple->x, &fsimple->y, &fsimple->w, &fsimple->h)) != 4)
398 ReadDlgErr(infile, eNOVALS, "simple x,y,w,h");
400 if (fsimple->x + fsimple->w > gridx)
402 ReadDlgErr(infile, eTOOWIDE, "simple");
404 if (fsimple->y + fsimple->h > gridy)
406 ReadDlgErr(infile, eTOOHIGH, "simple");
408 ReadAccOpen(infile, in);
409 result = std::fscanf(in, "%15s", buf);
412 fsimple->fitem = ScanFItem(infile, in, buf);
413 ReadAccClose(infile, in);
418 result = std::fscanf(in, "%15s", buf);
421 /* Since we always read one variable at a time the result from
422 * fscanf should always be 1.
426 ReadDlgErr(infile, eNOVALS, "fgrid");
432 static void DumpFItem(t_fitem* fitem)
436 std::printf(" type: %s, set: '%s', get: '%s', def: '%s', help: '%s'\n {", type[fitem->edlg],
437 fitem->set, fitem->get, fitem->def, fitem->help);
438 for (i = 0; (i < fitem->nname); i++)
440 std::printf(" '%s'", fitem->name[i]);
445 static void DumpFSimple(t_fsimple* fsimple)
447 std::printf("Simple %dx%d at %d,%d\n", fsimple->w, fsimple->h, fsimple->x, fsimple->y);
448 DumpFItem(fsimple->fitem);
451 static void DumpFGroup(t_fgroup* fgroup)
455 std::printf("Group %dx%d at %d,%d\n", fgroup->w, fgroup->h, fgroup->x, fgroup->y);
456 for (i = 0; (i < fgroup->nfitem); i++)
458 DumpFItem(fgroup->fitem[i]);
462 void DumpFGrid(t_fgrid* fgrid)
466 std::printf("Grid %dx%d\n", fgrid->w, fgrid->h);
467 for (i = 0; (i < fgrid->nfgroup); i++)
469 DumpFGroup(fgrid->fgroup[i]);
471 for (i = 0; (i < fgrid->nfsimple); i++)
473 DumpFSimple(fgrid->fsimple[i]);