ARB
nds.cxx
Go to the documentation of this file.
1 // ================================================================ //
2 // //
3 // File : AWT_nds.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // ================================================================ //
10 
11 #include "nds.h"
12 #include <awt_config_manager.hxx>
13 #include <awt_sel_boxes.hxx>
14 
15 #include <aw_awar.hxx>
16 #include <aw_file.hxx>
17 #include <aw_msg.hxx>
18 #include <aw_root.hxx>
19 #include <aw_select.hxx>
20 
21 #include <TreeNode.h>
22 #include <items.h>
23 #include <item_sel_list.h>
24 #include <gb_aci.h>
25 
26 #include <arb_msg_fwd.h>
27 #include <arb_global_defs.h>
28 #include <arb_strbuf.h>
29 
30 #define nds_assert(cond) arb_assert(cond)
31 
32 #define NDS_PER_PAGE 10 // number of NDS definitions on each config-page
33 #define NDS_PAGES 6 // how many config-pages (each has NDS_PER_PAGE definitions)
34 
35 #define NDS_COUNT (NDS_PER_PAGE*NDS_PAGES) // overall number of NDS definitions
36 
37 #define AWAR_NDS_USE_ALL "arb_presets/all"
38 #define AWAR_NDS_PAGE "arb_presets/page"
39 
40 class NodeTextBuilder : virtual Noncopyable {
41  GBS_strstruct out;
42 
43  long count; // number of active NDS entries
44  int show_errors; // how many errors to show
45 
46  long lengths[NDS_COUNT]; // allowed max. length of generated string (0 means "unlimited")
47  char *fieldname[NDS_COUNT]; // database field name (if empty -> no field; may be hierarchical, see 'rek')
48  bool rek[NDS_COUNT]; // 1->key is hierarchical (e.g. 'ali_16s/data')
49  char *parsing[NDS_COUNT]; // ACI/SRT program
50  bool at_group[NDS_COUNT]; // whether string shall appear at group NDS entries
51  bool at_leaf[NDS_COUNT]; // whether string shall appear at leaf NDS entries
52 
53  void append(const char *str, int length = -1) {
54  nds_assert(str);
55  if (length == -1) length = strlen(str);
56  nds_assert(int(strlen(str)) == length);
57  out.ncat(str, length);
58  }
59 
60  __ATTR__FORMAT(2) void appendf(const char *format, ...) { FORWARD_FORMATTED(append, format); }
61 
62 public:
63 
65  out(200),
66  count(-1)
67  {
68  for (int i = 0; i<NDS_COUNT; ++i) {
69  fieldname[i] = NULp;
70  parsing[i] = NULp;
71  }
72  }
74 
75  void init(GBDATA *gb_main);
76  const char *work(GBDATA *gb_main, GBDATA *gbd, NDS_Type mode, TreeNode *species, const char *tree_name, bool forceGroup);
77 
78  long max_columns() const { // number of used NDS entries (>= max number of columns in generated value)
79  nds_assert(count>=0);
80  return count;
81  }
82 };
83 
84 inline const char *viewkeyAwarName(int i, const char *name) {
85  nds_assert(i >= 0 && i < NDS_PER_PAGE);
86  return GBS_global_string("tmp/viewkeys/viewkey_%i/%s", i, name);
87 }
88 
89 inline AW_awar *viewkeyAwar(AW_root *aw_root, AW_default awdef, int i, const char *name, bool string_awar) {
90  const char *awar_name = viewkeyAwarName(i, name);
91  AW_awar *awar = NULp;
92  if (string_awar) awar = aw_root->awar_string(awar_name, "", awdef);
93  else awar = aw_root->awar_int(awar_name, 0, awdef);
94  return awar;
95 }
96 
97 #define VIEWKEY_LENGTH_MAX 1000000 // do not change (will break backward compatibility!)
98 
99 static void nds_length_changed_cb(AW_root *, AW_awar *Awar_len1, AW_awar *Awar_len2) {
100  long len2 = Awar_len2->read_int();
101  if (len2<0 || len2>=VIEWKEY_LENGTH_MAX) {
102  len2 = 0;
103  Awar_len2->write_int(len2);
104  }
105  long len1 = len2 ? len2 : VIEWKEY_LENGTH_MAX;
106  Awar_len1->write_int(len1);
107 }
108 
109 static void map_viewkey(AW_root *aw_root, AW_default awdef, int i, GBDATA *gb_viewkey, bool initialize) {
110  // maps one NDS key data to one line of the config window.
111  // if 'initialize' is true => add callbacks etc. (shall only happen once for each 'i')
112 
113  GBDATA *gb_key_text = GB_entry(gb_viewkey, "key_text");
114  GBDATA *gb_pars = GB_entry(gb_viewkey, "pars");
115  GBDATA *gb_group = GB_entry(gb_viewkey, "group");
116  GBDATA *gb_leaf = GB_entry(gb_viewkey, "leaf");
117  GBDATA *gb_len1 = GB_entry(gb_viewkey, "len1");
118  GBDATA *gb_len2 = GB_entry(gb_viewkey, "len2");
119 
120  nds_assert(gb_key_text);
121  nds_assert(gb_pars);
122  nds_assert(gb_group);
123  nds_assert(gb_leaf);
124  nds_assert(gb_len1);
125  nds_assert(gb_len2);
126 
127  {
128  AW_awar *Awar;
129  Awar = viewkeyAwar(aw_root, awdef, i, "key_text", true); Awar->map(gb_key_text);
130  Awar = viewkeyAwar(aw_root, awdef, i, "pars", true); Awar->map(gb_pars);
131  Awar = viewkeyAwar(aw_root, awdef, i, "group", false); Awar->map(gb_group);
132  Awar = viewkeyAwar(aw_root, awdef, i, "leaf", false); Awar->map(gb_leaf);
133  }
134 
135  AW_awar *Awar_len1 = viewkeyAwar(aw_root, awdef, i, "len1", false); Awar_len1->map(gb_len1);
136  AW_awar *Awar_len2 = viewkeyAwar(aw_root, awdef, i, "len2", false); Awar_len2->map(gb_len2);
137 
138  if (initialize) {
139  Awar_len2->add_callback(makeRootCallback(nds_length_changed_cb, Awar_len1, Awar_len2));
140  }
141 }
142 
143 static void map_viewkeys(AW_root *aw_root, /*AW_default*/ GBDATA *awdef, GBDATA *gb_main) {
144  // map visible viewkeys to internal db entries
145  static bool initialized = false;
146  AW_awar *awar_selected_page = NULp;
147 
148  if (!initialized) {
149  awar_selected_page = aw_root->awar_int(AWAR_NDS_PAGE, 0, gb_main);
150  awar_selected_page->add_callback(makeRootCallback(map_viewkeys, awdef, gb_main)); // bind to self
151  }
152  else {
153  awar_selected_page = aw_root->awar(AWAR_NDS_PAGE);
154  }
155 
156  int page = awar_selected_page->read_int();
157  if (page<NDS_PAGES) {
158  GB_transaction ta(gb_main);
159 
160  GBDATA *gb_arb_presets = GB_search(gb_main, "arb_presets", GB_CREATE_CONTAINER);
161  GBDATA *gb_viewkey = NULp;
162 
163  int i1 = page*NDS_PER_PAGE;
164  int i2 = i1+NDS_PER_PAGE-1;
165 
166  for (int i = 0; i <= i2; i++) {
167  gb_viewkey = gb_viewkey ? GB_nextEntry(gb_viewkey) : GB_entry(gb_arb_presets, "viewkey");
169  nds_assert(gb_viewkey);
170  if (i >= i1) map_viewkey(aw_root, awdef, i-i1, gb_viewkey, !initialized);
171  }
172  }
173 
174  initialized = true;
175 }
176 
177 static __ATTR__USERESULT GB_ERROR nds_delete_database_entries(GBDATA *gb_main, int page_to_reset, bool only_delete_len2_entries) {
178  GB_transaction ta(gb_main);
179  GBDATA *gb_arb_presets = GB_search(gb_main, "arb_presets", GB_FIND);
180  GB_ERROR error = NULp;
181 
182  if (gb_arb_presets) { // existing NDS settings => delete
183  GBDATA *gb_viewkey = NULp;
184 
185  for (int i = 0; i<NDS_COUNT; ++i) {
186  gb_viewkey = gb_viewkey ? GB_nextEntry(gb_viewkey) : GB_entry(gb_arb_presets, "viewkey");
187 
188  int current_page = i/NDS_PER_PAGE;
189 
190  if (!gb_viewkey) {
191  // whole entry does not exist -> create it
192  gb_viewkey = GB_create_container(gb_arb_presets, "viewkey");
193  if (!gb_viewkey) error = GB_await_error();
194  }
195  else if (current_page == page_to_reset) {
196  // existing NDS entry on current page => delete contained entries
197  for (GBDATA *gb_child = GB_child(gb_viewkey); gb_child && !error; ) {
198  GBDATA *gb_next_child = GB_nextChild(gb_child);
199 
200  bool del = true;
201  if (only_delete_len2_entries) {
202  const char *key = GB_read_key_pntr(gb_child);
203  bool is_len2 = key && strcmp(key, "len2") == 0;
204  del = is_len2;
205  }
206 
207  if (del) error = GB_delete(gb_child);
208  gb_child = gb_next_child;
209  }
210  }
211  }
212  }
213 
214  return ta.close(error);
215 }
216 
218  // Note: shall be callable multiple times
219  // (consecutive calls with same DB should not change anything).
220 
221  GB_transaction ta(gb_main);
222  GBDATA *gb_viewkey = NULp;
223  GBDATA *gb_arb_presets = GB_search(gb_main, "arb_presets", GB_CREATE_CONTAINER);
224  GB_ERROR error = gb_arb_presets ? NULp : GB_await_error();
225 
226  for (int i = 0; i<NDS_COUNT && !error; ++i) {
227  gb_viewkey = gb_viewkey ? GB_nextEntry(gb_viewkey) : GB_entry(gb_arb_presets, "viewkey");
228 
229  if (!gb_viewkey) {
230  gb_viewkey = GB_create_container(gb_arb_presets, "viewkey");
231  if (!gb_viewkey) error = GB_await_error();
232  }
233 
234  if (!error) {
235  int group = 0;
236  int leaf = 0;
237  bool was_group_name = false;
238 
239  GBDATA *gb_key_text = GB_entry(gb_viewkey, "key_text");
240  if (!gb_key_text) {
241  gb_key_text = GB_create(gb_viewkey, "key_text", GB_STRING);
242  if (!gb_key_text) error = GB_await_error();
243  else {
244  const char *wanted = "";
245  switch (i) {
246  case 0: wanted = "name"; leaf = 1; break;
247  case 1: wanted = "full_name"; leaf = 1; break;
248  case 2: wanted = ""; was_group_name = true; break;
249  case 3: wanted = "acc"; leaf = 1; break;
250  case 4: wanted = "date"; break;
251  }
252  error = GB_write_string(gb_key_text, wanted);
253  }
254  }
255 
256  if (!error && strcmp(GB_read_char_pntr(gb_key_text), "group_name") == 0) {
257  error = GB_write_string(gb_key_text, "");
258  was_group_name = true; // means: change group/leaf + add 'taxonomy(1)' to ACI
259  }
260 
261  if (!error) {
262  GBDATA *gb_pars = GB_searchOrCreate_string(gb_viewkey, "pars", "");
263  if (!gb_pars) error = GB_await_error();
264  else if (was_group_name) {
265  group = 1;
266  leaf = 0;
267 
268  const char *pars = GB_read_char_pntr(gb_pars);
269 
270  if (pars[0] == 0) pars = "taxonomy(1)"; // empty ACI/SRT
271  else if (pars[0] == ':') pars = GBS_global_string("taxonomy(1)|%s", pars); // was an SRT -> unsure what to do
272  else if (pars[0] == '|') pars = GBS_global_string("taxonomy(1)%s", pars); // was an ACI -> prefix taxonomy
273  else pars = GBS_global_string("taxonomy(1)|%s", pars); // other ACIs -> same
274 
275  error = GB_write_string(gb_pars, pars);
276  }
277  }
278 
279  if (!error) {
280  GBDATA *gb_flag1 = GB_entry(gb_viewkey, "flag1");
281  if (gb_flag1) {
282  if (GB_read_int(gb_flag1)) { // obsolete
283  leaf = 1;
284  }
285  error = GB_delete(gb_flag1);
286  }
287  }
288 
289  if (!error) {
290  GBDATA *gb_inherit = GB_entry(gb_viewkey, "inherit");
291  if (gb_inherit) { // 'inherit' is old NDS style -> convert & delete
292  if (was_group_name && GB_read_int(gb_inherit)) leaf = 1;
293  error = GB_delete(gb_inherit);
294  }
295  }
296 
297  if (!error) {
298  GBDATA *gb_group = GB_searchOrCreate_int(gb_viewkey, "group", group);
299  if (!gb_group) error = GB_await_error();
300  else group = GB_read_int(gb_group);
301  }
302  if (!error) {
303  GBDATA *gb_leaf = GB_searchOrCreate_int(gb_viewkey, "leaf", leaf);
304  if (!gb_leaf) error = GB_await_error();
305  else leaf = GB_read_int(gb_leaf);
306  }
307 
308  // maintain length field
309  if (!error) {
310  GBDATA *gb_len1 = GB_searchOrCreate_int(gb_viewkey, "len1", VIEWKEY_LENGTH_MAX); // length field used up to arb-7.0 (kept up-to-date for backward compatibility)
311  if (!gb_len1) error = GB_await_error();
312  else {
313  long arb7value = GB_read_int(gb_len1);
314  long DEFAULT_LEN = 0; // 0 means "unlimited"
315  GBDATA *gb_len2 = GB_entry(gb_viewkey, "len2"); // length field used starting with arb-7.1
316 
317  if (!gb_len2) {
318  // first time this database is started with arb-7.1++
319  // (also happens after loading a stored config => keep configs arb-7.0-- compatible)
320  if (arb7value != VIEWKEY_LENGTH_MAX) {
321  bool userWantedUnlimited = arb7value >= 999;
322  bool isDefaultAndUnused = arb7value == 30 && !leaf && !group;
323  if (userWantedUnlimited || isDefaultAndUnused) {
324  error = GB_write_int(gb_len1, VIEWKEY_LENGTH_MAX);
325  }
326  else {
327  DEFAULT_LEN = arb7value;
328  }
329  }
330 
331  if (!error) {
332  gb_len2 = GB_searchOrCreate_int(gb_viewkey, "len2", DEFAULT_LEN);
333  if (!gb_len2) {
334  error = GB_await_error();
335  }
336  }
337  }
338  else {
339  // always use backward-compat-value in "len1"
340  // - either that value was correctly maintained by arb-7.1++ or
341  // - database was edited with arb-7.0-- and the length value was changed there
342 
343  long wanted = arb7value == VIEWKEY_LENGTH_MAX ? DEFAULT_LEN : arb7value;
344 
345  if (GB_read_int(gb_len2) != wanted) {
346  error = GB_write_int(gb_len2, wanted);
347  }
348  }
349  }
350  }
351  }
352  }
353 
354  return ta.close(error);
355 }
356 
358  GB_transaction ta(gb_main);
359  aw_root->awar_int(AWAR_NDS_USE_ALL, 1, gb_main);
360 
362  if (!error) map_viewkeys(aw_root, awdef, gb_main);
363  return ta.close(error);
364 }
365 
367  aw_message_if(nds_create_vars(aw_root, awdef, gb_main));
368 }
369 
370 static const char *script_part_of(const char *predef_entry) {
371  const char *numsign = strchr(predef_entry, '#');
372  return numsign ? numsign+1 : predef_entry;
373 }
374 
375 static bool in_pre_update = false;
376 
377 static void awt_pre_to_view(AW_root *aw_root) {
378  if (!in_pre_update) {
379  LocallyModify<bool> dontRecurse(in_pre_update, true);
380 
381  const char *sel_predef_entry = aw_root->awar(AWAR_SELECT_ACISRT_PRE)->read_char_pntr();
382  aw_root->awar(AWAR_SELECT_ACISRT)->write_string(script_part_of(sel_predef_entry));
383  }
384 }
385 static void awt_select_pre_from_view(AW_root *aw_root, AW_selection_list *programs) {
386  if (!in_pre_update) {
387  LocallyModify<bool> dontRecurse(in_pre_update, true);
388 
389  const char *currScript = aw_root->awar(AWAR_SELECT_ACISRT)->read_char_pntr();
390  const char *foundPredef = NULL;
391 
392  for (AW_selection_list_iterator piter(programs); piter && !foundPredef; ++piter) { // search entry pre-defining current script
393  const char *predef = piter.get_value()->get_string();
394  const char *script = script_part_of(predef);
395 
396  if (strcmp(script, currScript) == 0) {
397  foundPredef = predef;
398  }
399  }
400 
401  // select script pre-defining current ACI (or select default if modified)
402  aw_root->awar(AWAR_SELECT_ACISRT_PRE)->write_string(foundPredef ? foundPredef : currScript);
403  }
404 }
405 
406 void NDS_popup_select_srtaci_window(AW_window *aww, const char *acisrt_awarname) {
407  static AW_window *win = NULp;
408 
409  AW_root *aw_root = aww->get_root();
410 
411  if (!win) {
412  AW_awar *awar_curr_aci = aw_root->awar_string(AWAR_SELECT_ACISRT);
413  AW_awar *awar_sel_aci = aw_root->awar_string(AWAR_SELECT_ACISRT_PRE);
414 
415  AW_window_simple *aws = new AW_window_simple;
416  aws->init(aw_root, "SRT_ACI_SELECT", "SRT_ACI_SELECT");
417  aws->load_xfig("awt/srt_select.fig");
418 
419  aws->button_length(13);
420  aws->callback(AW_POPDOWN);
421  aws->at("close");
422  aws->create_button("CLOSE", "CLOSE", "C");
423 
424  aws->callback(makeHelpCallback("acisrt.hlp"));
425  aws->at("help");
426  aws->create_button("HELP", "HELP", "H");
427 
428  aws->at("box");
429  AW_selection_list *programs = aws->create_selection_list(AWAR_SELECT_ACISRT_PRE);
430  GB_ERROR error;
431  {
432  StorableSelectionList storable_sellist(TypedSelectionList("sellst", programs, "SRT/ACI scripts", "srt_aci"));
433  error = storable_sellist.load(GB_path_in_ARBLIB("sellists/srt_aci*.sellst"), false);
434  }
435  if (error) aw_message(error);
436 
437  aws->at("field");
438  aws->create_text_field(AWAR_SELECT_ACISRT);
439 
440  awar_sel_aci->add_callback(awt_pre_to_view);
441  awar_curr_aci->add_callback(makeRootCallback(awt_select_pre_from_view, programs));
442 
443  win = aws;
444  }
445 
446  aw_root->awar(AWAR_SELECT_ACISRT)->map(acisrt_awarname);
447  win->activate();
448 }
449 
451  for (int i = 0; i<NDS_PER_PAGE; ++i) {
452  cdef.add(viewkeyAwarName(i, "leaf"), "leaf", i);
453  cdef.add(viewkeyAwarName(i, "group"), "group", i);
454  cdef.add(viewkeyAwarName(i, "key_text"), "key_text", i);
455  cdef.add(viewkeyAwarName(i, "len1"), "len1", i); // continue to use old arb-7.0-- config name (after loading config, nds_maintain_viewkeys() will correct values again)
456  cdef.add(viewkeyAwarName(i, "pars"), "pars", i);
457  }
458 }
459 
460 static char *nds_store_config() {
462  nds_init_config(cdef);
463  return cdef.read();
464 }
465 
466 static void nds_restore_config(const char *stored, GBDATA *gb_main) {
467  // if stored == NULp -> reset
468 
470  nds_init_config(cdef);
471 
472  const int current_page = AW_root::SINGLETON->awar(AWAR_NDS_PAGE)->read_int();
473 
474  if (stored) { // restore
475  AWT_config parsedCfg(stored);
476  if (parsedCfg.has_entry("inherit0")) {
477  aw_message("Converting stored config to new NDS format -- consider saving it again.");
478  // Note: The conversion applied here is also done in NDS_create_vars()
479 
480  GB_ERROR error = NULp;
481 
482  for (int i = 0; !error && i<NDS_COUNT; ++i) {
483  bool was_group_name = false;
484  {
485  const char *key_text_key = GBS_global_string("key_text%i", i);
486  const char *key_text = parsedCfg.get_entry(key_text_key);
487  if (strcmp(key_text, "group_name") == 0) {
488  was_group_name = true;
489  parsedCfg.set_entry(key_text_key, "");
490  }
491  }
492 
493  bool leaf = false;
494  bool group = false;
495  int inherit = 0;
496 
497  {
498  const char *inherit_key = GBS_global_string("inherit%i", i);
499  const char *inherit_value = parsedCfg.get_entry(inherit_key);
500 
501  if (inherit_value) {
502  inherit = atoi(inherit_value);
503  parsedCfg.delete_entry(inherit_key);
504  }
505  else {
506  error = GB_export_errorf("Expected entry '%s' in saved config", inherit_key);
507  }
508  }
509 
510  if (was_group_name) {
511  if (!error) {
512  leaf = inherit;
513  group = true;
514 
515  char *aci_key = GBS_global_string_copy("pars%i", i);
516  const char *aci = parsedCfg.get_entry(aci_key);
517  char *new_aci = NULp;
518 
519  if (aci[0] == 0) { new_aci = strdup("taxonomy(1)"); }
520  else if (aci[0] == '|') { new_aci = GBS_global_string_copy("taxonomy(1)%s", aci); }
521  else { new_aci = GBS_global_string_copy("taxonomy(1)|%s", aci); }
522 
523  parsedCfg.set_entry(aci_key, new_aci);
524 
525  free(new_aci);
526  free(aci_key);
527  }
528  }
529  else {
530  leaf = true;
531  }
532 
533  if (!error) {
534  const char *flag1_key = GBS_global_string("active%i", i);
535  const char *flag1_value = parsedCfg.get_entry(flag1_key);
536  if (flag1_value) {
537  int flag1 = atoi(flag1_value);
538  if (flag1 == 0) { leaf = group = false; }
539  parsedCfg.delete_entry(flag1_key);
540  }
541  else {
542  error = GB_export_errorf("Expected entry '%s' in saved config", flag1_key);
543  }
544  }
545 
546  if (!error) {
547  const char *leaf_key = GBS_global_string("leaf%i", i);
548  parsedCfg.set_entry(leaf_key, GBS_global_string("%i", int(leaf)));
549  const char *group_key = GBS_global_string("group%i", i);
550  parsedCfg.set_entry(group_key, GBS_global_string("%i", int(group)));
551  }
552  }
553 
554  if (!error) {
555  char *converted_cfg_str = parsedCfg.config_string();
556  cdef.write(converted_cfg_str);
557  free(converted_cfg_str);
558  }
559  else {
560  aw_message(error);
561  }
562  }
563  else {
564  GB_transaction ta(gb_main); // avoid multiple refreshes of tree display during restore
565 
566  cdef.write(stored);
567 
568  GB_ERROR error = nds_delete_database_entries(gb_main, current_page, true); // removes "len2" DB entries of current page (10 entries) => next step does smart conversion
569  if (!error) error = nds_create_vars(AW_root::SINGLETON, AW_ROOT_DEFAULT, gb_main); // => reinit NDS
570  error = ta.close(error);
571  aw_message_if(error);
572  }
573  }
574  else { // reset to factory defaults
575  GB_transaction ta(gb_main); // bundles delete and recreate (refresh delayed until both is done)
576 
577  cdef.reset(); // AWAR values are just empty here
578 
579  GB_ERROR error = nds_delete_database_entries(gb_main, current_page, false); // removes DB entries of current page (10 entries)
580  if (!error) error = nds_create_vars(AW_root::SINGLETON, AW_ROOT_DEFAULT, gb_main); // => reinit NDS
581  error = ta.close(error);
582  aw_message_if(error);
583  }
584 }
585 
587  static AW_window_simple *aws = NULp;
588  if (!aws) {
589  aws = new AW_window_simple;
590  aws->init(aw_root, "NDS_PROPS", "NDS");
591  aws->load_xfig("awt/nds.fig");
592  aws->auto_space(10, 5);
593 
594  aws->callback(AW_POPDOWN);
595  aws->at("close");
596  aws->create_button("CLOSE", "CLOSE", "C");
597 
598  aws->at("help");
599  aws->callback(makeHelpCallback("props_nds.hlp"));
600  aws->create_button("HELP", "HELP", "H");
601 
602  aws->at("page");
603  aws->create_option_menu(AWAR_NDS_PAGE);
604  for (int p = 0; p < NDS_PAGES; p++) {
605  const char *text = GBS_global_string("Entries %i - %i", p*NDS_PER_PAGE+1, (p+1)*NDS_PER_PAGE);
606  aws->insert_option(text, "", p);
607  }
608  aws->update_option_menu();
609 
610  aws->at("use");
611  aws->create_option_menu(AWAR_NDS_USE_ALL);
612  aws->insert_default_option("Use all entries", "", 1);
613  aws->insert_option ("Only use visible entries", "", 0);
614  aws->update_option_menu();
615 
616  aws->at("config");
617  AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "nds", makeStoreConfigCallback(nds_store_config), makeRestoreConfigCallback(nds_restore_config, gb_main));
618 
619  // --------------------
620 
621  aws->button_length(13);
622  int dummy, closey;
623  aws->at_newline();
624  aws->get_at_position(&dummy, &closey);
625 
626  aws->create_button(NULp, "K");
627 
628  aws->at_newline();
629 
630  int leafx, groupx, fieldx, columnx, srtx, srtux;
631 
632  aws->auto_space(10, 0);
633 
634  int i;
635  for (i=0; i<NDS_PER_PAGE; i++) {
636  aws->get_at_position(&leafx, &dummy);
637  aws->create_toggle(viewkeyAwarName(i, "leaf"));
638 
639  aws->get_at_position(&groupx, &dummy);
640  aws->create_toggle(viewkeyAwarName(i, "group"));
641 
642  aws->get_at_position(&fieldx, &dummy);
643  {
644  const char *awar_name = viewkeyAwarName(i, "key_text");
645  create_itemfield_selection_button(aws, FieldSelDef(awar_name, gb_main, SPECIES_get_selector(), FIELD_FILTER_NDS, "display-field"), NULp);
646  }
647 
648  aws->get_at_position(&columnx, &dummy);
649  aws->create_input_field(viewkeyAwarName(i, "len2"), 4);
650 
651  aws->get_at_position(&srtx, &dummy);
652  {
653  char *awar_name = strdup(viewkeyAwarName(i, "pars"));
654 
655  aws->button_length(0);
656  aws->callback(makeWindowCallback(NDS_popup_select_srtaci_window, awar_name)); // awar_name belongs to cbs now
657  {
658  char *button_id = GBS_global_string_copy("SELECT_SRTACI_%i", i+1);
659  aws->create_button(button_id, "S");
660  free(button_id);
661  }
662 
663  aws->get_at_position(&srtux, &dummy);
664  aws->at_attach_to(true, false, -7, 30);
665  aws->create_input_field(awar_name, 40);
666  }
667 
668  aws->at_unattach();
669  aws->at_newline();
670  }
671 
672  aws->at(leafx, closey);
673 
674  aws->at_x(leafx);
675  aws->create_button(NULp, "LEAF");
676  aws->at_x(groupx);
677  aws->create_button(NULp, "GRP.");
678 
679  aws->at_x(fieldx);
680  aws->create_button(NULp, "FIELD");
681 
682  aws->at_x(columnx);
683  aws->create_button(NULp, "WIDTH");
684 
685  aws->at_x(srtx);
686  aws->create_button(NULp, "SRT");
687 
688  aws->at_x(srtux);
689  aws->create_button(NULp, "ACI/SRT PROGRAM");
690  }
691 
692  return aws;
693 }
694 
695 
696 
698  GBDATA *gb_arb_presets = GB_search(gb_main, "arb_presets", GB_CREATE_CONTAINER);
699  bool only_visible_page = false;
700  int page = 0;
701  {
702  int all = *GBT_readOrCreate_int(gb_arb_presets, "all", 1);
703  if (!all) {
704  page = *GBT_readOrCreate_int(gb_arb_presets, "page", 0);
705  only_visible_page = true;
706  }
707  }
708 
709  count = 0;
710  int idx = 0;
711  for (GBDATA *gbz = GB_entry(gb_arb_presets, "viewkey"); gbz; gbz = GB_nextEntry(gbz), ++idx) {
712  bool use = !only_visible_page || (idx/NDS_PER_PAGE) == page;
713  if (use) {
714  // wanted NDS entry?
715  bool atLeaf = *GBT_read_int(gbz, "leaf");
716  bool atGroup = *GBT_read_int(gbz, "group");
717 
718  if (atLeaf || atGroup) {
719  GBDATA *gb_keyname = GB_entry(gbz, "key_text");
720  char *keyname = GB_read_string(gb_keyname);
721 
722  if (keyname[0] && strcmp(keyname, NO_FIELD_SELECTED) == 0) {
723  freeset(keyname, strdup("")); // NDS code interprets empty keyname as "no field"
724  }
725  freeset(fieldname[count], keyname);
726 
727  rek[count] = bool(GB_first_non_key_char(keyname));
728  lengths[count] = *GBT_read_int(gbz, "len2");
729  at_leaf[count] = atLeaf;
730  at_group[count] = atGroup;
731 
732  GBDATA *gbe = GB_entry(gbz, "pars");
733  freenull(parsing[count]);
734  if (gbe && GB_read_string_count(gbe)>1) parsing[count] = GB_read_string(gbe);
735  count++;
736  }
737  }
738  }
739 
740  show_errors = 10;
741 }
742 
744  for (int i = 0; i<count; ++i) {
745  freenull(fieldname[i]);
746  freenull(parsing[i]);
747  }
748 }
749 
750 static char *quoted_if_containing_separator(const char *text, char separator) {
751  bool contains_separator = strchr(text, separator);
752  if (!contains_separator) return NULp;
753  return GBS_global_string_copy("\"%s\"", text);
754 }
755 
756 const char *NodeTextBuilder::work(GBDATA *gb_main, GBDATA *gbd, NDS_Type mode, TreeNode *species, const char *tree_name, bool forceGroup) {
757  // @@@ change result into SizedCstr? (to speed up display)
758 
759  nds_assert(count>=0); // initialized?
760  out.erase();
761 
762  if (!gbd) {
763  if (!species) return "<internal error: no tree-node, no db-entry>";
764  if (!species->name) return "<internal error: species w/o name>";
765  appendf("<%s>", species->name); // zombie
766  }
767  else {
768  bool field_was_printed = false;
769  bool is_leaf = !forceGroup && (species ? species->is_leaf() : true);
770 
771  for (int i = 0; i < count; i++) {
772  if (is_leaf) { if (!at_leaf[i]) continue; }
773  else { if (!at_group[i]) continue; }
774 
775  char *str = NULp; // the generated string
776  bool apply_aci = false; // whether aci shall be applied
777 
778  {
779  const char *field_output = "";
780  const char *field_name = fieldname[i];
781 
782  if (field_name[0] == 0) { // empty field_name (or NO_FIELD_SELECTED) -> only do ACI/SRT
783  apply_aci = true;
784  }
785  else { // non-empty field_name
786  GBDATA *gbe;
787  if (rek[i]) { // hierarchical key
788  gbe = GB_search(gbd, field_name, GB_FIND);
789  }
790  else { // flat entry
791  gbe = GB_entry(gbd, field_name);
792  }
793 
794  // silently ignore missing fields (and leave apply_aci false!)
795  if (gbe) {
796  apply_aci = true;
797  switch (GB_read_type(gbe)) {
798  case GB_INT: field_output = GBS_global_string("%li", GB_read_int(gbe)); break;
799  case GB_BYTE: field_output = GBS_global_string("%i", GB_read_byte(gbe)); break;
800 
801  case GB_FLOAT: {
802  const char *format = "%5.4f";
803  if (mode == NDS_OUTPUT_TAB_SEPARATED) { // '.' -> ','
804  char *dotted = GBS_global_string_copy(format, GB_read_float(gbe));
805  char *dot = strchr(dotted, '.');
806  if (dot) *dot = ',';
807  field_output = GBS_static_string(dotted);
808  free(dotted);
809  }
810  else {
811  field_output = GBS_global_string(format, GB_read_float(gbe));
812  }
813  break;
814  }
815  case GB_STRING:
816  field_output = GB_read_char_pntr(gbe);
817  if (!field_output) field_output="<read error>";
818  break;
819 
820  default: {
821  char *as_string = GB_read_as_string(gbe);
822  field_output = GBS_static_string(as_string);
823  free(as_string);
824  }
825  }
826  }
827  else {
828  if (GB_have_error()) {
829  field_output = GB_await_error();
830  }
831  }
832  }
833  str = strdup(field_output);
834  }
835 
836  // apply ACI/SRT program
837 
838  GB_ERROR error = NULp;
839  if (apply_aci) {
840  const char *aci = parsing[i];
841  if (aci) {
842  GBL_env env(gb_main, tree_name); // @@@ pass from caller?
843  GBL_call_env callEnv(gbd, env);
844 
845  char *aci_result = GB_command_interpreter_in_env(str, aci, callEnv);
846  if (!aci_result) aci_result = GBS_global_string_copy("<error: %s>", GB_await_error());
847  freeset(str, aci_result);
848  }
849  }
850 
852 
853  // quote string, if it contains separator
854  {
855  char *quoted = NULp;
856  switch (mode) {
858  quoted = quoted_if_containing_separator(str, ',');
859  break;
860 
862  quoted = quoted_if_containing_separator(str, '\t');
863  break;
864 
865  case NDS_OUTPUT_LEAFTEXT:
867  break;
868  }
869 
870  if (quoted) freeset(str, quoted);
871  }
872 
873 
874  bool skip_display = ((mode == NDS_OUTPUT_LEAFTEXT || mode == NDS_OUTPUT_LEAFTEXT_UNLIMITED) && str[0] == 0);
875  if (!skip_display) {
876  switch (mode) {
877  case NDS_OUTPUT_LEAFTEXT:
879  if (!field_was_printed) break; // no comma no space if nothing printed yet
880  out.put(','); // separate single fields by comma in compressed mode
881  out.put(' '); // print at least one space if not using tabs
882  break;
883 
885  if (i != 0) out.put(','); // CSV output (for office calc)
886  break;
887 
889  if (i != 0) out.put('\t'); // tabbed output (for office calc)
890  break;
891  }
892 
893  field_was_printed = true;
894 
895  int str_len = strlen(str);
896  switch (mode) {
900  append(str, str_len);
901  break;
902 
903  case NDS_OUTPUT_LEAFTEXT: {
904  int nds_len = lengths[i];
905  if (str_len>nds_len && nds_len != 0) { // string is too long -> shorten (0 means "unlimited")
906  str[nds_len] = 0;
907  str_len = nds_len;
908  }
909  append(str, str_len);
910  }
911  }
912  }
913 
914  // show first XXX errors
915  if (error && show_errors>0) {
916  show_errors--;
917  aw_message(error);
918  }
919 
920  free(str);
921  }
922  }
923 
924  return out.get_data();
925 }
926 
927 NodeTextBuilder& NDS_Labeler::theBuilder(GBDATA *gb_main) const {
928  if (!builder) {
930  builder = new NodeTextBuilder;
931  builder->init(gb_main);
932  }
933  return *builder;
934 }
935 
936 NDS_Labeler::NDS_Labeler(NDS_Type type_) :
937  type(type_),
938  builder(NULp)
939 {
940 }
941 NDS_Labeler::~NDS_Labeler() {
942  delete builder;
943 }
944 
945 // @@@ add method returning a string array (e.g. ConstStrArray?) instead of comma and/or tab separated versions. useful when caller splits string again.
946 
947 long NDS_Labeler::max_columns(GBDATA *gb_main) const {
948  return theBuilder(gb_main).max_columns();
949 }
950 
951 const char *NDS_Labeler::speciesLabel(GBDATA *gb_main, GBDATA *gb_species, TreeNode *species, const char *tree_name) const {
952  return theBuilder(gb_main).work(gb_main, gb_species, get_NDS_Type(), species, tree_name, false);
953 }
954 const char *NDS_Labeler::groupLabel(GBDATA *gb_main, GBDATA *gb_group, TreeNode *species, const char *tree_name) const {
955  // forces group nodes (even if 'species' is a leaf)
956  return theBuilder(gb_main).work(gb_main, gb_group, get_NDS_Type(), species, tree_name, true);
957 }
958 
959 static const char *createReplaceTable() {
960  static char replaceTable[256];
961 
962  for (int i = 0; i<32; ++i) replaceTable[i] = '?';
963  for (int i = 32; i<256; ++i) replaceTable[i] = i;
964 
965  const char LFREP = '#';
966 
967  replaceTable['\n'] = LFREP;
968  replaceTable['\r'] = LFREP;
969  replaceTable['\t'] = ' ';
970 
971  return replaceTable;
972 }
973 
974 char *NDS_mask_nonprintable_chars(char * const str) {
975  // mask nonprintable characters in result of NDS.
976  //
977  // modifies and returns 'str'
978  //
979  // background: gtk renders LFs as such (i.e. renders multiple lines),
980  // motif printed a small box (i.e. rendered all text in one line)
981 
982  static const char *replaceTable = createReplaceTable();
983  for (int i = 0; str[i]; ++i) {
984  str[i] = replaceTable[safeCharIndex(str[i])];
985  }
986  return str;
987 }
988 
989 // --------------------------------------------------------------------------------
990 
991 #ifdef UNIT_TESTS
992 #ifndef TEST_UNIT_H
993 #include <test_unit.h>
994 #endif
995 
996 #define TEST_EXPECT_MASK_NONPRINTABLE(i,o) do { \
997  char *masked = strdup(i); \
998  NDS_mask_nonprintable_chars(masked); \
999  TEST_EXPECT_EQUAL(masked,o); \
1000  free(masked); \
1001  } while (0)
1002 
1003 void TEST_mask_nds() {
1004  TEST_EXPECT_MASK_NONPRINTABLE("plain text", "plain text");
1005  TEST_EXPECT_MASK_NONPRINTABLE("with\nLF", "with#LF");
1006  TEST_EXPECT_MASK_NONPRINTABLE("with\rLF", "with#LF");
1007  TEST_EXPECT_MASK_NONPRINTABLE("with\r\nLF", "with##LF");
1008  TEST_EXPECT_MASK_NONPRINTABLE("tab\tseparated", "tab separated");
1009  TEST_EXPECT_MASK_NONPRINTABLE("\t\n\t\n", " # #");
1010 }
1011 
1012 #define TEST_EXPECT_NDS_EQUALS(specName,labeler,expected_NDS) do { \
1013  GBDATA *gb_species = GBT_find_species(gb_main, specName); \
1014  TEST_REJECT_NULL(gb_species); \
1015  \
1016  const char *nds = labeler.speciesLabel(gb_main, gb_species, NULp, NULp); \
1017  TEST_EXPECT_EQUAL(nds, expected_NDS); \
1018  } while(0)
1019 
1020 #define TEST_EXPECT_NDS_EQUALS__BROKEN(specName,labeler,expected_NDS) do { \
1021  GBDATA *gb_species = GBT_find_species(gb_main, specName); \
1022  TEST_REJECT_NULL(gb_species); \
1023  \
1024  const char *nds = labeler.speciesLabel(gb_main, gb_species, NULp, NULp); \
1025  TEST_EXPECT_EQUAL__BROKEN(nds, expected_NDS); \
1026  } while(0)
1027 
1028 void TEST_nds() {
1029  GB_shell shell;
1030  const char *testDB = "display/nds.arb"; // NDS definitions are in ../../UNIT_TESTER/run/display/nds.arb@arb_presets
1031  GBDATA *gb_main = GB_open(testDB, "r");
1032 
1033  TEST_REJECT_NULL(gb_main);
1034 
1035  {
1036  GB_transaction ta(gb_main);
1037 
1038  NDS_Labeler leaftext_labeler(NDS_OUTPUT_LEAFTEXT);
1039  NDS_Labeler leaftext_unlimited(NDS_OUTPUT_LEAFTEXT_UNLIMITED);
1040  NDS_Labeler tab_separated_labeler(NDS_OUTPUT_TAB_SEPARATED);
1041  NDS_Labeler comma_separated_labeler(NDS_OUTPUT_COMMA_SEPARATED);
1042 
1043  TEST_EXPECT_NDS_EQUALS("MycChlor", leaftext_labeler, "'MycChlor', Mycobacterium #phenolicus, acc=X79094"); // missing field 'comment' not appended
1044  TEST_EXPECT_NDS_EQUALS("MycChlor", leaftext_unlimited, "'MycChlor', Mycobacterium #phenolicus, acc=X79094"); // missing field 'comment' not appended
1045  TEST_EXPECT_NDS_EQUALS("MycChlor", tab_separated_labeler, "'MycChlor'\tMycobacterium #phenolicus\tacc=X79094\t"); // but empty column for 'comment' inserted here
1046  TEST_EXPECT_NDS_EQUALS("MycChlor", comma_separated_labeler, "'MycChlor',Mycobacterium #phenolicus,acc=X79094,"); // and here
1047 
1048  TEST_EXPECT_NDS_EQUALS("ActUtahe", leaftext_labeler, "'ActUtahe', Act;ino planes uta,hen.sis#, acc=X80823, comment"); // comment not truncated (unlimited zero width)
1049  TEST_EXPECT_NDS_EQUALS("ActUtahe", leaftext_unlimited, "'ActUtahe', Act;ino planes uta,hen.sis#, acc=X80823, comment"); // comment not truncated (unlimited zero width)
1050  TEST_EXPECT_NDS_EQUALS("ActUtahe", tab_separated_labeler, "'ActUtahe'\tAct;ino planes uta,hen.sis#\tacc=X80823\tcomment");
1051  TEST_EXPECT_NDS_EQUALS("ActUtahe", comma_separated_labeler, "'ActUtahe',\"Act;ino planes uta,hen.sis#\",acc=X80823,comment"); // quote 2nd value (cause it contains a comma)
1052 
1053  TEST_EXPECT_NDS_EQUALS("StpGrise", leaftext_labeler, "'StpGrise', Strepto s griseus, acc=M76388 X55435 X6"); // acc truncated!
1054  TEST_EXPECT_NDS_EQUALS("StpGrise", leaftext_unlimited, "'StpGrise', Strepto s griseus, acc=M76388 X55435 X61478"); // acc NOT truncated here
1055  TEST_EXPECT_NDS_EQUALS("StpGrise", tab_separated_labeler, "'StpGrise'\tStrepto s griseus\tacc=M76388 X55435 X61478\t"); // acc NOT truncated here
1056  TEST_EXPECT_NDS_EQUALS("StpGrise", comma_separated_labeler, "'StpGrise',Strepto s griseus,acc=M76388 X55435 X61478,");
1057 
1058  TEST_EXPECT_NDS_EQUALS("StpAmbof", leaftext_labeler, "'StpAmbof', Strepto s ambofaciens nomen fa, acc=M27245, This is the comment for StpAmbof :-)"); // full_name truncated + comment not truncated (unlimited zero width)
1059  TEST_EXPECT_NDS_EQUALS("StpAmbof", leaftext_unlimited, "'StpAmbof', Strepto s ambofaciens nomen falsus longus abscindere, acc=M27245, This is the comment for StpAmbof :-)"); // full_name + comment not truncated here
1060  TEST_EXPECT_NDS_EQUALS("StpAmbof", tab_separated_labeler, "'StpAmbof'\tStrepto s ambofaciens nomen falsus longus abscindere\tacc=M27245\tThis is the comment for StpAmbof :-)"); // full_name + comment not truncated here
1061  TEST_EXPECT_NDS_EQUALS("StpAmbof", comma_separated_labeler, "'StpAmbof',Strepto s ambofaciens nomen falsus longus abscindere,acc=M27245,This is the comment for StpAmbof :-)");
1062  }
1063 
1064  GB_close(gb_main);
1065 }
1066 
1067 #endif // UNIT_TESTS
1068 
1069 // --------------------------------------------------------------------------------
1070 
1071 
1072 
1073 
1074 
const char * GB_ERROR
Definition: arb_core.h:25
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
GB_TYPES type
void delete_entry(const char *entry)
group_matcher all()
Definition: test_unit.h:1011
void add(const char *awar_name, const char *config_name)
bool has_entry(const char *entry) const
AliDataPtr format(AliDataPtr data, const size_t wanted_len, GB_ERROR &error)
Definition: insdel.cxx:615
Definition: arbdb.h:65
long GB_read_int(GBDATA *gbd)
Definition: arbdb.cxx:729
GBDATA * GB_child(GBDATA *father)
Definition: adquery.cxx:322
static void dot(double **i, double **j, double **k)
Definition: trnsprob.cxx:59
~NodeTextBuilder()
Definition: nds.cxx:743
CONSTEXPR_INLINE unsigned char safeCharIndex(char c)
Definition: dupstr.h:73
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
Definition: arbdb.cxx:1387
GBDATA * GB_searchOrCreate_string(GBDATA *gb_container, const char *fieldpath, const char *default_value)
Definition: adquery.cxx:546
GBDATA * GB_nextEntry(GBDATA *entry)
Definition: adquery.cxx:339
void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, const StoreConfigCallback &store_cb, const RestoreConfigCallback &load_or_reset_cb, const char *macro_id, const AWT_predefined_config *predef)
char * GB_read_as_string(GBDATA *gbd)
Definition: arbdb.cxx:1060
const char * viewkeyAwarName(int i, const char *name)
Definition: nds.cxx:84
long read_int() const
Definition: AW_awar.cxx:184
NOT4PERL long * GBT_readOrCreate_int(GBDATA *gb_container, const char *fieldpath, long default_value)
Definition: adtools.cxx:402
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
#define FORWARD_FORMATTED(receiver, format)
Definition: arb_msg_fwd.h:19
bool GB_have_error()
Definition: arb_msg.cxx:338
void erase()
Definition: arb_strbuf.h:141
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
static void nds_length_changed_cb(AW_root *, AW_awar *Awar_len1, AW_awar *Awar_len2)
Definition: nds.cxx:99
void activate()
Definition: aw_window.hxx:360
static const char * script_part_of(const char *predef_entry)
Definition: nds.cxx:370
CONSTEXPR long FIELD_FILTER_NDS
Definition: item_sel_list.h:52
#define NO_FIELD_SELECTED
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:231
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1916
void create_itemfield_selection_button(AW_window *aws, const FieldSelDef &selDef, const char *at)
static bool initialized
Definition: AW_advice.cxx:36
static __ATTR__USERESULT GB_ERROR nds_create_vars(AW_root *aw_root, AW_default awdef, GBDATA *gb_main)
Definition: nds.cxx:357
#define NDS_PER_PAGE
Definition: nds.cxx:32
const char * work(GBDATA *gb_main, GBDATA *gbd, NDS_Type mode, TreeNode *species, const char *tree_name, bool forceGroup)
Definition: nds.cxx:756
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
size_t GB_read_string_count(GBDATA *gbd)
Definition: arbdb.cxx:916
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
static AW_root * SINGLETON
Definition: aw_root.hxx:102
NOT4PERL long * GBT_read_int(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:327
GBDATA * GB_create_container(GBDATA *father, const char *key)
Definition: arbdb.cxx:1829
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
AW_awar * viewkeyAwar(AW_root *aw_root, AW_default awdef, int i, const char *name, bool string_awar)
Definition: nds.cxx:89
Definition: arbdb.h:67
#define NDS_COUNT
Definition: nds.cxx:35
GB_TYPES GB_read_type(GBDATA *gbd)
Definition: arbdb.cxx:1643
void NDS_popup_select_srtaci_window(AW_window *aww, const char *acisrt_awarname)
Definition: nds.cxx:406
GB_CSTR GB_read_key_pntr(GBDATA *gbd)
Definition: arbdb.cxx:1656
static void nds_restore_config(const char *stored, GBDATA *gb_main)
Definition: nds.cxx:466
GBDATA * GB_create(GBDATA *father, const char *key, GB_TYPES type)
Definition: arbdb.cxx:1781
const char * GB_first_non_key_char(const char *str)
Definition: adquery.cxx:416
static const char * createReplaceTable()
Definition: nds.cxx:959
static void awt_select_pre_from_view(AW_root *aw_root, AW_selection_list *programs)
Definition: nds.cxx:385
static int group[MAXN+1]
Definition: ClustalV.cxx:65
long max_columns() const
Definition: nds.cxx:78
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1325
#define AWAR_SELECT_ACISRT
Definition: nds.h:30
static void error(const char *msg)
Definition: mkptypes.cxx:96
NDS_Type
Definition: nds.h:35
GBDATA * GB_searchOrCreate_int(GBDATA *gb_container, const char *fieldpath, long default_value)
Definition: adquery.cxx:569
char * str
Definition: defines.h:20
float GB_read_float(GBDATA *gbd)
Definition: arbdb.cxx:744
#define AWAR_NDS_USE_ALL
Definition: nds.cxx:37
GB_CSTR GB_path_in_ARBLIB(const char *relative_path)
Definition: adsocket.cxx:1156
#define VIEWKEY_LENGTH_MAX
Definition: nds.cxx:97
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
Definition: arbdb.h:86
char * NDS_mask_nonprintable_chars(char *const str)
Definition: nds.cxx:974
GB_ERROR GB_write_int(GBDATA *gbd, long i)
Definition: arbdb.cxx:1250
static char * quoted_if_containing_separator(const char *text, char separator)
Definition: nds.cxx:750
static void map_viewkeys(AW_root *aw_root, GBDATA *awdef, GBDATA *gb_main)
Definition: nds.cxx:143
#define AWAR_NDS_PAGE
Definition: nds.cxx:38
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:262
void ncat(const char *from, size_t count)
Definition: arb_strbuf.h:173
bool is_leaf() const
Definition: TreeNode.h:211
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
static char * nds_store_config()
Definition: nds.cxx:460
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:35
AW_window * NDS_create_window(AW_root *aw_root, GBDATA *gb_main)
Definition: nds.cxx:586
static __ATTR__USERESULT GB_ERROR nds_maintain_viewkeys(GBDATA *gb_main)
Definition: nds.cxx:217
#define __ATTR__USERESULT
Definition: attributes.h:58
char * name
Definition: TreeNode.h:174
int GB_read_byte(GBDATA *gbd)
Definition: arbdb.cxx:734
AW_awar * map(const char *awarn)
Definition: AW_awar.cxx:521
char * GB_read_string(GBDATA *gbd)
Definition: arbdb.cxx:909
ItemSelector & SPECIES_get_selector()
Definition: species.cxx:139
void set_entry(const char *entry, const char *value)
const char * GBS_static_string(const char *str)
Definition: arb_msg.cxx:212
NodeTextBuilder()
Definition: nds.cxx:64
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
static void map_viewkey(AW_root *aw_root, AW_default awdef, int i, GBDATA *gb_viewkey, bool initialize)
Definition: nds.cxx:109
AW_root * get_root()
Definition: aw_window.hxx:354
#define nds_assert(cond)
Definition: nds.cxx:30
AW_window_simple * win
#define NULp
Definition: cxxforward.h:114
bool is_leaf() const
Definition: probe_tree.h:67
static bool in_pre_update
Definition: nds.cxx:375
GB_ERROR write_string(const char *aw_string)
static void nds_init_config(AWT_config_definition &cdef)
Definition: nds.cxx:450
static __ATTR__USERESULT GB_ERROR nds_delete_database_entries(GBDATA *gb_main, int page_to_reset, bool only_delete_len2_entries)
Definition: nds.cxx:177
const char * get_data() const
Definition: arb_strbuf.h:120
NOT4PERL char * GB_command_interpreter_in_env(const char *str, const char *commands, const GBL_call_env &callEnv)
Definition: gb_aci.cxx:361
GBDATA * GB_nextChild(GBDATA *child)
Definition: adquery.cxx:326
GB_ERROR load(const char *filemask, bool append) const
GB_transaction ta(gb_var)
const char * get_entry(const char *entry) const
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
Definition: arbdb.cxx:904
GBDATA * gb_main
Definition: adname.cxx:32
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
Definition: adquery.cxx:531
static void awt_pre_to_view(AW_root *aw_root)
Definition: nds.cxx:377
void init(GBDATA *gb_main)
Definition: nds.cxx:697
size_t length
#define AWAR_SELECT_ACISRT_PRE
Definition: nds.h:31
char * config_string() const
void NDS_create_vars(AW_root *aw_root, AW_default awdef, GBDATA *gb_main)
Definition: nds.cxx:366
#define AW_ROOT_DEFAULT
Definition: aw_base.hxx:106
GB_ERROR write_int(long aw_int)
#define NDS_PAGES
Definition: nds.cxx:33
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
void aw_message_if(GB_ERROR error)
Definition: aw_msg.hxx:21
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655
void put(char c)
Definition: arb_strbuf.h:158
void write(const char *cfgStr) const
Definition: arbdb.h:66