ARB
NT_edconf.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : NT_edconf.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // =============================================================== //
10 
11 #include "NT_local.h"
12 #include "ad_trees.h"
13 
14 #include <TreeNode.h>
15 #include <TreeDisplay.hxx>
16 #include <RegExpr.hxx>
17 
18 #include <awt_sel_boxes.hxx>
19 #include <awt_misc.hxx>
20 #include <awt_config_manager.hxx>
21 #include <awt_modules.hxx>
22 
23 #include <aw_awars.hxx>
24 #include <aw_root.hxx>
25 #include <aw_msg.hxx>
26 #include <aw_select.hxx>
27 
28 #include <ad_config.h>
29 #include <ad_cb_prot.h>
30 
31 #include <arb_global_defs.h>
32 
33 #include <map>
34 #include <set>
35 #include <string>
36 
37 using namespace std;
38 
39 // AWT_canvas-local (%i=canvas-id):
40 #define AWAR_CL_SELECTED_CONFIGS "configuration_data/win%i/selected"
41 #define AWAR_CL_DISPLAY_CONFIG_MARKERS "configuration_data/win%i/display"
42 
43 #define AWAR_CONFIG_COMMENT "tmp/configuration/comment"
44 
50  CONF_COMBINE // logical AND
51 };
52 static void nt_extract_configuration(UNFIXED, extractType ext_type);
53 
54 typedef map<string, string> ConfigHits; // key=speciesname; value[markerIdx]==1 -> highlighted
55 
56 class ConfigMarkerDisplay FINAL_TYPE : public MarkerDisplay, virtual Noncopyable {
57  GBDATA *gb_main;
58  SmartPtr<ConstStrArray> config; // configuration names
59  StrArray errors; // config load-errors
60  ConfigHits hits;
61 
62  void updateHits() {
63  flush_cache();
64  hits.clear();
65  errors.erase();
66  for (int c = 0; c<size(); ++c) {
68  GBT_config cfg(gb_main, (*config)[c], error);
69 
70  for (int area = 0; area<=1 && !error; ++area) {
71  GBT_config_parser cparser(cfg, area);
72 
73  while (1) {
74  const GBT_config_item& item = cparser.nextItem(error);
75  if (error || item.type == CI_END_OF_CONFIG) break;
76  if (item.type == CI_SPECIES) {
77  ConfigHits::iterator found = hits.find(item.name);
78  if (found == hits.end()) {
79  string h(size(), '0');
80  h[c] = '1';
81  hits[item.name] = h;
82  }
83  else {
84  (found->second)[c] = '1';
85  }
86  }
87  }
88  }
89 
90  errors.put(ARB_strdup(null2empty(error)));
91  }
92  }
93 
94 public:
96  : MarkerDisplay(config_->size()),
97  gb_main(gb_main_),
98  config(config_)
99  {
100  updateHits();
101  }
102  const char *get_marker_name(int markerIdx) const OVERRIDE {
103  const char *error = errors[markerIdx];
104  const char *name = (*config)[markerIdx];
105  if (error && error[0]) return GBS_global_string("%s (Error: %s)", name, error);
106  return name;
107  }
108  void retrieve_marker_state(const char *speciesName, NodeMarkers& node) OVERRIDE {
109  ConfigHits::const_iterator found = hits.find(speciesName);
110  if (found != hits.end()) {
111  const string& hit = found->second;
112 
113  for (int c = 0; c<size(); ++c) {
114  if (hit[c] == '1') node.incMarker(c);
115  }
116  }
117  node.incNodeSize();
118  }
119 
120  void handle_click(int markerIdx, AW_MouseButton button, AWT_graphic_exports& exports) OVERRIDE {
121  if (button == AW_BUTTON_LEFT || button == AW_BUTTON_RIGHT) {
122  AW_root::SINGLETON->awar(AWAR_CONFIGURATION)->write_string(get_marker_name(markerIdx)); // select config of clicked marker
123  if (button == AW_BUTTON_RIGHT) { // extract configuration
125  exports.request_structure_update(); // needed to recalculate branch colors
126  }
127  }
128  }
129 };
130 
131 inline bool displays_config_markers(MarkerDisplay *md) { return dynamic_cast<ConfigMarkerDisplay*>(md); }
132 
133 #define CONFIG_SEPARATOR "\1"
134 
135 inline AW_awar *get_canvas_awar(const char *awar_name_format, int canvas_id) {
136  return AW_root::SINGLETON->awar_no_error(GBS_global_string(awar_name_format, canvas_id));
137 }
138 inline AW_awar *get_config_awar (int canvas_id) { return get_canvas_awar(AWAR_CL_SELECTED_CONFIGS, canvas_id); }
140 
142  // returns configs stored in awar as array (empty array if awar undefined!)
144 
145  AW_awar *awar = get_config_awar(canvas_id);
146  if (awar) {
147  char *config_str = awar->read_string();
148  GBT_splitNdestroy_string(*config, config_str, CONFIG_SEPARATOR, true);
149  }
150 
151  return config;
152 }
153 static void write_configs_to_awar(int canvas_id, const CharPtrArray& configs) {
154  char *config_str = GBT_join_strings(configs, CONFIG_SEPARATOR[0]);
156  free(config_str);
157 }
158 
159 // --------------------------------------------------------------------------------
160 
162 static bool allow_selection2awar_update = true;
163 static bool allow_to_activate_display = false;
164 
165 static void init_config_awars(AW_root *root) {
167 }
170  int ntw_id = ntw->get_index();
172  bool redraw = false;
173 
174  if (config->empty() || get_display_toggle_awar(ntw_id)->read_int() == 0) {
175  if (displays_config_markers(agt->get_marker_display())) { // only hide config markers
176  agt->hide_marker_display();
177  redraw = true;
178  }
179  }
180  else {
182 
183  if (activate) {
184  init_config_awars(aw_root);
185  ConfigMarkerDisplay *disp = new ConfigMarkerDisplay(config, ntw->gb_main);
186  agt->set_marker_display(disp);
187  redraw = true;
188  }
189  }
190 
191  if (selected_configs_list[ntw_id]) { // if configuration_marker_window has been opened
192  // update content of subset-selection (needed when reloading a config-set (not implemented yet) or after renaming a config)
194  awt_set_subset_selection_content(selected_configs_list[ntw_id], *config);
195  }
196 
198 }
199 
201  LocallyModify<bool> allowInteractiveActivation(allow_to_activate_display, true);
203 }
204 
205 static void configs_selectionlist_changed_cb(AW_selection *selected_configs, bool interactive_change, AW_CL ntw_id) {
207  LocallyModify<bool> allowInteractiveActivation(allow_to_activate_display, interactive_change);
208 
209  StrArray config;
210  selected_configs->get_values(config);
211  write_configs_to_awar(ntw_id, config);
212  }
213 }
214 
215 static void config_modified_cb(GBDATA *gb_cfg_area) { // called with "top_area" AND "middle_area" entry!
216  static GBDATA *gb_lastname = NULp;
217  static GB_ULONG lastcall = 0;
218 
219  GBDATA *gb_name = GB_entry(GB_get_father(gb_cfg_area), "name");
220  GB_ULONG thiscall = GB_time_of_day();
221 
222  bool is_same_modification = gb_name == gb_lastname && (thiscall == lastcall || thiscall == (lastcall+1));
223  if (!is_same_modification) { // avoid duplicate check if "top_area" and "middle_area" changed (=standard case)
224  // touch all canvas-specific awars that contain 'name'
225  const char *name = GB_read_char_pntr(gb_name);
226 
227  for (int canvas_id = 0; canvas_id<MAX_NT_WINDOWS; ++canvas_id) {
229  for (size_t c = 0; c<config->size(); ++c) {
230  if (strcmp((*config)[c], name) == 0) {
231  get_config_awar(canvas_id)->touch();
232  break;
233  }
234  }
235  }
236  }
237  gb_lastname = gb_name;
238  lastcall = thiscall;
239 }
240 
241 #define CONFIG_BASE_PATH "/configuration_data/configuration"
242 
244  static bool installed = false;
245  if (!installed) {
246  DatabaseCallback dbcb = makeDatabaseCallback(config_modified_cb);
249 
250  installed = true;
251  }
252 }
253 
255  GBDATA *gb_main = ntw->gb_main;
256 
257  int ntw_idx = ntw->get_index();
258  AW_awar *awar_selCfgs = ntw->awr->awar_string(GBS_global_string(AWAR_CL_SELECTED_CONFIGS, ntw_idx), "", gb_main);
259  awar_selCfgs->add_callback(makeRootCallback(selected_configs_awar_changed_cb, ntw));
260 
261  AW_awar *awar_dispCfgs = ntw->awr->awar_int(GBS_global_string(AWAR_CL_DISPLAY_CONFIG_MARKERS, ntw_idx), 1, gb_main);
262  awar_dispCfgs->add_callback(makeRootCallback(selected_configs_display_awar_changed_cb, ntw));
263 
264  awar_selCfgs->touch(); // force initial refresh
266 }
267 
268 // define where to store config-sets (using config-manager):
269 #define MANAGED_CONFIGSET_SECTION "configmarkers"
270 #define MANAGED_CONFIGSET_ENTRY "selected_configs"
271 
272 static void setup_configmarker_config_cb(AWT_config_definition& config, int ntw_id) {
273  AW_awar *selcfg_awar = get_config_awar(ntw_id);
274  nt_assert(selcfg_awar);
275  if (selcfg_awar) {
276  config.add(selcfg_awar->awar_name, MANAGED_CONFIGSET_ENTRY);
277  }
278 }
279 
280 struct ConfigModifier : virtual Noncopyable {
281  virtual ~ConfigModifier() {}
282  virtual const char *modify(const char *old) const = 0;
283 
284  bool modifyConfig(ConstStrArray& config) const {
285  bool changed = false;
286  for (size_t i = 0; i<config.size(); ++i) {
287  const char *newContent = modify(config[i]);
288  if (!newContent) {
289  config.remove(i);
290  changed = true;
291  }
292  else if (strcmp(newContent, config[i]) != 0) {
293  config.replace(i, newContent);
294  changed = true;
295  }
296  }
297  return changed;
298  }
299 };
300 class ConfigRenamer : public ConfigModifier { // derived from Noncopyable
301  const char *oldName;
302  const char *newName;
303  const char *modify(const char *name) const OVERRIDE {
304  return strcmp(name, oldName) == 0 ? newName : name;
305  }
306 public:
307  ConfigRenamer(const char *oldName_, const char *newName_)
308  : oldName(oldName_),
309  newName(newName_)
310  {}
311 };
312 class ConfigDeleter : public ConfigModifier { // derived from Noncopyable
313  const char *toDelete;
314  const char *modify(const char *name) const OVERRIDE {
315  return strcmp(name, toDelete) == 0 ? NULp : name;
316  }
317 public:
318  ConfigDeleter(const char *toDelete_)
319  : toDelete(toDelete_)
320  {}
321 };
322 
323 static char *correct_managed_configsets_cb(const char *key, const char *value, AW_CL cl_ConfigModifier) {
324  char *modified_value = NULp;
325  if (strcmp(key, MANAGED_CONFIGSET_ENTRY) == 0) {
326  const ConfigModifier *mod = (const ConfigModifier*)cl_ConfigModifier;
327  ConstStrArray config;
328  GBT_split_string(config, value, CONFIG_SEPARATOR, true);
329  if (mod->modifyConfig(config)) {
330  modified_value = GBT_join_strings(config, CONFIG_SEPARATOR[0]);
331  }
332  }
333  return modified_value ? modified_value : ARB_strdup(value);
334 }
335 static void modify_configurations(const ConfigModifier& mod) {
336  for (int canvas_id = 0; canvas_id<MAX_NT_WINDOWS; ++canvas_id) {
337  // modify currently selected configs:
339  if (mod.modifyConfig(*config)) {
340  write_configs_to_awar(canvas_id, *config);
341  }
342  }
343  // change all configuration-sets stored in config-manager (shared by all windows)
345 }
346 
347 static void configuration_renamed_cb(const char *old_name, const char *new_name) { modify_configurations(ConfigRenamer(old_name, new_name)); }
348 static void configuration_deleted_cb(const char *name) { modify_configurations(ConfigDeleter(name)); }
349 
351  AW_window_simple *aws = new AW_window_simple;
352 
353  int ntw_id = ntw->get_index();
354  aws->init(root, GBS_global_string("MARK_CONFIGS_%i", ntw_id), "Highlight configurations in tree");
355  aws->load_xfig("mark_configs.fig");
356 
357  aws->auto_space(10, 10);
358 
359  aws->at("close");
360  aws->callback(AW_POPDOWN);
361  aws->create_button("CLOSE", "CLOSE", "C");
362 
363  aws->at("help");
364  aws->callback(makeHelpCallback("species_configs_highlight.hlp"));
365  aws->create_button("HELP", "HELP", "H");
366 
367 
368  aws->at("list");
370  AW_selection *sub_sel;
371  {
372  LocallyModify<bool> avoid(allow_selection2awar_update, false); // avoid awar gets updated from empty sub-selectionlist
373  sub_sel = awt_create_subset_selection_list(aws, all_configs->get_sellist(), "selected", "add", "sort", false, configs_selectionlist_changed_cb, ntw->get_index());
374  }
375 
377  selected_configs_list[ntw_id] = sub_sel;
378 
379  // @@@ would like to use ntw-specific awar for this selection list (opening two lists links them)
380 
381  aws->at("show");
382  aws->label("Display?");
383  aws->create_toggle(get_display_toggle_awar(ntw_id)->awar_name);
384 
385  aws->at("settings");
386  aws->callback(TREE_create_marker_settings_window);
387  aws->create_autosize_button("SETTINGS", "Settings", "S");
388 
390 
391  return aws;
392 }
393 
394 // -----------------------------
395 // class Store_species
396 
397 class Store_species : virtual Noncopyable {
398  // stores an amount of species:
399  TreeNode *node;
400  Store_species *next;
401 public:
403  node = aNode;
404  next = NULp;
405  }
406  ~Store_species();
407 
409  nt_assert(!next);
410  next = list;
411  return this;
412  }
413 
414  Store_species* remove() {
415  Store_species *follower = next;
416  next = NULp;
417  return follower;
418  }
419 
420  TreeNode *getNode() const { return node; }
421 
422  void call(void (*aPizza)(TreeNode*)) const;
423 };
424 
426  delete next;
427 }
428 
429 void Store_species::call(void (*aPizza)(TreeNode*)) const {
430  aPizza(node);
431  if (next) next->call(aPizza);
432 }
433 
434 static void unmark_species(TreeNode *node) {
435  nt_assert(node);
436  nt_assert(node->gb_node);
437  nt_assert(GB_read_flag(node->gb_node)!=0);
438  GB_write_flag(node->gb_node, 0);
439 }
440 
441 static void mark_species(TreeNode *node, Store_species **extra_marked_species) {
442  nt_assert(node);
443  nt_assert(node->gb_node);
444  nt_assert(GB_read_flag(node->gb_node)==0);
445  GB_write_flag(node->gb_node, 1);
446 
447  *extra_marked_species = (new Store_species(node))->add(*extra_marked_species);
448 }
449 
450 
451 
453  nt_assert(node);
454  while (!node->is_leaf()) {
455  node = node->get_rightson();
456  nt_assert(node);
457  }
458  return node;
459 }
460 
462  if (node) {
463  TreeNode *father = node->get_father();
464  while (father) {
465  if (father->rightson==node) {
466  node = rightmost_leaf(father->get_leftson());
467  nt_assert(node->is_leaf());
468  if (!node->gb_node) { // Zombie
469  node = left_neighbour_leaf(node);
470  }
471  return node;
472  }
473  node = father;
474  father = node->get_father();
475  }
476  }
477  return NULp;
478 }
479 
480 const char CFG_SEP = 1;
481 
483  TreeNode *tree,
484  GBS_strstruct& memfile,
485  Store_species **extra_marked_species,
486  int use_species_aside,
487  int *auto_mark,
488  int marked_at_left,
489  int *marked_at_right)
490 {
522  if (!tree) return 0;
523  if (tree->is_leaf()) {
524  if (!tree->gb_node) {
525  UNCOVERED();
526  *marked_at_right = marked_at_left;
527  return 0; // Zombie
528  }
529 
530  if (!GB_read_flag(tree->gb_node)) { // unmarked species
531  if (*auto_mark) {
532  (*auto_mark)--;
533  mark_species(tree, extra_marked_species);
534  }
535  else {
536  *marked_at_right = 0;
537  return 0;
538  }
539  }
540  else { // marked species
541  if (marked_at_left<use_species_aside) {
542  // on the left side there are not as many marked species as needed!
543 
544  nt_assert(marked_at_left>=0);
545 
546  TreeNode *leaf_at_left = tree;
547  int step_over = marked_at_left+1; // step over myself
548  int then_mark = use_species_aside-marked_at_left;
549 
550  while (step_over--) { // step over self and over any adjacent, marked species
551  leaf_at_left = left_neighbour_leaf(leaf_at_left);
552  }
553 
554  Store_species *marked_back = NULp;
555  while (leaf_at_left && then_mark--) { // then additionally mark some species
556  if (GB_read_flag(leaf_at_left->gb_node) == 0) { // if they are not marked yet
557  mark_species(leaf_at_left, extra_marked_species);
558  marked_back = (new Store_species(leaf_at_left))->add(marked_back);
559  }
560  leaf_at_left = left_neighbour_leaf(leaf_at_left);
561  }
562 
563  while (marked_back) {
564  memfile.put(CFG_SEP);
565  memfile.put('L');
566  memfile.cat(marked_back->getNode()->name);
567  GBS_write_hash(used, marked_back->getNode()->name, 1); // Mark species
568 
569  Store_species *rest = marked_back->remove();
570  delete marked_back;
571  marked_back = rest;
572  }
573 
574  marked_at_left = use_species_aside;
575  }
576  // now use_species_aside species to left are marked!
577  *auto_mark = use_species_aside;
578  }
579 
580  memfile.put(CFG_SEP);
581  memfile.put('L');
582  memfile.cat(tree->name);
583  GBS_write_hash(used, tree->name, 1); // Mark species
584 
585  *marked_at_right = marked_at_left+1;
586  return 1;
587  }
588 
589  const size_t oldpos = memfile.get_position();
590  if (tree->gb_node && tree->name) { // but we are a group
591  GBDATA *gb_grouped = GB_entry(tree->gb_node, "grouped");
592  memfile.put(CFG_SEP);
593  if (gb_grouped && GB_read_byte(gb_grouped)) {
594  memfile.put('F');
595  }
596  else {
597  memfile.put('G');
598  }
599 
600  memfile.cat(tree->name);
601  }
602 
603  int right_of_leftson;
604  long nspecies= nt_build_conf_string_rek(used, tree->get_leftson(), memfile, extra_marked_species, use_species_aside, auto_mark, marked_at_left, &right_of_leftson);
605  nspecies += nt_build_conf_string_rek(used, tree->get_rightson(), memfile, extra_marked_species, use_species_aside, auto_mark, right_of_leftson, marked_at_right);
606 
607  if (tree->gb_node && tree->name) { // but we are a group
608  memfile.put(CFG_SEP);
609  memfile.put('E'); // Group end indicated by 'E'
610  }
611 
612  if (!nspecies) {
613  const size_t newpos = memfile.get_position();
614  memfile.cut_tail(newpos-oldpos); // delete group info
615  }
616  return nspecies;
617 }
618 
621  const char *last_group_name;
622 };
623 
624 static void nt_build_sai_string_by_hash(const char *key, long /*val*/, void *cd_sai_builder) {
625  SAI_string_builder *sai_builder = (SAI_string_builder*)cd_sai_builder;
626 
627  const char *sep = strchr(key, 1);
628  if (sep) {
629  GBS_strstruct& sai_middle = sai_builder->sai_middle;
630  const char *last_group_name = sai_builder->last_group_name;
631 
632  if (!last_group_name || strncmp(key, last_group_name, sep-key)) { // new group
633  if (last_group_name) {
634  sai_middle.put(CFG_SEP);
635  sai_middle.put('E'); // End of old group
636  }
637  sai_middle.put(CFG_SEP);
638  sai_middle.cat("FSAI:");
639  sai_middle.ncat(key, sep-key);
640  sai_builder->last_group_name = key;
641  }
642  sai_middle.put(CFG_SEP);
643  sai_middle.put('S');
644  sai_middle.cat(sep+1);
645  }
646 }
647 
648 static void nt_build_sai_string(GBDATA *gb_main, const char *topAreaSaiList, GBS_strstruct& topfile, GBS_strstruct& middlefile) {
649  // collect all Sais,
650  // place some SAI in top area (those listed in 'toparea_SAIs'; SAI-groups will be ignored here)
651  // rest of SAI goes into middle area (SAI-groups respected here)
652 
653  GBDATA *gb_sai_data = GBT_get_SAI_data(gb_main);
654  if (gb_sai_data) {
656 
657  ConstStrArray topAreaSai;
658  GBT_split_string(topAreaSai, topAreaSaiList, ",;: \t", true);
659 
660  for (GBDATA *gb_sai = GBT_first_SAI_rel_SAI_data(gb_sai_data); gb_sai; gb_sai = GBT_next_SAI(gb_sai)) {
661  GBDATA *gb_name = GB_search(gb_sai, "name", GB_FIND);
662  if (gb_name) {
663  char *name = GB_read_string(gb_name);
664 
665  bool wantedInTop = false;
666  for (unsigned s = 0; !wantedInTop && s<topAreaSai.size(); ++s) {
667  wantedInTop = strcmp(name, topAreaSai[s]) == 0;
668  }
669 
670  if (!wantedInTop) {
671  GBDATA *gb_gn = GB_search(gb_sai, "sai_group", GB_FIND);
672  char *gn;
673 
674  if (gb_gn) gn = GB_read_string(gb_gn);
675  else gn = ARB_strdup("SAI's");
676 
677  char *cn = new char[strlen(gn) + strlen(name) + 2];
678  sprintf(cn, "%s%c%s", gn, 1, name);
679  GBS_write_hash(hash, cn, 1);
680  delete [] cn;
681  free(gn);
682  }
683  free(name);
684  }
685  }
686 
687  // add top area SAIs in defined order:
688  for (unsigned s = 0; s<topAreaSai.size(); ++s) {
689  GBDATA *gb_sai = GBT_find_SAI_rel_SAI_data(gb_sai_data, topAreaSai[s]);
690  if (gb_sai) {
691  topfile.put(CFG_SEP);
692  topfile.put('S');
693  topfile.cat(topAreaSai[s]);
694  }
695  }
696 
697  // open surrounding SAI-group:
698  middlefile.put(CFG_SEP);
699  middlefile.cat("GSAI-Maingroup");
700 
701  SAI_string_builder sai_builder = { middlefile, NULp };
703  if (sai_builder.last_group_name) {
704  middlefile.put(CFG_SEP);
705  middlefile.put('E'); // End of old group
706  }
707 
708  // close surrounding SAI-group:
709  middlefile.put(CFG_SEP);
710  middlefile.put('E');
711 
712  GBS_free_hash(hash);
713  }
714 }
715 
717  file.put(CFG_SEP);
718  file.cat("FMore Sequences");
719 
720  for (GBDATA *gb_species = GBT_first_marked_species(gb_main);
721  gb_species;
722  gb_species = GBT_next_marked_species(gb_species))
723  {
724  char *name = GBT_read_string(gb_species, "name");
725  if (!GBS_read_hash(used, name)) {
726  file.put(CFG_SEP);
727  file.put('L');
728  file.cat(name);
729  }
730  free(name);
731  }
732 
733  file.put(CFG_SEP);
734  file.put('E'); // Group end indicated by 'E'
735 }
736 
739  AW_root *aw_root = AW_root::SINGLETON;
740  char *cn = aw_root->awar(AWAR_CONFIGURATION)->read_string();
741 
742  if (strcmp(cn, NO_CONFIG_SELECTED) == 0) {
743  aw_message("Please select a configuration");
744  }
745  else {
746  GB_ERROR error = NULp;
747  GBT_config cfg(GLOBAL.gb_main, cn, error);
748 
749  if (!error) {
750  size_t unknown_species = 0;
751  bool refresh = false;
752 
753  GB_HASH *was_marked = NULp; // only used for CONF_COMBINE
754 
755  switch (ext_type) {
756  case CONF_EXTRACT: // unmark all
758  refresh = true;
759  break;
760 
761  case CONF_COMBINE: // store all marked species in hash and unmark them
764  refresh = GBS_hash_elements(was_marked);
765  break;
766 
767  default:
768  break;
769  }
770 
771  for (int area = 0; area<=1 && !error; ++area) {
772  GBT_config_parser cparser(cfg, area);
773 
774  while (1) {
775  const GBT_config_item& citem = cparser.nextItem(error);
776  if (error || citem.type == CI_END_OF_CONFIG) break;
777 
778  if (citem.type == CI_SPECIES) {
779  GBDATA *gb_species = GBT_find_species(GLOBAL.gb_main, citem.name);
780 
781  if (gb_species) {
782  int oldmark = GB_read_flag(gb_species);
783  int newmark = oldmark;
784  switch (ext_type) {
785  case CONF_EXTRACT:
786  case CONF_MARK: newmark = 1; break;
787  case CONF_UNMARK: newmark = 0; break;
788  case CONF_INVERT: newmark = !oldmark; break;
789  case CONF_COMBINE: {
790  nt_assert(!oldmark); // should have been unmarked above
791  newmark = GBS_read_hash(was_marked, citem.name); // mark if was_marked
792  break;
793  }
794  default: nt_assert(0); break;
795  }
796  if (newmark != oldmark) {
797  GB_write_flag(gb_species, newmark);
798  refresh = true;
799  }
800  }
801  else {
802  unknown_species++;
803  }
804  }
805  }
806  }
807 
808  if (was_marked) GBS_free_hash(was_marked);
809  if (unknown_species>0 && !error) error = GBS_global_string("configuration '%s' contains %zu unknown species", cn, unknown_species);
810  if (refresh) aw_root->awar(AWAR_TREE_REFRESH)->touch();
811  }
812  aw_message_if(error);
813  }
814  free(cn);
815 }
816 
819 
820  AW_awar *awar_selected = aww->get_root()->awar(AWAR_CONFIGURATION);
821  char *name = awar_selected->read_string();
822  GBDATA *gb_configuration = GBT_find_configuration(GLOBAL.gb_main, name);
823 
824  if (gb_configuration) {
825  dbsel->get_sellist()->move_selection(1);
826 
827  GB_ERROR error = GB_delete(gb_configuration);
828  error = ta.close(error);
829  if (error) {
830  aw_message(error);
831  }
832  else {
834  }
835  }
836  free(name);
837 }
838 
843 };
844 
845 static GB_ERROR nt_create_configuration(TreeNode *tree, const char *conf_name, int use_species_aside, ConfigCreation creation) {
846  GB_ERROR error = NULp;
847 
848  if (!conf_name || !conf_name[0]) error = "no config name given";
849  else {
850  if (use_species_aside==-1) {
851  static int last_used_species_aside = 3;
852  {
853  const char *val = GBS_global_string("%i", last_used_species_aside);
854  char *use_species = aw_input("How many extra species to view aside marked:", val);
855  if (use_species) use_species_aside = atoi(use_species);
856  free(use_species);
857  }
858 
859  if (use_species_aside<1) error = "illegal number of 'species aside'";
860  else last_used_species_aside = use_species_aside; // remember for next time
861  }
862 
863  if (!error) {
864  GB_transaction ta(GLOBAL.gb_main); // open close transaction
866 
867  GBT_config newcfg;
868  {
870  GBS_strstruct topfile(1000);
871  GBS_strstruct midfile(10000);
872  {
873  GBS_strstruct middlefile(10000);
874 
876 
877  if (use_species_aside) {
878  Store_species *extra_marked_species = NULp;
879  int auto_mark = 0;
880  int marked_at_right;
881 
882  nt_build_conf_string_rek(used, tree, middlefile, &extra_marked_species, use_species_aside, &auto_mark, use_species_aside, &marked_at_right);
883  if (extra_marked_species) {
884  extra_marked_species->call(unmark_species);
885  delete extra_marked_species;
886  }
887  }
888  else {
889  int dummy_1=0, dummy_2;
890  nt_build_conf_string_rek(used, tree, middlefile, NULp, 0, &dummy_1, 0, &dummy_2);
891  }
892  nt_build_conf_marked(GLOBAL.gb_main, used, midfile);
893  midfile.ncat(middlefile.get_data(), middlefile.get_position());
894  }
895 
896  newcfg.set_definition(GBT_config::TOP_AREA, topfile.release());
898 
899  GBS_free_hash(used);
900  }
901 
902  GBT_config previous(GLOBAL.gb_main, conf_name, error);
903  error = NULp; // ignore
904 
905  const char *prevComment = NULp; // old or fixed comment
906  const char *comment = NULp;
907  bool warnIfSavingDefault = true;
908  switch (creation) {
909  case BY_CALLING_THE_EDITOR: { // always saves DEFAULT_CONFIGURATION!
910  prevComment = "This configuration will be OVERWRITTEN each time\nARB_EDIT4 is started w/o specifying a config!\n---";
911  comment = "created for ARB_EDIT4";
912  warnIfSavingDefault = false;
913  break;
914  }
915  case FROM_MANAGER: {
916  if (previous.exists()) {
917  prevComment = previous.get_comment();
918  comment = "updated manually";
919  }
920  else {
921  prevComment = awr->awar(AWAR_CONFIG_COMMENT)->read_char_pntr();
922  if (!prevComment[0]) prevComment = NULp;
923  comment = "created manually";
924  }
925  break;
926  }
927  case FROM_IMPORTER:
928  nt_assert(!previous.exists());
929  comment = "created by importer";
930  break;
931  }
932 
933  nt_assert(implicated(prevComment, comment));
934  if (comment) {
935  // annotate with treename
936  const char *treename = awr->awar(AWAR_TREE_NAME)->read_char_pntr();
937  if (treename[0]) {
938  comment = GBS_global_string("%s (tree=%s)", comment, treename);
939  }
940  else {
941  comment = GBS_global_string("%s (no tree)", comment);
942  }
943  char *dated = GBS_log_action_to(prevComment, comment, true);
944  newcfg.set_comment(dated);
945  free(dated);
946  }
947 
948  error = newcfg.save(GLOBAL.gb_main, conf_name, warnIfSavingDefault);
949  awr->awar(AWAR_CONFIGURATION)->touch(); // refreshes comment field
950  }
951  }
952 
953  return error;
954 }
955 
957  const char *cfgName = AW_root::SINGLETON->awar(AWAR_CONFIGURATION)->read_char_pntr();
959  aw_message_if(err);
960 }
961 
963  AW_awar *awar_curr_cfg = aww->get_root()->awar(AWAR_CONFIGURATION);
964  char *old_name = awar_curr_cfg->read_string();
965 
966  {
967  char *new_name = aw_input("Rename selection", "Enter the new name of the selection", old_name);
968  if (new_name) {
969  GB_ERROR err = NULp;
970 
971  {
973 
974  GBDATA *gb_existing_cfg = GBT_find_configuration(GLOBAL.gb_main, new_name);
975  if (gb_existing_cfg) err = GBS_global_string("There is already a selection named '%s'", new_name);
976  else {
977  GBDATA *gb_old_cfg = GBT_find_configuration(GLOBAL.gb_main, old_name);
978  if (gb_old_cfg) {
979  GBDATA *gb_name = GB_entry(gb_old_cfg, "name");
980  if (gb_name) {
981  err = GB_write_string(gb_name, new_name);
982  if (!err) awar_curr_cfg->write_string(new_name);
983  }
984  else err = "Selection has no name";
985  }
986  else err = "Can't find that selection";
987  }
988  err = ta.close(err);
989  }
990 
991  if (err) {
992  aw_message(err);
993  }
994  else {
995  nt_assert(GB_get_transaction_level(GLOBAL.gb_main) == 0); // otherwise callback below behaves wrong
996  configuration_renamed_cb(old_name, new_name);
997  }
998  free(new_name);
999  }
1000  }
1001  free(old_name);
1002 }
1003 
1005  const char *config = root->awar(AWAR_CONFIGURATION)->read_char_pntr();
1006 
1007  bool nonexisting_config = false;
1008  GBDATA *gb_target_commment = NULp;
1009  if (config[0]) {
1010  GBDATA *gb_configuration = GBT_find_configuration(GLOBAL.gb_main, config);
1011  if (gb_configuration) {
1012  gb_target_commment = GB_entry(gb_configuration, "comment");
1013  }
1014  else {
1015  nonexisting_config = true;
1016  }
1017  }
1018 
1019  AW_awar *awar_comment = root->awar(AWAR_CONFIG_COMMENT);
1020  if (gb_target_commment) {
1021  if (!awar_comment->is_mapped()) awar_comment->write_string("");
1022  awar_comment->map(gb_target_commment);
1023  }
1024  else {
1025  char *reuse_comment = nonexisting_config ? awar_comment->read_string() : ARB_strdup("");
1026  if (awar_comment->is_mapped()) {
1027  awar_comment->unmap();
1028  }
1029  awar_comment->write_string(reuse_comment);
1030  free(reuse_comment);
1031  }
1032 }
1034  // called when comment-awar changes or gets re-map-ped
1035 
1036  AW_awar *awar_comment = root->awar(AWAR_CONFIG_COMMENT);
1037  const char *comment = awar_comment->read_char_pntr();
1038 
1039  const char *config = root->awar(AWAR_CONFIGURATION)->read_char_pntr();
1040  GBDATA *gb_configuration = config[0] ? GBT_find_configuration(GLOBAL.gb_main, config) : NULp;
1041 
1042  GB_ERROR error = NULp;
1043  if (awar_comment->is_mapped()) {
1044  if (!comment[0]) { // empty existing comment
1045  nt_assert(gb_configuration);
1046  GBDATA *gb_commment = GB_entry(gb_configuration, "comment");
1047  nt_assert(gb_commment);
1048  if (gb_commment) {
1049  awar_comment->unmap();
1050  error = GB_delete(gb_commment);
1051  }
1052  }
1053  }
1054  else {
1055  if (comment[0]) { // ignore empty comment for unmapped awar
1056  if (gb_configuration) {
1057  nt_assert(!GB_entry(gb_configuration, "comment"));
1058  error = GBT_write_string(gb_configuration, "comment", comment);
1059  if (!error) {
1060  awar_comment->write_string("");
1062  }
1063  }
1064  else if (!config[0]) {
1065  // do NOT warn if name field contains (not yet) existing name
1066  // (allows to edit comment while creating new config)
1067  error = "Please select an existing species selection to edit its comment";
1068  }
1069  }
1070  }
1071 
1072  aw_message_if(error);
1073 }
1074 
1075 static void init_config_admin_awars(AW_root *root) {
1076  init_config_awars(root);
1079 }
1080 
1081 #pragma GCC diagnostic push
1082 #if (GCC_VERSION_CODE<700)
1083 #pragma GCC diagnostic ignored "-Wstrict-overflow" // gcc 6.x produces a bogus overflow warning (gcc 7.x is smart enough)
1084 #endif
1085 
1086 static GB_ERROR swap_configs(GBDATA *gb_main, StrArray& config, int i1, int i2) {
1087  GB_ERROR error = NULp;
1088 
1089  if (i1>i2) swap(i1, i2); // otherwise overwrite below does not work
1090  nt_assert(i1<i2 && i1>=0 && i2<int(config.size()));
1091 
1092  GBT_config c1(gb_main, config[i1], error);
1093  if (!error) {
1094  GBT_config c2(gb_main, config[i2], error);
1095  if (!error) error = c1.saveAsOver(gb_main, config[i1], config[i2], false);
1096  if (!error) error = c2.saveAsOver(gb_main, config[i2], config[i1], false);
1097  if (!error) config.swap(i1, i2);
1098  }
1099  return error;
1100 }
1101 
1102 #pragma GCC diagnostic pop
1103 
1105  AW_root *awr = aww->get_root();
1106  AW_awar *awar_config = awr->awar(AWAR_CONFIGURATION);
1107  const char *selected = awar_config->read_char_pntr();
1108 
1109  if (selected && selected[0]) {
1110  AW_selection_list *sellist = sel->get_sellist();
1111 
1112  int source_idx = sellist->get_index_of(AW_scalar(selected));
1113  int target_idx = -1;
1114  switch (mode) {
1115  case ARM_TOP: target_idx = 0; break;
1116  case ARM_UP: target_idx = source_idx-1; break;
1117  case ARM_DOWN: target_idx = source_idx+1; break;
1118  case ARM_BOTTOM: target_idx = -1; break;
1119  }
1120 
1121  int entries = sellist->size();
1122  target_idx = (target_idx+entries)%entries;
1123 
1124  {
1125  GBDATA *gb_main = sel->get_gb_main();
1126  GB_transaction ta(gb_main);
1127 
1128  StrArray config;
1129  sellist->to_array(config, true);
1130 
1131  GB_ERROR error = NULp;
1132  if (source_idx<target_idx) {
1133  for (int i = source_idx+1; i<=target_idx; ++i) {
1134  swap_configs(gb_main, config, i-1, i);
1135  }
1136  }
1137  else if (source_idx>target_idx) {
1138  for (int i = source_idx-1; i>=target_idx; --i) {
1139  swap_configs(gb_main, config, i+1, i);
1140  }
1141  }
1142 
1143  error = ta.close(error);
1144  aw_message_if(error);
1145  }
1146  awar_config->touch();
1147  }
1148 }
1149 
1150 static void clear_comment_cb(AW_window *aww) {
1151  AW_awar *awar_comment = aww->get_root()->awar(AWAR_CONFIG_COMMENT);
1152  char *comment = awar_comment->read_string();
1153 
1155  GBT_splitNdestroy_string(line, comment, '\n');
1156 
1157  bool removedDatedLines = false;
1158  RegExpr datedLine("^([A-Z][a-z]{2}\\s){2}[0-9]+\\s([0-9]{2}:){2}[0-9]{2}\\s[0-9]{4}:\\s", false); // matches lines created with GBS_log_action_to(..., stamp=true)
1159  for (int i = line.size()-1; i >= 0; --i) {
1160  const RegMatch *match = datedLine.match(line[i]);
1161  nt_assert(implicated(!match, !datedLine.has_failed())); // assert RegExpr compiles
1162  if (match && match->didMatch()) {
1163  line.safe_remove(i);
1164  removedDatedLines = true;
1165  }
1166  }
1167 
1168  if (!removedDatedLines) line.clear(); // erase all
1169 
1170  comment = GBT_join_strings(line, '\n');
1171  awar_comment->write_string(comment);
1172 }
1173 
1175  static AW_window_simple *existing_aws[MAX_NT_WINDOWS] = { MAX_NT_WINDOWS_NULLINIT };
1176 
1177  int ntw_id = ntw->get_index();
1178  if (!existing_aws[ntw_id]) {
1180 
1181  AW_window_simple *aws = new AW_window_simple;
1182  aws->init(root, GBS_global_string("SPECIES_SELECTIONS_%i", ntw_id), "Species Selections");
1183  aws->load_xfig("nt_selection.fig");
1184 
1185  aws->at("close");
1186  aws->callback(AW_POPDOWN);
1187  aws->create_button("CLOSE", "CLOSE", "C");
1188 
1189  aws->at("help");
1190  aws->callback(makeHelpCallback("species_configs.hlp"));
1191  aws->create_button("HELP", "HELP", "H");
1192 
1193  aws->at("name");
1194  aws->create_input_field(AWAR_CONFIGURATION);
1195 
1196  aws->at("comment");
1197  aws->create_text_field(AWAR_CONFIG_COMMENT);
1198 
1199  aws->at("clr");
1200  aws->callback(clear_comment_cb);
1201  aws->create_autosize_button("CLEAR", "Clear", "l");
1202 
1203  aws->at("list");
1205 
1206  aws->button_length(8);
1207 
1208  aws->at("store");
1209  aws->callback(makeWindowCallback(nt_store_configuration, ntw));
1210  aws->create_button(GBS_global_string("STORE_%i", ntw_id), "STORE", "S");
1211 
1212  aws->at("extract");
1213  aws->callback(makeWindowCallback(nt_extract_configuration, CONF_EXTRACT));
1214  aws->create_button("EXTRACT", "EXTRACT", "E");
1215 
1216  aws->at("mark");
1217  aws->callback(makeWindowCallback(nt_extract_configuration, CONF_MARK));
1218  aws->create_button("MARK", "MARK", "M");
1219 
1220  aws->at("unmark");
1221  aws->callback(makeWindowCallback(nt_extract_configuration, CONF_UNMARK));
1222  aws->create_button("UNMARK", "UNMARK", "U");
1223 
1224  aws->at("invert");
1225  aws->callback(makeWindowCallback(nt_extract_configuration, CONF_INVERT));
1226  aws->create_button("INVERT", "INVERT", "I");
1227 
1228  aws->at("combine");
1229  aws->callback(makeWindowCallback(nt_extract_configuration, CONF_COMBINE));
1230  aws->create_button("COMBINE", "COMBINE", "C");
1231 
1232  aws->at("delete");
1233  aws->callback(makeWindowCallback(nt_delete_configuration, dbsel));
1234  aws->create_button("DELETE", "DELETE", "D");
1235 
1236  aws->at("rename");
1237  aws->callback(nt_rename_configuration);
1238  aws->create_button("RENAME", "RENAME", "R");
1239 
1240  aws->at("highlight");
1241  aws->callback(makeCreateWindowCallback(create_configuration_marker_window, ntw));
1242  aws->create_autosize_button(GBS_global_string("HIGHLIGHT_%i", ntw_id), "Highlight in tree", "t");
1243 
1244  aws->button_length(0);
1245  aws->at("sort");
1247 
1248  existing_aws[ntw_id] = aws;
1249  }
1250  return existing_aws[ntw_id];
1251 }
1252 
1254  create_configuration_admin_window(aw_main->get_root(), ntw)->activate();
1255 }
1256 
1257 // -----------------------------------------
1258 // various ways to start the editor
1259 
1261  aww->hide();
1262 
1263  const char *cfgName = aww->get_root()->awar(AWAR_CONFIGURATION)->read_char_pntr();
1264  char *quotedCfg = GBK_singlequote(cfgName);
1265 
1266  AWT_system_cb(GBS_global_string("arb_edit4 -c %s &", quotedCfg));
1267 
1268  free(quotedCfg);
1269 }
1270 
1272  static AW_window_simple *aws = NULp;
1273  if (!aws) {
1274  init_config_awars(awr);
1275 
1276  aws = new AW_window_simple;
1277  aws->init(awr, "SELECT_CONFIGURATION", "SELECT A CONFIGURATION");
1278  aws->at(10, 10);
1279  aws->auto_space(0, 0);
1281  aws->at_newline();
1282 
1283  aws->callback(nt_start_editor_on_configuration);
1284  aws->create_button("START", "START");
1285 
1286  aws->callback(AW_POPDOWN);
1287  aws->create_button("CLOSE", "CLOSE", "C");
1288 
1289  aws->window_fit();
1290  }
1291  return aws;
1292 }
1293 
1294 void NT_start_editor_on_tree(AW_window *aww, int use_species_aside, TREE_canvas *ntw) {
1295  init_config_awars(aww->get_root());
1297  if (!error) error = GBK_system("arb_edit4 -c " DEFAULT_CONFIGURATION " &");
1298  aw_message_if(error);
1299 }
1300 
1302  init_config_awars(ntw->awr);
1303 
1304  const char *dated_suffix = ARB_dateTime_suffix();
1305  char *configName = GBS_global_string_copy("imported_%s", dated_suffix);
1306 
1307  // ensure unique config-name
1308  {
1309  int unique = 1;
1310  GB_transaction ta(ntw->gb_main);
1311  while (GBT_find_configuration(ntw->gb_main, configName)) {
1312  freeset(configName, GBS_global_string_copy("imported_%s_%i", dated_suffix, ++unique));
1313  }
1314  }
1315 
1317  aw_message_if(error);
1318 
1319  free(configName);
1320 }
1321 
1322 void NT_create_config_after_import(TREE_canvas *ntw, bool imported_from_scratch) {
1328  if (imported_from_scratch) {
1330  }
1331  else {
1332  GB_transaction ta(ntw->gb_main);
1333 
1334  // remember marks + mark queried species:
1335  for (GBDATA *gb_species = GBT_first_species(ntw->gb_main); gb_species; gb_species = GBT_next_species(gb_species)) {
1336  GB_write_user_flag(gb_species, GB_USERFLAG_WASMARKED, GB_read_flag(gb_species));
1337  GB_write_flag(gb_species, GB_user_flag(gb_species, GB_USERFLAG_QUERY));
1338  }
1339 
1341 
1342  // restore old marks:
1343  for (GBDATA *gb_species = GBT_first_species(ntw->gb_main); gb_species; gb_species = GBT_next_species(gb_species)) {
1344  GB_write_flag(gb_species, GB_user_flag(gb_species, GB_USERFLAG_WASMARKED));
1346  }
1347  }
1348 }
1349 
1350 // --------------------------------------------------------------------------------
1351 
1352 #ifdef UNIT_TESTS
1353 #ifndef TEST_UNIT_H
1354 #include <test_unit.h>
1355 #endif
1356 
1357 static bool fold_group(TreeNode *tree, const char *groupName) {
1358  if (!tree->is_leaf()) {
1359  if (tree->is_normal_group()) {
1360  nt_assert(tree->name);
1361  fprintf(stderr, "group='%s' groupName='%s'\n", tree->name, groupName);
1362  if (strcmp(tree->name, groupName) == 0) {
1363  nt_assert(tree->gb_node);
1364  GBDATA *gb_grouped = GB_entry(tree->gb_node, "grouped");
1365  if (!gb_grouped) {
1366  gb_grouped = GB_create(tree->gb_node, "grouped", GB_BYTE);
1367  }
1368  TEST_REJECT_NULL(gb_grouped);
1369  if (GB_read_byte(gb_grouped) == 0) {
1370  TEST_EXPECT_NO_ERROR(GB_write_byte(gb_grouped, 1));
1371  return true;
1372  }
1373  }
1374  }
1375  return
1376  fold_group(tree->get_leftson(), groupName) ||
1377  fold_group(tree->get_rightson(), groupName);
1378  }
1379  return false;
1380 }
1381 
1382 void TEST_build_conf_string() {
1383  GB_shell shell;
1384  GBDATA *gb_main = GB_open("TEST_trees.arb", "r");
1385 
1386  {
1387  GB_transaction ta(gb_main);
1388 
1389  TreeNode *tree = GBT_read_tree(gb_main, "tree_groups", new SimpleRoot);
1390 
1391  GBS_strstruct memfile(500);
1392  Store_species *extra_marked_species = NULp;
1393 
1394  TEST_REJECT_NULL(tree);
1395  TEST_EXPECT_NO_ERROR(GBT_link_tree(tree, gb_main, false, NULp, NULp));
1396 
1397  int auto_mark = 0;
1398  int dummy;
1399  int marked;
1400 
1401  // test result with no species marked:
1402  GBT_mark_all(gb_main, 0);
1404  {
1405  GB_HASH *used = GBS_create_hash(100, GB_IGNORE_CASE);
1406 
1407  memfile.erase();
1408  marked = nt_build_conf_string_rek(used, tree, memfile, &extra_marked_species, 0, &auto_mark, 0, &dummy);
1409  TEST_EXPECT_EQUAL(marked, 0);
1410  TEST_EXPECT_EQUAL(memfile.get_data(), "");
1411  TEST_EXPECT_NULL(extra_marked_species);
1412 
1414  GBS_free_hash(used);
1415  }
1416 
1417  // mark some species:
1418  TEST_EXPECT_NO_ERROR(GBT_restore_marked_species(gb_main, "CloButy2;CloPaste;CorAquat;CurCitre;CloTyro4"));
1420 
1421  {
1422  GB_HASH *used = GBS_create_hash(100, GB_IGNORE_CASE);
1423 
1424  memfile.erase();
1425  marked = nt_build_conf_string_rek(used, tree, memfile, &extra_marked_species, 0, &auto_mark, 0, &dummy);
1426  TEST_EXPECT_EQUAL(marked, 5); // ------------------------------------- v 'G' indicates the open group
1427  TEST_EXPECT_EQUAL(memfile.get_data(), "\1Gupper\1LCloButy2\1E\1Glower\1Glow1\1LCurCitre\1LCorAquat\1LCloPaste\1E\1Glow2\1LCloTyro4\1E\1E");
1428  TEST_EXPECT_NULL(extra_marked_species);
1429 
1431  GBS_free_hash(used);
1432  }
1433 
1434  // test with closed groups:
1435  {
1436  GB_HASH *used = GBS_create_hash(100, GB_IGNORE_CASE);
1437 
1438  TEST_EXPECT(fold_group(tree, "low1"));
1439 
1440  memfile.erase();
1441  marked = nt_build_conf_string_rek(used, tree, memfile, &extra_marked_species, 0, &auto_mark, 0, &dummy);
1442  TEST_EXPECT_EQUAL(marked, 5); // ------------------------------------- v 'F' indicates the closed group
1443  TEST_EXPECT_EQUAL(memfile.get_data(), "\1Gupper\1LCloButy2\1E\1Glower\1Flow1\1LCurCitre\1LCorAquat\1LCloPaste\1E\1Glow2\1LCloTyro4\1E\1E");
1444  TEST_EXPECT_NULL(extra_marked_species);
1445 
1447  GBS_free_hash(used);
1448  }
1449 
1450  // test with marking 2 species aside:
1451  {
1452  GB_HASH *used = GBS_create_hash(100, GB_IGNORE_CASE);
1453 
1454  memfile.erase();
1455  marked = nt_build_conf_string_rek(used, tree, memfile, &extra_marked_species, 2, &auto_mark, 0, &dummy);
1456  TEST_EXPECT_EQUAL(marked, 11);
1457  TEST_EXPECT_EQUAL(memfile.get_data(), "\1Gupper\1LCloTyro3\1LCloButyr\1LCloButy2\1LCloBifer\1LCloInnoc\1E\1Glower\1Flow1\1LCytAquat\1LCurCitre\1LCorAquat\1LCelBiazo\1LCorGluta\1LCloCarni\1LCloPaste\1E\1Glow2\1Gtwoleafs\1LCloTyrob\1LCloTyro2\1E\1LCloTyro4\1E\1E");
1458 
1459  TEST_REJECT_NULL(extra_marked_species);
1460  TEST_EXPECT_EQUAL(GBT_count_marked_species(gb_main), 15); // 5 species were marked before + marked 5*2 neighbors
1461  extra_marked_species->call(unmark_species);
1462  delete extra_marked_species;
1463  TEST_EXPECT_EQUAL(GBT_count_marked_species(gb_main), 5); // 5 previously marked species
1464 
1466  GBS_free_hash(used);
1467  }
1468 
1469  // test nt_build_conf_marked:
1470  {
1471  GB_HASH *used = GBS_create_hash(100, GB_IGNORE_CASE);
1472 
1473  memfile.erase();
1474  nt_build_conf_marked(gb_main, used, memfile);
1475  TEST_EXPECT_EQUAL(memfile.get_data(), "\1FMore Sequences\1LCorAquat\1LCurCitre\1LCloButy2\1LCloPaste\1LCloTyro4\1E");
1476 
1477  // exclude 2 species (simulates that they are already in "normal" config)
1478  GBS_write_hash(used, "CurCitre", 1);
1479  GBS_write_hash(used, "CloPaste", 1);
1480  memfile.erase();
1481  nt_build_conf_marked(gb_main, used, memfile);
1482  TEST_EXPECT_EQUAL(memfile.get_data(), "\1FMore Sequences\1LCorAquat\1LCloButy2\1LCloTyro4\1E");
1483 
1484  GBS_free_hash(used);
1485  }
1486 
1487  // test nt_build_sai_string:
1488  {
1489  GBS_strstruct topfile(500);
1490 
1491  memfile.erase();
1492  nt_build_sai_string(gb_main, "HELIX_NR;HELIX;dummy", topfile, memfile);
1493 
1494  TEST_EXPECT_EQUAL(topfile.get_data(), "\1SHELIX_NR\1SHELIX");
1495  TEST_EXPECT_EQUAL(memfile.get_data(), "\1GSAI-Maingroup\1FSAI:SAI's\1SPOS_VAR_BY_PARSIMONY\1E\1FSAI:special\1SECOLI\1E\1E");
1496  }
1497 
1498  destroy(tree);
1499  }
1500 
1501  GB_close(gb_main);
1502 }
1503 
1504 #endif // UNIT_TESTS
1505 
1506 // --------------------------------------------------------------------------------
1507 
1508 
void NT_popup_configuration_admin(AW_window *aw_main, TREE_canvas *ntw)
Definition: NT_edconf.cxx:1253
GB_HASH * GBT_create_marked_species_hash(GBDATA *gb_main)
Definition: adhashtools.cxx:40
GB_ERROR GBK_system(const char *system_command)
Definition: arb_msg.cxx:571
void GBS_hash_do_const_sorted_loop(const GB_HASH *hs, gb_hash_const_loop_type func, gbs_hash_compare_function sorter, void *client_data)
Definition: adhash.cxx:641
const char * GB_ERROR
Definition: arb_core.h:25
void set_marker_display(MarkerDisplay *display)
static void reorder_configs_cb(AW_window *aww, awt_reorder_mode mode, AW_DB_selection *sel)
Definition: NT_edconf.cxx:1104
static void configuration_deleted_cb(const char *name)
Definition: NT_edconf.cxx:348
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
void cut_tail(size_t byte_count)
Definition: arb_strbuf.h:145
static AW_selection * selected_configs_list[MAX_NT_WINDOWS]
Definition: NT_edconf.cxx:161
void add(const char *awar_name, const char *config_name)
GBDATA * GBT_first_marked_species(GBDATA *gb_main)
Definition: aditem.cxx:113
size_t size() const
Definition: arb_strarray.h:85
AW_window * NT_create_startEditorOnOldConfiguration_window(AW_root *awr)
Definition: NT_edconf.cxx:1271
static void selected_configs_display_awar_changed_cb(AW_root *root, TREE_canvas *ntw)
Definition: NT_edconf.cxx:200
#define GB_USERFLAG_WASMARKED
Definition: arbdb.h:56
void NT_create_config_after_import(TREE_canvas *ntw, bool imported_from_scratch)
Definition: NT_edconf.cxx:1322
Store_species(TreeNode *aNode)
Definition: NT_edconf.cxx:402
Definition: arbdb.h:65
GB_ERROR GB_add_hierarchy_callback(GBDATA *gb_main, const char *db_path, GB_CB_TYPE type, const DatabaseCallback &dbcb)
Definition: ad_cb.cxx:432
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
static void nt_build_sai_string_by_hash(const char *key, long, void *cd_sai_builder)
Definition: NT_edconf.cxx:624
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
Definition: adhash.cxx:454
GB_ERROR GBT_restore_marked_species(GBDATA *gb_main, const char *stored_marked)
Definition: aditem.cxx:446
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
Definition: arbdb.cxx:1387
static AW_window * create_configuration_marker_window(AW_root *root, TREE_canvas *ntw)
Definition: NT_edconf.cxx:350
#define CONFIG_SEPARATOR
Definition: NT_edconf.cxx:133
#define ASSERT_NO_ERROR(errorExpr)
Definition: arb_assert.h:360
long GBT_mark_all(GBDATA *gb_main, int flag)
Definition: aditem.cxx:295
static const int MIDDLE_AREA
Definition: ad_config.h:49
Store_species * add(Store_species *list)
Definition: NT_edconf.cxx:408
static void init_config_awars(AW_root *root)
Definition: NT_edconf.cxx:165
AW_selection * awt_create_subset_selection_list(AW_window *aww, AW_selection_list *parent_selection, const char *at_box, const char *at_add, const char *at_sort, bool autocorrect_subselection, SubsetChangedCb subChanged_cb, AW_CL cl_user)
void add(int v)
Definition: ClustalV.cxx:461
#define AWAR_CONFIG_COMMENT
Definition: NT_edconf.cxx:43
#define AWAR_CL_DISPLAY_CONFIG_MARKERS
Definition: NT_edconf.cxx:41
extractType
Definition: NT_edconf.cxx:45
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
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)
TreeNode * GBT_read_tree(GBDATA *gb_main, const char *tree_name, TreeRoot *troot)
Definition: adtree.cxx:837
long read_int() const
Definition: AW_awar.cxx:184
static const int TOP_AREA
Definition: ad_config.h:48
void NT_start_editor_on_tree(AW_window *aww, int use_species_aside, TREE_canvas *ntw)
Definition: NT_edconf.cxx:1294
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
#define AWAR_CONFIGURATION
AW_root * awr
Definition: awt_canvas.hxx:338
static void init_config_admin_awars(AW_root *root)
Definition: NT_edconf.cxx:1075
STL namespace.
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
char * release()
Definition: arb_strbuf.h:129
const char CFG_SEP
Definition: NT_edconf.cxx:480
void GBS_free_hash(GB_HASH *hs)
Definition: adhash.cxx:538
#define MANAGED_CONFIGSET_ENTRY
Definition: NT_edconf.cxx:270
static void nt_delete_configuration(AW_window *aww, AW_DB_selection *dbsel)
Definition: NT_edconf.cxx:817
TreeNode * getNode() const
Definition: NT_edconf.cxx:420
void cat(const char *from)
Definition: arb_strbuf.h:183
void get_values(StrArray &intoArray)
Definition: aw_select.hxx:198
bool modifyConfig(ConstStrArray &config) const
Definition: NT_edconf.cxx:284
static GB_ERROR swap_configs(GBDATA *gb_main, StrArray &config, int i1, int i2)
Definition: NT_edconf.cxx:1086
ConfigRenamer(const char *oldName_, const char *newName_)
Definition: NT_edconf.cxx:307
static void nt_build_conf_marked(GBDATA *gb_main, GB_HASH *used, GBS_strstruct &file)
Definition: NT_edconf.cxx:716
ConfigCreation
Definition: NT_edconf.cxx:839
bool is_mapped() const
Definition: aw_awar.hxx:153
GB_ERROR GBT_link_tree(TreeNode *tree, GBDATA *gb_main, bool show_status, int *zombies, int *duplicates)
Definition: adtree.cxx:953
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1722
AW_awar * get_config_awar(int canvas_id)
Definition: NT_edconf.cxx:138
#define MAX_NT_WINDOWS_NULLINIT
Definition: NT_local.h:33
bool empty() const
Definition: arb_strarray.h:86
unsigned long GB_ULONG
Definition: arbdb_base.h:42
ConfigDeleter(const char *toDelete_)
Definition: NT_edconf.cxx:318
static void unmark_species(TreeNode *node)
Definition: NT_edconf.cxx:434
#define DEFAULT_CONFIGURATION
Definition: ad_config.h:30
static SmartPtr< ConstStrArray > get_selected_configs_from_awar(int canvas_id)
Definition: NT_edconf.cxx:141
TreeNode * rightson
Definition: TreeNode.h:171
#define DOWNCAST(totype, expr)
Definition: downcast.h:141
ConfigMarkerDisplay(SmartPtr< ConstStrArray > config_, GBDATA *gb_main_)
Definition: NT_edconf.cxx:95
void GBT_split_string(ConstStrArray &dest, const char *namelist, const char *separator, bool dropEmptyTokens)
Definition: arb_strarray.h:232
const char * ARB_dateTime_suffix()
Definition: arb_string.cxx:54
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:231
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1916
struct Unfixed_cb_parameter * UNFIXED
Definition: cb_base.h:15
static struct aisc_static_set_mem md
#define AWAR_CL_SELECTED_CONFIGS
Definition: NT_edconf.cxx:40
static TreeNode * left_neighbour_leaf(TreeNode *node)
Definition: NT_edconf.cxx:461
POS_TREE1 * father
Definition: probe_tree.h:39
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
bool GB_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2750
static void configuration_renamed_cb(const char *old_name, const char *new_name)
Definition: NT_edconf.cxx:347
void to_array(StrArray &array, bool values)
Definition: AW_select.cxx:516
bool didMatch() const
Definition: RegExpr.hxx:37
static AW_root * SINGLETON
Definition: aw_root.hxx:102
TreeNode * NT_get_tree_root_of_canvas(TREE_canvas *ntw)
Definition: NT_extern.cxx:858
AW_window * TREE_create_marker_settings_window(AW_root *root)
bool exists() const
Definition: ad_config.h:51
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
#define TEST_EXPECT(cond)
Definition: test_unit.h:1328
static void selected_config_changed_cb(AW_root *root)
Definition: NT_edconf.cxx:1004
char * GBT_read_string(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:267
static char * correct_managed_configsets_cb(const char *key, const char *value, AW_CL cl_ConfigModifier)
Definition: NT_edconf.cxx:323
GBDATA * GB_create(GBDATA *father, const char *key, GB_TYPES type)
Definition: arbdb.cxx:1781
AW_MouseButton
Definition: aw_window.hxx:70
GBDATA * get_gb_main()
Definition: AW_select.cxx:592
long GB_number_of_subentries(GBDATA *gbd)
Definition: arbdb.cxx:2892
static void config_modified_cb(GBDATA *gb_cfg_area)
Definition: NT_edconf.cxx:215
void hide_marker_display()
bool displays_config_markers(MarkerDisplay *md)
Definition: NT_edconf.cxx:131
static void selected_configs_awar_changed_cb(AW_root *aw_root, TREE_canvas *ntw)
Definition: NT_edconf.cxx:168
GBT_CONFIG_ITEM_TYPE type
Definition: ad_config.h:83
AW_DB_selection * awt_create_CONFIG_selection_list(GBDATA *gb_main, AW_window *aws, const char *varname)
static void nt_extract_configuration(UNFIXED, extractType ext_type)
Definition: NT_edconf.cxx:737
MarkerDisplay * get_marker_display()
#define AWAR_TREE_NAME
Definition: ad_trees.h:18
static void modify_configurations(const ConfigModifier &mod)
Definition: NT_edconf.cxx:335
#define MAX_NT_WINDOWS
Definition: NT_local.h:32
Store_species * remove()
Definition: NT_edconf.cxx:414
static int nt_build_conf_string_rek(GB_HASH *used, TreeNode *tree, GBS_strstruct &memfile, Store_species **extra_marked_species, int use_species_aside, int *auto_mark, int marked_at_left, int *marked_at_right)
Definition: NT_edconf.cxx:482
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1325
int get_index_of(const AW_scalar &searched_value)
Definition: AW_select.cxx:303
virtual ~ConfigModifier()
Definition: NT_edconf.cxx:281
void touch()
Definition: AW_awar.cxx:207
const char * get_comment() const
Definition: ad_config.h:63
static void error(const char *msg)
Definition: mkptypes.cxx:96
#define AWAR_TREE_REFRESH
#define NO_CONFIG_SELECTED
void remove(int i)
Definition: arb_strarray.h:103
const RegMatch * match(const std::string &versus, size_t offset=0) const
Definition: RegExpr.cxx:80
void set_comment(const char *newComment)
Definition: ad_config.h:64
void GBT_splitNdestroy_string(ConstStrArray &names, char *&namelist, const char *separator, bool dropEmptyTokens)
static AW_window * create_configuration_admin_window(AW_root *root, TREE_canvas *ntw)
Definition: NT_edconf.cxx:1174
static void install_config_change_callbacks(GBDATA *gb_main)
Definition: NT_edconf.cxx:243
GBDATA * GBT_next_marked_species(GBDATA *gb_species)
Definition: aditem.cxx:116
static bool allow_selection2awar_update
Definition: NT_edconf.cxx:162
CONSTEXPR_INLINE_Cxx14 void swap(unsigned char &c1, unsigned char &c2)
Definition: ad_io_inline.h:19
GB_ULONG GB_time_of_day(void)
Definition: adsocket.cxx:357
GB_ERROR save(GBDATA *gb_main, const char *name, bool warnIfSavingDefault) const
Definition: ad_config.h:67
size_t GBS_hash_elements(const GB_HASH *hs)
Definition: adhash.cxx:570
static void nt_build_sai_string(GBDATA *gb_main, const char *topAreaSaiList, GBS_strstruct &topfile, GBS_strstruct &middlefile)
Definition: NT_edconf.cxx:648
GBDATA * GBT_first_SAI_rel_SAI_data(GBDATA *gb_sai_data)
Definition: aditem.cxx:159
static void mark_species(TreeNode *node, Store_species **extra_marked_species)
Definition: NT_edconf.cxx:441
AW_awar * get_canvas_awar(const char *awar_name_format, int canvas_id)
Definition: NT_edconf.cxx:135
AW_awar * get_display_toggle_awar(int canvas_id)
Definition: NT_edconf.cxx:139
static void nt_store_configuration(AW_window *, TREE_canvas *ntw)
Definition: NT_edconf.cxx:956
void safe_remove(int i)
Definition: arb_strarray.h:114
static void nt_start_editor_on_configuration(AW_window *aww)
Definition: NT_edconf.cxx:1260
static TreeNode * rightmost_leaf(TreeNode *node)
Definition: NT_edconf.cxx:452
map< string, string > ConfigHits
Definition: NT_edconf.cxx:54
static SearchTree * tree[SEARCH_PATTERNS]
Definition: ED4_search.cxx:629
int GB_read_flag(GBDATA *gbd)
Definition: arbdb.cxx:2796
char * read_string() const
Definition: AW_awar.cxx:198
AW_awar * awar_no_error(const char *awar)
end timer stuff
Definition: AW_root.cxx:549
GB_ERROR saveAsOver(GBDATA *gb_main, const char *name, const char *oldName, bool warnIfSavingDefault) const
Definition: ad_config.cxx:101
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
void awt_create_order_buttons(AW_window *aws, awt_orderfun reorder_cb, AW_CL cl_user)
Definition: AWT_modules.cxx:17
char * GBS_log_action_to(const char *comment, const char *action, bool stamp)
Definition: adstring.cxx:976
void awt_set_subset_selection_content(AW_selection *subset_sel_, const CharPtrArray &values)
AW_awar * unmap()
Definition: AW_awar.cxx:596
Definition: arbdb.h:86
GBDATA * GBT_find_configuration(GBDATA *gb_main, const char *name)
Definition: ad_config.cxx:58
void call(void(*aPizza)(TreeNode *)) const
Definition: NT_edconf.cxx:429
long GBT_count_marked_species(GBDATA *gb_main)
Definition: aditem.cxx:372
const char * get_marker_name(int markerIdx) const OVERRIDE
Definition: NT_edconf.cxx:102
static void configs_selectionlist_changed_cb(AW_selection *selected_configs, bool interactive_change, AW_CL ntw_id)
Definition: NT_edconf.cxx:205
#define TEST_EXPECT_ZERO(cond)
Definition: test_unit.h:1085
int get_index() const
#define nt_assert(cond)
Definition: NT_local.h:27
static GB_ERROR nt_create_configuration(TreeNode *tree, const char *conf_name, int use_species_aside, ConfigCreation creation)
Definition: NT_edconf.cxx:845
const std::string * has_failed() const
Definition: RegExpr.hxx:78
char * awar_name
Definition: aw_awar.hxx:103
static void setup_configmarker_config_cb(AWT_config_definition &config, int ntw_id)
Definition: NT_edconf.cxx:272
AWT_graphic * gfx
Definition: awt_canvas.hxx:339
char * GBT_join_strings(const CharPtrArray &strings, char separator)
GBDATA * GBT_next_SAI(GBDATA *gb_sai)
Definition: aditem.cxx:166
#define AWAR_TOPAREA_SAIS
Definition: NT_local.h:30
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
#define CONFIG_BASE_PATH
Definition: NT_edconf.cxx:241
#define TEST_EXPECT_NULL(n)
Definition: test_unit.h:1322
xml element
void NT_activate_configMarkers_display(TREE_canvas *ntw)
Definition: NT_edconf.cxx:254
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:35
char * GBK_singlequote(const char *arg)
Definition: arb_msg.cxx:599
void GB_write_flag(GBDATA *gbd, long flag)
Definition: arbdb.cxx:2773
long AW_CL
Definition: cb.h:21
void GB_write_user_flag(GBDATA *gbd, unsigned char user_bit, bool state)
Definition: arbdb.cxx:2765
GB_ERROR GBT_write_string(GBDATA *gb_container, const char *fieldpath, const char *content)
Definition: adtools.cxx:451
const GBT_config_item & nextItem(GB_ERROR &error)
Definition: ad_config.cxx:139
#define OVERRIDE
Definition: cxxforward.h:110
void move_selection(int offset)
Definition: AW_select.cxx:415
void nt_create_config_after_import(TREE_canvas *ntw)
Definition: NT_edconf.cxx:1301
char * name
Definition: TreeNode.h:174
int GB_read_byte(GBDATA *gbd)
Definition: arbdb.cxx:734
awt_reorder_mode
Definition: awt_modules.hxx:22
AW_awar * map(const char *awarn)
Definition: AW_awar.cxx:521
char * GB_read_string(GBDATA *gbd)
Definition: arbdb.cxx:909
GB_ERROR GB_write_byte(GBDATA *gbd, int i)
Definition: arbdb.cxx:1238
void AWT_modify_managed_configs(AW_default default_file, const char *id, ConfigModifyCallback mod_cb, AW_CL cl_user)
GBDATA * GBT_first_species(GBDATA *gb_main)
Definition: aditem.cxx:124
#define TEST_EXPECT_NO_ERROR(call)
Definition: test_unit.h:1118
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
static void config_comment_changed_cb(AW_root *root)
Definition: NT_edconf.cxx:1033
void hide()
Definition: AW_window.cxx:1835
void GB_clear_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2760
int GBS_HCF_sortedByKey(const char *k0, long dummy_1x, const char *k1, long dummy_2x)
Definition: adhash.cxx:653
#define MANAGED_CONFIGSET_SECTION
Definition: NT_edconf.cxx:269
AW_root * get_root()
Definition: aw_window.hxx:354
static int line
Definition: arb_a2ps.c:296
GBDATA * GBT_next_species(GBDATA *gb_species)
Definition: aditem.cxx:128
#define NULp
Definition: cxxforward.h:114
GBDATA * gb_main
Definition: NT_local.h:37
static void write_configs_to_awar(int canvas_id, const CharPtrArray &configs)
Definition: NT_edconf.cxx:153
GBDATA * GBT_find_species(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:139
static void clear_comment_cb(AW_window *aww)
Definition: NT_edconf.cxx:1150
void retrieve_marker_state(const char *speciesName, NodeMarkers &node) OVERRIDE
Definition: NT_edconf.cxx:108
GB_ERROR write_string(const char *aw_string)
const char * get_data() const
Definition: arb_strbuf.h:120
GBDATA * GBT_find_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name)
Definition: aditem.cxx:171
#define GB_USERFLAG_QUERY
Definition: arbdb.h:55
int GB_get_transaction_level(GBDATA *gbd)
Definition: arbdb.cxx:2590
void handle_click(int markerIdx, AW_MouseButton button, AWT_graphic_exports &exports) OVERRIDE
Definition: NT_edconf.cxx:120
long GBT_get_species_count(GBDATA *gb_main)
Definition: aditem.cxx:207
GB_transaction ta(gb_var)
void destroy(TreeNode *that)
Definition: TreeNode.h:600
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
Definition: arbdb.cxx:904
GBDATA * gb_node
Definition: TreeNode.h:173
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 * GBT_get_SAI_data(GBDATA *gb_main)
Definition: aditem.cxx:154
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
Definition: adquery.cxx:531
char * aw_input(const char *title, const char *prompt, const char *default_input)
Definition: AW_modal.cxx:251
const char * replace(int i, const char *elem)
Definition: arb_strarray.h:217
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1294
static void nt_rename_configuration(AW_window *aww)
Definition: NT_edconf.cxx:962
bool is_normal_group() const
Definition: TreeNode.h:470
long GBS_read_hash(const GB_HASH *hs, const char *key)
Definition: adhash.cxx:392
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
size_t get_position() const
Definition: arb_strbuf.h:112
AW_selection_list * get_sellist()
Definition: aw_select.hxx:196
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
NT_global GLOBAL
Definition: NT_main.cxx:46
void set_definition(int area, char *new_def)
Definition: ad_config.h:57
const char * last_group_name
Definition: NT_edconf.cxx:621
GBS_strstruct & sai_middle
Definition: NT_edconf.cxx:620
GBDATA * gb_main
Definition: awt_canvas.hxx:336
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)
Definition: adhash.cxx:253
void put(char c)
Definition: arb_strbuf.h:158
#define UNCOVERED()
Definition: arb_assert.h:380
void AWT_system_cb(AW_window *, const char *command)
Definition: AWT_misc.cxx:84
static bool allow_to_activate_display
Definition: NT_edconf.cxx:163
GB_write_int const char s
Definition: AW_awar.cxx:154