ARB
GDE_ParseMenu.cxx
Go to the documentation of this file.
1 #include "GDE_proto.h"
2 
3 #include <aw_window.hxx>
4 #include <MultiFileReader.h>
5 #include <arb_file.h>
6 
7 #include <cctype>
8 
9 /*
10  Copyright (c) 1989, University of Illinois board of trustees. All rights
11  reserved. Written by Steven Smith at the Center for Prokaryote Genome
12  Analysis. Design and implementation guidance by Dr. Gary Olsen and Dr.
13  Carl Woese.
14 
15  Copyright (c) 1990,1991,1992 Steven Smith at the Harvard Genome Laboratory.
16  All rights reserved.
17 
18  Changed to fit into ARB by ARB development team.
19 */
20 
21 
22 inline bool only_whitespace(const char *line) {
23  size_t white = strspn(line, " \t");
24  return line[white] == 0; // only 0 after leading whitespace
25 }
26 
27 static char *readableItemname(const GmenuItem& i) {
28  return GBS_global_string_copy("%s/%s", i.parent_menu->label, i.label);
29 }
30 
31 inline __ATTR__NORETURN void throwError(const char *msg) {
32  throw string(msg);
33 }
34 
35 static __ATTR__NORETURN void throwParseError(const char *msg, const LineReader& file) {
36  fprintf(stderr, "\n%s:%zu: %s\n", file.getFilename().c_str(), file.getLineNumber(), msg);
37  fflush(stderr);
38  throwError(msg);
39 }
40 
41 static __ATTR__NORETURN void throwItemError(const GmenuItem& i, const char *error, const LineReader& file) {
42  char *itemName = readableItemname(i);
43  const char *msg = GBS_global_string("[Above this line] Invalid item '%s' defined: %s", itemName, error);
44  free(itemName);
45  throwParseError(msg, file);
46 }
47 
48 static void CheckItemConsistency(const GmenuItem *item, const LineReader& file) {
49  // (incomplete) consistency check.
50  // bailing out with ItemError() here, will make unit-test and arb-startup fail!
51 
52  if (item) {
53  const GmenuItem& I = *item;
54  if (I.seqtype != '-' && I.numinputs<1) {
55  // Such an item would create a window where alignment/species selection is present,
56  // but no sequence export will take place.
57  //
58  // Pressing 'GO' would result in failure or deadlock.
59  throwItemError(I, "item defines seqtype ('seqtype:' <> '-'), but is lacking input-specification ('in:')", file);
60  }
61  if (I.seqtype == '-' && I.numinputs>0) {
62  // Such an item would create a window where alignment/species selection has no GUI-elements,
63  // but sequences are exported (generating a corrupt sequence file)
64  //
65  // Pressing 'GO' would result in failure.
66  throwItemError(I, "item defines no seqtype ('seqtype:' = '-'), but defines input-specification ('in:')", file);
67  }
68  }
69 }
70 
71 #define THROW_IF_NO(ptr,name) do { if (!ptr) throwParseError(GBS_global_string("'%s' used w/o '" name "'", head), in); } while(0)
72 
73 #define THROW_IF_NO_MENU() THROW_IF_NO(thismenu, "menu")
74 #define THROW_IF_NO_ITEM() THROW_IF_NO(thisitem, "item")
75 #define THROW_IF_NO_ARG() THROW_IF_NO(thisarg, "arg")
76 #define THROW_IF_NO_INPUT() THROW_IF_NO(thisinput, "in")
77 #define THROW_IF_NO_OUTPUT() THROW_IF_NO(thisoutput, "out")
78 
79 // --------------------------------------------------------------------------------
80 
81 inline const char *truncate_4000(const char *str) {
82  const int BUFSIZE = 4000;
83  static char buffer[BUFSIZE];
84  strcpy_truncate(buffer, str, BUFSIZE);
85  return buffer;
86 }
87 
88 inline void trim(char *str) {
89  int s = 0;
90  int d = 0;
91 
92  while (isspace(str[s])) ++s;
93  while (str[s]) str[d++] = str[s++];
94 
95  str[d] = 0;
96  while (d>0 && isspace(str[d-1])) str[--d] = 0;
97 }
98 
99 static void splitEntry(const char *input, char *head, char *tail) {
102  const char *colon = strchr(input, ':');
103  if (colon) {
104  int len = colon-input;
105  memcpy(head, input, len);
106  head[len] = 0;
107 
108  strcpy(tail, colon+1);
109 
110  trim(tail);
111  }
112  else {
113  strcpy(head, input);
114  }
115  trim(head);
116 }
117 
118 // --------------------------------------------------------------------------------
119 
120 static void ParseMenus(LineReader& in) {
121  /* parses menus via LineReader (contains ALL found menu-files) and
122  * assemble an internal representation of the menu/menu-item hierarchy.
123  *
124  * please document changes in ../HELP_SOURCE/source/gde_menus.hlp
125  */
126 
127  memset((char*)&menu[0], 0, sizeof(Gmenu)*GDEMAXMENU);
128 
129  int curarg = 0;
130  int curinput = 0;
131  int curoutput = 0;
132 
133  Gmenu *thismenu = NULp;
134  GmenuItem *thisitem = NULp;
135  GmenuItemArg *thisarg = NULp;
136  GfileFormat *thisinput = NULp;
137  GfileFormat *thisoutput = NULp;
138 
139  bool thismenu_firstOccurrence = true;
140 
141  int j;
142  char temp[GBUFSIZ];
143  char head[GBUFSIZ];
144  char tail[GBUFSIZ];
145 
146  string lineStr;
147 
148  while (in.getLine(lineStr)) {
149  gde_assert(lineStr.length()<GBUFSIZ); // otherwise buffer usage may fail
150 
151  const char *in_line = lineStr.c_str();
152  if (in_line[0] == '#' || (in_line[0] && in_line[1] == '#')) {
153  ; // skip line
154  }
155  else if (only_whitespace(in_line)) {
156  ; // skip line
157  }
158  else {
159  splitEntry(in_line, head, temp);
160 
161  // menu: chooses menu to use (may occur multiple times with same label!)
162  if (strcmp(head, "menu") == 0) {
163  int curmenu = -1;
164  for (j=0; j<num_menus && curmenu == -1; j++) {
165  if (strcmp(temp, menu[j].label) == 0) curmenu=j;
166  }
167 
168  thismenu_firstOccurrence = curmenu == -1;
169 
170  // If menu not found, make a new one
171  if (thismenu_firstOccurrence) {
172  curmenu = num_menus++;
173  thismenu = &menu[curmenu];
174  thismenu->label = ARB_strdup(temp);
175  thismenu->numitems = 0;
176  thismenu->active_mask = AWM_ALL;
177  }
178  else {
179  thismenu = &menu[curmenu];
180  }
181 
182  CheckItemConsistency(thisitem, in);
183  thisitem = NULp;
184  thisarg = NULp;
185  thisoutput = NULp;
186  thisinput = NULp;
187  }
188  else if (strcmp(head, "menumask") == 0) {
190  AW_active wanted_mask = strcmp("expert", temp) == 0 ? AWM_EXP : AWM_ALL;
191  if (!thismenu_firstOccurrence && thismenu->active_mask != wanted_mask) {
192  throwParseError(GBS_global_string("menumask has inconsistent definitions (in different definitions of menu '%s')", thismenu->label), in);
193  }
194  thismenu->active_mask = wanted_mask;
195  }
196  else if (strcmp(head, "menumeta") == 0) {
198  char wanted_meta = temp[0];
199  if (!thismenu_firstOccurrence && thismenu->meta != wanted_meta) {
200  if (wanted_meta != 0) {
201  if (thismenu->meta != 0) {
202  throwParseError(GBS_global_string("menumeta has inconsistent definitions (in different definitions of menu '%s')", thismenu->label), in);
203  }
204  else {
205  thismenu->meta = wanted_meta;
206  }
207  }
208  }
209  else {
210  thismenu->meta = wanted_meta;
211  }
212  }
213  // item: chooses menu item to use
214  else if (strcmp(head, "item") == 0) {
215  CheckItemConsistency(thisitem, in);
216 
218 
219  curarg = -1;
220  curinput = -1;
221  curoutput = -1;
222 
223  int curitem = thismenu->numitems++;
224 
225  // Resize the item list for this menu (add one item)
226  if (curitem == 0) {
227  ARB_alloc(thismenu->item, 1);
228  }
229  else {
230  ARB_realloc(thismenu->item, thismenu->numitems);
231  }
232 
233  thisitem = &(thismenu->item[curitem]);
234 
235  thisitem->numargs = 0;
236  thisitem->numoutputs = 0;
237  thisitem->numinputs = 0;
238  thisitem->label = ARB_strdup(temp);
239  thisitem->method = NULp;
240  thisitem->input = NULp;
241  thisitem->output = NULp;
242  thisitem->arg = NULp;
243  thisitem->meta = '\0';
244  thisitem->seqtype = '-'; // no default sequence export
245  thisitem->aligned = false;
246  thisitem->help = NULp;
247 
248  thisitem->parent_menu = thismenu;
249  thisitem->aws = NULp; // no window opened yet
250  thisitem->active_mask = AWM_ALL;
251  thisitem->popup = NULp;
252 
253  for (int i = 0; i<curitem; ++i) {
254  if (strcmp(thismenu->item[i].label, thisitem->label) == 0) {
255  throwParseError(GBS_global_string("Duplicated item label '%s'", thisitem->label), in);
256  }
257  }
258 
259  thisarg = NULp;
260  }
261 
262  // itemmethod: generic command line generated by this item
263  else if (strcmp(head, "itemmethod") == 0) {
265  ARB_calloc(thisitem->method, strlen(temp)+1);
266 
267  {
268  char *to = thisitem->method;
269  char *from = temp;
270  char last = 0;
271  char c;
272 
273  do {
274  c = *from++;
275  if (c == '@' && last == '@') {
276  // replace "@@" with "'"
277  // [WHY_USE_DOUBLE_AT]
278  // - cant use 1 single quote ("'"). Things inside will not be preprocessed correctly.
279  // - cant use 2 single quotes ("''") any longer. clang fails on OSX.
280  to[-1] = '\'';
281  }
282  else {
283  *to++ = c;
284  }
285  last = c;
286  }
287  while (c!=0);
288  }
289 
290  }
291  // Help file
292  else if (strcmp(head, "itemhelp") == 0) {
294  if (thisitem->help) throwParseError("duplicated 'itemhelp' entry", in);
295  thisitem->help = GBS_string_eval(temp, "*.help=agde_*1.hlp");
296  }
297  // Meta key equiv
298  else if (strcmp(head, "itemmeta") == 0) {
300  if (thisitem->meta) throwParseError("duplicated 'itemmeta' entry", in);
301  thisitem->meta = temp[0];
302  }
303  else if (strcmp(head, "itemmask") == 0) {
305  if (strcmp("expert", temp) == 0) thisitem->active_mask = AWM_EXP;
306  }
307  // Sequence type restriction
308  else if (strcmp(head, "seqtype") == 0) {
310  thisitem->seqtype = toupper(temp[0]);
311  /* 'A' -> amino acids,
312  * 'N' -> nucleotides,
313  * '-' -> don't select sequences,
314  * otherwise any alignment
315  */
316  }
317  /* arg: defines the symbol for a command line argument.
318  * this is used for substitution into the itemmethod
319  * definition.
320  */
321 
322  else if (strcmp(head, "arg") == 0) {
324 
325  curarg = thisitem->numargs++;
326  ARB_recalloc(thisitem->arg, curarg, thisitem->numargs);
327 
328  thisarg = &(thisitem->arg[curarg]);
329 
330  thisarg->symbol = ARB_strdup(temp);
331  thisarg->type = 0;
332  thisarg->min = 0.0;
333  thisarg->max = 0.0;
334  thisarg->numchoices = 0;
335  thisarg->choice = NULp;
336  thisarg->textvalue = NULp;
337  thisarg->ivalue = 0;
338  thisarg->fvalue = 0.0;
339  thisarg->label = NULp;
340  thisarg->active_mask = AWM_ALL;
341  }
342  // argtype: Defines the type of argument (menu,chooser, text, slider)
343  else if (strcmp(head, "argtype") == 0) {
344  THROW_IF_NO_ARG();
345  int arglen = -1;
346  if (strncmp(temp, "text", (arglen = 4)) == 0) {
347  thisarg->type = TEXTFIELD;
348  freedup(thisarg->textvalue, "");
349 
350  if (temp[arglen] == 0) thisarg->textwidth = TEXTFIELDWIDTH; // only 'text'
351  else {
352  if (temp[arglen] != '(' || temp[strlen(temp)-1] != ')') {
353  sprintf(head, "Unknown argtype '%s' -- syntax: text(width) e.g. text(20)", truncate_4000(temp));
354  throwParseError(head, in);
355  }
356  thisarg->textwidth = atoi(temp+arglen+1);
357  if (thisarg->textwidth<1) {
358  sprintf(head, "Illegal textwidth specified in '%s'", truncate_4000(temp));
359  throwParseError(head, in);
360  }
361  }
362  }
363  else if (strcmp(temp, "choice_list") == 0) thisarg->type = CHOICE_LIST;
364  else if (strcmp(temp, "choice_menu") == 0) thisarg->type = CHOICE_MENU;
365  else if (strcmp(temp, "chooser") == 0) thisarg->type = CHOOSER;
366  else if (strcmp(temp, "filename") == 0) {
367  thisarg->type = FILE_SELECTOR;
368  freedup(thisarg->textvalue, "");
369  }
370  else if (strcmp(temp, "sai") == 0) thisarg->type = CHOICE_SAI;
371  else if (strcmp(temp, "slider") == 0) thisarg->type = SLIDER;
372  else if (strcmp(temp, "tree") == 0) thisarg->type = CHOICE_TREE;
373  else if (strcmp(temp, "weights") == 0) thisarg->type = CHOICE_WEIGHTS;
374  else {
375  sprintf(head, "Unknown argtype '%s'", truncate_4000(temp));
376  throwParseError(head, in);
377  }
378  }
379  /* argtext: The default text value of the symbol.
380  * $argument is replaced by this value if it is not
381  * changed in the dialog box by the user.
382  */
383  else if (strcmp(head, "argtext") == 0) {
384  THROW_IF_NO_ARG();
385  freedup(thisarg->textvalue, temp);
386  }
387  /* arglabel: Text label displayed in the dialog box for
388  * this argument. It should be a descriptive label.
389  */
390  else if (strcmp(head, "arglabel") == 0) {
391  THROW_IF_NO_ARG();
392  thisarg->label = GBS_string_eval(temp, "\\\\n=\\n");
393  }
394  /* Argument choice values use the following notation:
395  *
396  * argchoice:Displayed value:Method
397  *
398  * Where "Displayed value" is the label displayed in the dialog box
399  * and "Method" is the value passed back on the command line.
400  */
401  else if (strcmp(head, "argchoice") == 0) {
402  THROW_IF_NO_ARG();
403  splitEntry(temp, head, tail);
404 
405  int curchoice = thisarg->numchoices++;
406  ARB_recalloc(thisarg->choice, curchoice, thisarg->numchoices);
407 
408  thisarg->choice[curchoice].label = ARB_strdup(head);
409  thisarg->choice[curchoice].method = ARB_strdup(tail);
410  }
411  // argmin: Minimum value for a slider
412  else if (strcmp(head, "argmin") == 0) {
413  THROW_IF_NO_ARG();
414  (void)sscanf(temp, "%lf", &(thisarg->min));
415  }
416  // argmax: Maximum value for a slider
417  else if (strcmp(head, "argmax") == 0) {
418  THROW_IF_NO_ARG();
419  (void)sscanf(temp, "%lf", &(thisarg->max));
420  }
421  // argvalue: default value for a slider
422  else if (strcmp(head, "argvalue") == 0) {
423  THROW_IF_NO_ARG();
424  if (thisarg->type == TEXT) {
425  freedup(thisarg->textvalue, temp);
426  }
427  else {
428  (void)sscanf(temp, "%lf", &(thisarg->fvalue));
429  thisarg->ivalue = (int) thisarg->fvalue;
430  }
431  }
432  else if (strcmp(head, "argmask") == 0) {
433  THROW_IF_NO_ARG();
434  if (strcmp("expert", temp) == 0) thisarg->active_mask = AWM_EXP;
435  }
436  // in: Input file description
437  else if (strcmp(head, "in") == 0) {
439 
440  curinput = (thisitem->numinputs)++;
441  ARB_recalloc(thisitem->input, curinput, thisitem->numinputs);
442 
443  thisinput = &(thisitem->input)[curinput];
444 
445  thisinput->save = false;
446  thisinput->format = 0;
447  thisinput->symbol = ARB_strdup(temp);
448  thisinput->name = NULp;
449  thisinput->typeinfo = BASIC_TYPEINFO;
450  }
451  else if (strcmp(head, "informat") == 0) {
453  if (Find(temp, "genbank")) thisinput->format = GENBANK;
454  else if (Find(temp, "flat")) thisinput->format = NA_FLAT;
455  else throwParseError(GBS_global_string("Unknown informat '%s' (allowed 'genbank' or 'flat')", temp), in);
456  }
457  else if (strcmp(head, "insave") == 0) {
459  thisinput->save = true;
460  }
461  else if (strcmp(head, "intyped") == 0) {
463  if (Find(temp, "detailed")) thisinput->typeinfo = DETAILED_TYPEINFO;
464  else if (Find(temp, "basic")) thisinput->typeinfo = BASIC_TYPEINFO;
465  else throwParseError(GBS_global_string("Unknown value '%s' for 'intyped' (known: 'detailed', 'basic')", temp), in);
466  }
467  // out: Output file description
468  else if (strcmp(head, "out") == 0) {
470 
471  curoutput = (thisitem->numoutputs)++;
472  ARB_recalloc(thisitem->output, curoutput, thisitem->numoutputs);
473 
474  thisoutput = &(thisitem->output)[curoutput];
475 
476  thisoutput->save = false;
477  thisoutput->format = 0;
478  thisoutput->symbol = ARB_strdup(temp);
479  thisoutput->name = NULp;
480  }
481  else if (strcmp(head, "outformat") == 0) {
483  if (Find(temp, "genbank")) thisoutput->format = GENBANK;
484  else if (Find(temp, "gde")) thisoutput->format = GDE;
485  else if (Find(temp, "flat")) thisoutput->format = NA_FLAT;
486  else throwParseError(GBS_global_string("Unknown outformat '%s' (allowed 'genbank', 'gde' or 'flat')", temp), in);
487  }
488  else if (strcmp(head, "outaligned") == 0) {
490  if (Find(temp, "yes")) thisitem->aligned = true;
491  else throwParseError(GBS_global_string("Unknown outaligned '%s' (allowed 'yes' or skip entry)", temp), in);
492  }
493  else if (strcmp(head, "outsave") == 0) {
495  thisoutput->save = true;
496  }
497  else {
498  throwParseError(GBS_global_string("No known GDE-menu-command found (line='%s')", in_line), in);
499  }
500  }
501  }
502 
503  CheckItemConsistency(thisitem, in);
504 
505  gde_assert(num_menus>0); // if this fails, the file arb.menu contained no menus (maybe file has zero size)
506 }
507 
514  GB_ERROR error = NULp;
515  StrArray files;
516  {
517  char *user_menu_dir = ARB_strdup(GB_path_in_arbprop("gde"));
518 
519  if (!GB_is_directory(user_menu_dir)) {
520  error = GB_create_directory(user_menu_dir);
521  }
523 
524  if (!error) {
525  GBS_read_dir(files, user_menu_dir, "/\\.menu$/");
526  GBS_read_dir(files, GB_path_in_ARBLIB("gde"), "/\\.menu$/");
527  error = GB_incur_error();
528  }
529 
530  free(user_menu_dir);
531  }
532 
533  if (!error) {
534  MultiFileReader menus(files);
535  error = menus.get_error();
536  if (!error) {
537  try {
538  ParseMenus(menus);
539  }
540  catch (const string& err) {
541  error = GBS_static_string(err.c_str());
542  }
543  }
544  }
545 
546  if (error) error = GBS_global_string("Error while loading menus: %s", error);
547  return error;
548 }
549 
550 bool Find(const char *target, const char *key) {
551  // Search the target string for the given key
552  return strstr(target, key) ? true : false;
553 }
554 
555 int Find2(const char *target, const char *key) {
556  /* Like Find(), but returns the index of the leftmost
557  * occurrence, and -1 if not found.
558  */
559  const char *found = strstr(target, key);
560  return found ? int(found-target) : -1;
561 }
562 
563 // --------------------------------------------------------------------------------
564 
565 #ifdef UNIT_TESTS
566 #ifndef TEST_UNIT_H
567 #include <test_unit.h>
568 #endif
569 
570 void TEST_load_menu() {
571  // very basic test: just detects failing assertions, crashes and errors
572 
573  gb_getenv_hook old = GB_install_getenv_hook(arb_test::fakeenv);
574  {
575  // ../UNIT_TESTER/run/homefake/
576 
578 
579  // basic check of loaded data (needs to be adapted if menus change):
581 
582  string menus;
583  string menuitems;
584  for (int m = 0; m<num_menus; ++m) {
585  menus = menus + menu[m].label + ";";
586  menuitems += GBS_global_string("%i;", menu[m].numitems);
587  }
588 
589  // if any of the following names changes = >
590  // you also need to change the title passed to the corresponding call to GDE_load_menu
591  // (otherwise a runtime error occurs)
592 
593  TEST_EXPECT_EQUAL(menus,
594  "Import;Export;Print;Align;SAI;Incremental phylogeny;Phylogeny Distance Matrix;"
595  "Phylogeny max. parsimony;Phylogeny max. Likelihood EXP;Phylogeny max. Likelihood;Phylogeny (Other);User;");
596 
597  TEST_EXPECT_EQUAL(menuitems, "3;1;2;10;1;1;3;2;1;8;6;0;");
598  }
599  TEST_EXPECT_EQUAL((void*)arb_test::fakeenv, (void*)GB_install_getenv_hook(old));
600 }
601 
602 #endif // UNIT_TESTS
603 
604 // --------------------------------------------------------------------------------
605 
static int I
Definition: align.cxx:489
const char * GB_ERROR
Definition: arb_core.h:25
AW_bitset AW_active
Definition: aw_base.hxx:45
static void CheckItemConsistency(const GmenuItem *item, const LineReader &file)
GB_CSTR GB_path_in_arbprop(const char *relative_path)
Definition: adsocket.cxx:1166
char * textvalue
Definition: GDE_menu.h:33
GB_ERROR GB_incur_error()
Definition: arb_msg.h:49
return string(buffer, length)
bool getLine(string &line)
char * symbol
Definition: GDE_menu.h:51
#define THROW_IF_NO_ARG()
GfileFormat * output
Definition: GDE_menu.h:63
#define THROW_IF_NO_OUTPUT()
int numargs
Definition: GDE_menu.h:57
char * method
Definition: GDE_menu.h:23
int numinputs
Definition: GDE_menu.h:59
double min
Definition: GDE_menu.h:29
#define CHOICE_TREE
Definition: GDE_def.h:23
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
int numitems
Definition: GDE_menu.h:78
char * label
Definition: GDE_menu.h:79
char * name
Definition: GDE_menu.h:52
bool save
Definition: GDE_menu.h:49
struct Gmenu * parent_menu
Definition: GDE_menu.h:71
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
#define CHOOSER
Definition: GDE_def.h:20
GfileFormat * input
Definition: GDE_menu.h:62
bool GB_have_error()
Definition: arb_msg.cxx:338
int num_menus
Definition: GDE.cxx:26
char * GBS_string_eval(const char *insource, const char *icommand)
Definition: admatch.cxx:699
char * method
Definition: GDE_menu.h:61
static void ParseMenus(LineReader &in)
NOT4PERL gb_getenv_hook GB_install_getenv_hook(gb_getenv_hook hook)
Definition: adsocket.cxx:699
AW_window * aws
Definition: GDE_menu.h:72
#define TEXTFIELDWIDTH
Definition: GDE_def.h:15
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
int ivalue
Definition: GDE_menu.h:28
char seqtype
Definition: GDE_menu.h:66
char * symbol
Definition: GDE_menu.h:36
#define GBUFSIZ
Definition: GDE_def.h:14
char * label
Definition: GDE_menu.h:60
static char * readableItemname(const GmenuItem &i)
size_t getLineNumber() const
GB_ERROR LoadMenus()
#define TEXT
Definition: GDE_def.h:43
fflush(stdout)
void strcpy_truncate(char *dest, const char *source, size_t dest_size)
Definition: GDE_def.h:137
#define THROW_IF_NO_MENU()
TYPE * ARB_alloc(size_t nelem)
Definition: arb_mem.h:56
char * label
Definition: GDE_menu.h:35
#define CHOICE_WEIGHTS
Definition: GDE_def.h:25
int numchoices
Definition: GDE_menu.h:32
static __ATTR__NORETURN void throwItemError(const GmenuItem &i, const char *error, const LineReader &file)
#define GDE
Definition: GDE_def.h:29
int textwidth
Definition: GDE_menu.h:34
int format
Definition: GDE_menu.h:50
static void error(const char *msg)
Definition: mkptypes.cxx:96
TypeInfo typeinfo
Definition: GDE_menu.h:53
#define FILE_SELECTOR
Definition: GDE_def.h:26
GmenuItem * item
Definition: GDE_menu.h:80
#define GDEMAXMENU
Definition: GDE_extglob.h:20
double max
Definition: GDE_menu.h:30
void ARB_recalloc(TYPE *&tgt, size_t oelem, size_t nelem)
Definition: arb_mem.h:49
int numoutputs
Definition: GDE_menu.h:58
static __ATTR__NORETURN void throwParseError(const char *msg, const LineReader &file)
GargChoice * choice
Definition: GDE_menu.h:37
int Find2(const char *target, const char *key)
const char *(* gb_getenv_hook)(const char *varname)
Definition: arbdb.h:138
GB_CSTR GB_path_in_ARBLIB(const char *relative_path)
Definition: adsocket.cxx:1156
WindowCallback * popup
Definition: GDE_menu.h:74
Definition: fun.h:13
void GBS_read_dir(StrArray &names, const char *dir, const char *mask)
Definition: adfile.cxx:213
void trim(char *str)
char * help
Definition: GDE_menu.h:68
GmenuItemArg * arg
Definition: GDE_menu.h:64
#define THROW_IF_NO_ITEM()
Gmenu menu[GDEMAXMENU]
Definition: GDE.cxx:25
bool Find(const char *target, const char *key)
#define CHOICE_MENU
Definition: GDE_def.h:21
virtual const string & getFilename() const =0
const char * truncate_4000(const char *str)
#define CHOICE_SAI
Definition: GDE_def.h:24
TYPE * ARB_calloc(size_t nelem)
Definition: arb_mem.h:81
#define NA_FLAT
Definition: GDE_def.h:31
double fvalue
Definition: GDE_menu.h:31
#define TEXTFIELD
Definition: GDE_def.h:18
bool GB_is_directory(const char *path)
Definition: arb_file.cxx:176
AW_active active_mask
Definition: GDE_menu.h:39
#define SLIDER
Definition: GDE_def.h:19
void ARB_realloc(TYPE *&tgt, size_t nelem)
Definition: arb_mem.h:43
const char * GBS_static_string(const char *str)
Definition: arb_msg.cxx:212
#define TEST_EXPECT_NO_ERROR(call)
Definition: test_unit.h:1118
bool white(int ch)
AW_active active_mask
Definition: GDE_menu.h:73
static int line
Definition: arb_a2ps.c:296
#define NULp
Definition: cxxforward.h:116
#define __ATTR__NORETURN
Definition: attributes.h:56
#define CHOICE_LIST
Definition: GDE_def.h:22
__ATTR__NORETURN void throwError(const char *msg)
char * label
Definition: GDE_menu.h:22
char meta
Definition: GDE_menu.h:65
Definition: GDE_menu.h:77
AW_active active_mask
Definition: GDE_menu.h:83
#define BUFSIZE
char meta
Definition: GDE_menu.h:82
bool only_whitespace(const char *line)
#define THROW_IF_NO_INPUT()
static void splitEntry(const char *input, char *head, char *tail)
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1294
#define gde_assert(bed)
Definition: GDE_def.h:12
GB_ERROR GB_create_directory(const char *path)
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194
bool aligned
Definition: GDE_menu.h:67
const char * label
GB_write_int const char s
Definition: AW_awar.cxx:154