ARB
db_query.cxx
Go to the documentation of this file.
1 // ============================================================ //
2 // //
3 // File : db_query.cxx //
4 // Purpose : Database queries //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // ============================================================ //
10 
11 #include "db_query.h"
12 #include "db_query_local.h"
13 #include "query_expr.h"
14 
15 #include <dbui.h>
16 #include <item_sel_list.h>
17 #include <awt_config_manager.hxx>
18 #include <awt_sel_boxes.hxx>
19 
20 #include <aw_advice.hxx>
21 #include <aw_color_groups.hxx>
22 #include <aw_file.hxx>
23 #include <aw_msg.hxx>
24 #include <aw_awar.hxx>
25 #include <arb_progress.h>
26 #include <aw_root.hxx>
27 #include <aw_question.hxx>
28 #include <rootAsWin.h>
29 
30 #include <ad_cb.h>
31 
32 #include <arb_strbuf.h>
33 #include <arb_sort.h>
34 #include <arb_global_defs.h>
35 #include <Keeper.h>
36 
37 #include <list>
38 #include <stack>
39 
40 using namespace std;
41 using namespace QUERY;
42 
43 #define MAX_QUERY_LIST_LEN 100000
44 
45 #define AWAR_COLORIZE "tmp/dbquery_all/colorize"
46 
47 static void free_hit_description(long info) {
48  free(reinterpret_cast<char*>(info));
49 }
50 
51 inline void SET_QUERIED(GBDATA *gb_species, DbQuery *query, const char *hitInfo, size_t hitInfoLen = 0) {
52  dbq_assert(hitInfo);
53 
54  GB_raise_user_flag(gb_species, query->select_bit);
55 
56  char *name = query->selector.generate_item_id(query->gb_main, gb_species);
57  char *info;
58 
59  if (hitInfoLen == 0) hitInfoLen = strlen(hitInfo);
60  if (hitInfoLen>MAX_SHOWN_DATA_SIZE) {
61  char *dupInfo = strdup(hitInfo);
62  hitInfoLen = GBS_shorten_repeated_data(dupInfo);
63  if (hitInfoLen>MAX_SHOWN_DATA_SIZE) {
64  strcpy(dupInfo+hitInfoLen-5, "[...]");
65  }
66  info = strdup(dupInfo);
67  free(dupInfo);
68  }
69  else {
70  info = strdup(hitInfo);
71  }
72 
73  GBS_write_hash(query->hit_description, name, reinterpret_cast<long>(info)); // overwrite hit info (also deallocates)
74  free(name);
75 }
76 
77 inline void CLEAR_QUERIED(GBDATA *gb_species, DbQuery *query) {
78  GB_clear_user_flag(gb_species, query->select_bit);
79 
80  char *name = query->selector.generate_item_id(query->gb_main, gb_species);
81  GBS_write_hash(query->hit_description, name, 0); // delete hit info (also deallocates)
82  free(name);
83 }
84 
85 inline const char *getHitInfo(const char *item_id, DbQuery *query) {
86  long info = GBS_read_hash(query->hit_description, item_id);
87  return reinterpret_cast<const char*>(info);
88 }
89 inline const char *getHitInfo(GBDATA *gb_species, DbQuery *query) {
90  char *name = query->selector.generate_item_id(query->gb_main, gb_species);
91  const char *result = getHitInfo(name, query);
92  free(name);
93  return result;
94 }
95 inline string keptHitReason(const string& currentHitReason, GBDATA *gb_item, DbQuery *query) {
96  string reason = string("kept because ")+currentHitReason;
97  const char *hitinfo = getHitInfo(gb_item, query);
98  if (hitinfo) reason = string(hitinfo)+" ("+reason+')';
99  return reason;
100 }
101 
102 static void create_query_independent_awars(AW_root *aw_root, AW_default aw_def) {
103  aw_root->awar_int(AWAR_COLORIZE, 0, aw_def);
104 }
105 
107  return query->gb_main;
108 }
109 
111  return query->selector;
112 }
113 
118 };
119 
120 query_spec::query_spec(ItemSelector& selector_)
121  : selector(selector_),
122  gb_main(NULp),
123  gb_ref(NULp),
124  expect_hit_in_ref_list(false),
125  species_name(NULp),
126  tree_name(NULp),
127  select_bit(GB_USERFLAG_QUERY), // always == GB_USERFLAG_QUERY atm (nevertheless DO NOT hardcode)
128  use_menu(0),
129  ere_pos_fig(NULp),
130  where_pos_fig(NULp),
131  by_pos_fig(NULp),
132  qbox_pos_fig(NULp),
133  key_pos_fig(NULp),
134  query_pos_fig(NULp),
135  result_pos_fig(NULp),
136  count_pos_fig(NULp),
137  do_query_pos_fig(NULp),
138  config_pos_fig(NULp),
139  do_mark_pos_fig(NULp),
140  do_unmark_pos_fig(NULp),
141  do_delete_pos_fig(NULp),
142  do_set_pos_fig(NULp),
143  open_parser_pos_fig(NULp),
144  do_refresh_pos_fig(NULp),
145  popup_info_window(NULp),
146  info_box_pos_fig(NULp)
147 {
148  dbq_assert(&selector);
149 }
150 
151 bool query_spec::is_queried(GBDATA *gb_item) const {
152  return GB_user_flag(gb_item, select_bit);
153 }
154 
155 bool QUERY::IS_QUERIED(GBDATA *gb_item, const DbQuery *query) {
156  return query->is_queried(gb_item);
157 }
158 
160  GBDATA *gb_main = query->gb_main;
161  ItemSelector& selector = query->selector;
162 
163  long count = 0;
164 
165  for (GBDATA *gb_item_container = selector.get_first_item_container(gb_main, query->aws->get_root(), range);
166  gb_item_container;
167  gb_item_container = selector.get_next_item_container(gb_item_container, range))
168  {
169  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
170  gb_item;
171  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
172  {
173  if (IS_QUERIED(gb_item, query)) count++;
174  }
175  }
176  return count;
177 }
178 
179 #if defined(WARN_TODO)
180 #warning replace query_count_items by "method" of selector
181 #endif
182 
183 static int query_count_items(DbQuery *query, QUERY_RANGE range, QUERY_MODES mode) {
184  int count = 0;
185  GBDATA *gb_main = query->gb_main;
186  ItemSelector& selector = query->selector;
187  GB_transaction ta(gb_main);
188 
189  for (GBDATA *gb_item_container = selector.get_first_item_container(gb_main, query->aws->get_root(), range);
190  gb_item_container;
191  gb_item_container = selector.get_next_item_container(gb_item_container, range))
192  {
193  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
194  gb_item;
195  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
196  {
197  switch (mode) {
198  case QUERY_GENERATE: ++count; break;
199  case QUERY_ENLARGE: count += !IS_QUERIED(gb_item, query); break;
200  case QUERY_REDUCE: count += IS_QUERIED(gb_item, query); break;
201  }
202  }
203  }
204  return count;
205 }
206 
207 const int MAX_CRITERIA = int(sizeof(unsigned long)*8/QUERY_SORT_CRITERIA_BITS);
208 
209 static void split_sort_mask(unsigned long sort_mask, QUERY_RESULT_ORDER *order) {
210  // splits the sort order bit mask 'sort_mask' into single sort criteria and write these into 'order'
211  // (order[0] will contain the primary sort criteria, order[1] the secondary, ...)
212 
213  for (int o = 0; o<MAX_CRITERIA; ++o) {
214  order[o] = QUERY_RESULT_ORDER(sort_mask&QUERY_SORT_CRITERIA_MASK);
215  dbq_assert(order[o] == (order[o]&QUERY_SORT_CRITERIA_MASK));
216  sort_mask = sort_mask>>QUERY_SORT_CRITERIA_BITS;
217  }
218 }
219 
221  // Returns the first criteria in 'order' (which has to have MAX_CRITERIA elements)
222  // that matches
223  // - QUERY_SORT_BY_1STFIELD_CONTENT or
224  // - QUERY_SORT_NUM_BY_1STFIELD_CONTENT or
225  // - QUERY_SORT_BY_HIT_DESCRIPTION
226  // (or QUERY_SORT_NONE if none of the above is used)
227 
229  for (int o = 0; o<MAX_CRITERIA && first == QUERY_SORT_NONE; ++o) {
231  first = order[o];
232  }
233  }
234  return first;
235 }
236 
238  // removes all sort-criteria from order which would use the order of the currently selected primary key
239 
240  int n = 0;
241  for (int o = 0; o<MAX_CRITERIA; ++o) {
243  order[n++] = order[o];
244  }
245  }
246  for (; n<MAX_CRITERIA; ++n) {
247  order[n] = QUERY_SORT_NONE;
248  }
249 }
250 
253  split_sort_mask(query->sort_mask, order);
254 
256  if (usedOrder != QUERY_SORT_BY_HIT_DESCRIPTION && usedOrder != QUERY_SORT_NONE) { // do we display values?
257  DbQuery_update_list(query);
258  }
259 }
260 
261 inline bool keep_criteria(QUERY_RESULT_ORDER old_criteria, QUERY_RESULT_ORDER new_criteria) {
262  return
263  old_criteria != QUERY_SORT_NONE && // do not keep 'unsorted' (it is no real criteria)
264  (old_criteria != new_criteria || // do not keep new criteria (added later)
265  old_criteria == QUERY_SORT_REVERSE); // reverse may occur several times -> always keep
266 }
267 
268 static void result_sort_order_changed_cb(AW_root *aw_root, DbQuery *query) {
269  // adds the new selected sort order to the sort order mask
270  // (added order removes itself, if it previously existed in sort order mask)
271  //
272  // if 'unsorted' is selected -> delete sort order
273 
274  QUERY_RESULT_ORDER new_criteria = (QUERY_RESULT_ORDER)aw_root->awar(query->awar_sort)->read_int();
275  if (new_criteria == QUERY_SORT_NONE) {
276  query->sort_mask = QUERY_SORT_NONE; // clear sort_mask
277  }
278  else {
280  split_sort_mask(query->sort_mask, order);
281 
282  int empty_or_same = 0;
283  for (int o = 0; o<MAX_CRITERIA; o++) {
284  if (!keep_criteria(order[o], new_criteria)) {
285  empty_or_same++; // these criteria will be skipped below
286  }
287  }
288 
289  unsigned long new_sort_mask = 0;
290  for (int o = MAX_CRITERIA-(empty_or_same>0 ? 1 : 2); o >= 0; o--) {
291  if (keep_criteria(order[o], new_criteria)) {
292  new_sort_mask = (new_sort_mask<<QUERY_SORT_CRITERIA_BITS)|order[o];
293  }
294  }
295  query->sort_mask = (new_sort_mask<<QUERY_SORT_CRITERIA_BITS)|new_criteria; // add new primary key
296  }
297  DbQuery_update_list(query);
298 }
299 
300 struct hits_sort_params : virtual Noncopyable {
302  char *first_key;
305 
306  hits_sort_params(DbQuery *q, const char *fk)
307  : query(q),
308  first_key(strdup(fk))
309  {
310  first_type = GBT_get_type_of_changekey(query->gb_main, first_key, query->selector.change_key_path);
311  }
312 
314  free(first_key);
315  }
316 };
317 
318 inline int numeric_string_cmp(const char *str1, const char *str2) {
319  const char *end1;
320  const char *end2;
321 
322  double double1 = strtod(str1, const_cast<char**>(&end1));
323  double double2 = strtod(str2, const_cast<char**>(&end2));
324 
325  bool conv1 = !end1[0] && str1[0];
326  bool conv2 = !end2[0] && str2[0];
327 
328  bool both_converted = conv1 && conv2;
329 
330  int cmp;
331  if (both_converted) {
332  cmp = double_cmp(double1, double2);
333  }
334  else {
335  bool conv_partial1 = end1>str1;
336  bool conv_partial2 = end2>str2;
337 
338  if (conv_partial1 && conv_partial2) {
339  cmp = double_cmp(double1, double2);
340  if (!cmp) {
341  cmp = numeric_string_cmp(end1, end2);
342  }
343  }
344  else cmp = strcmp(str1, str2);
345  }
346  return cmp;
347 }
348 
349 static int compare_hits(const void *cl_item1, const void *cl_item2, void *cl_param) {
350  const hits_sort_params *param = static_cast<const hits_sort_params*>(cl_param);
351 
352  GBDATA *gb_item1 = (GBDATA*)cl_item1;
353  GBDATA *gb_item2 = (GBDATA*)cl_item2;
354 
355  DbQuery *query = param->query;
356  ItemSelector& selector = query->selector;
357 
358  int cmp = 0;
359 
360  for (int o = 0; o<MAX_CRITERIA && cmp == 0; o++) {
361  QUERY_RESULT_ORDER criteria = param->order[o];
362 
363  switch (criteria) {
364  case QUERY_SORT_NONE:
365  o = MAX_CRITERIA; // don't sort further
366  break;
367 
369  char *field1 = GBT_read_as_string(gb_item1, param->first_key);
370  char *field2 = GBT_read_as_string(gb_item2, param->first_key);
371 
372  cmp = ARB_strNULLcmp(field1, field2);
373 
374  free(field2);
375  free(field1);
376  break;
377  }
379  switch (param->first_type) {
380  case GB_INT: {
381  long *have1 = GBT_read_int(gb_item1, param->first_key);
382  long L1 = have1 ? *have1 : 0;
383  long *have2 = GBT_read_int(gb_item2, param->first_key);
384  long L2 = have2 ? *have2 : 0;
385 
386  cmp = have1 // use same logic as ARB_strNULLcmp
387  ? (have2 ? long_cmp(L1,L2) : -1)
388  : (have2 ? 1 : 0);
389  break;
390  }
391  case GB_FLOAT: {
392  float *have1 = GBT_read_float(gb_item1, param->first_key);
393  float f1 = have1 ? *have1 : 0;
394  float *have2 = GBT_read_float(gb_item2, param->first_key);
395  float f2 = have2 ? *have2 : 0;
396 
397  cmp = have1
398  ? (have2 ? float_cmp(f1,f2) : -1)
399  : (have2 ? 1 : 0);
400  break;
401  }
402  default: {
403  char *field1 = GBT_read_as_string(gb_item1, param->first_key);
404  char *field2 = GBT_read_as_string(gb_item2, param->first_key);
405 
406  cmp = (field1 && field2)
407  ? numeric_string_cmp(field1, field2)
408  : ARB_strNULLcmp(field1, field2);
409 
410  free(field2);
411  free(field1);
412  }
413  }
414  break;
415  }
417  if (selector.parent_selector) {
418  GBDATA *gb_parent1 = selector.get_parent(gb_item1);
419  GBDATA *gb_parent2 = selector.get_parent(gb_item2);
420 
421  char *pid1 = selector.generate_item_id(query->gb_main, gb_parent1);
422  char *pid2 = selector.generate_item_id(query->gb_main, gb_parent2);
423 
424  cmp = ARB_strNULLcmp(pid1, pid2);
425 
426  free(pid2);
427  free(pid1);
428  }
429  break;
430  }
431  case QUERY_SORT_BY_ID: {
432  const char *id1 = GBT_read_char_pntr(gb_item1, selector.id_field);
433  const char *id2 = GBT_read_char_pntr(gb_item2, selector.id_field);
434 
435  cmp = strcmp(id1, id2);
436  break;
437  }
439  cmp = GB_read_flag(gb_item2)-GB_read_flag(gb_item1);
440  break;
441 
443  const char *id1 = GBT_read_char_pntr(gb_item1, selector.id_field);
444  const char *id2 = GBT_read_char_pntr(gb_item2, selector.id_field);
445  const char *info1 = reinterpret_cast<const char *>(GBS_read_hash(query->hit_description, id1));
446  const char *info2 = reinterpret_cast<const char *>(GBS_read_hash(query->hit_description, id2));
447  cmp = ARB_strNULLcmp(info1, info2);
448  break;
449  }
450  case QUERY_SORT_REVERSE: {
451  GBDATA *tmp = gb_item1; // swap items for following compares (this is a prefix revert!)
452  gb_item1 = gb_item2;
453  gb_item2 = tmp;
454  break;
455  }
456  }
457  }
458 
459  return cmp;
460 }
461 
462 static void detectMaxNameLength(const char *key, long /*val*/, void *cl_len) {
463  int *len = (int*)cl_len;
464  int klen = strlen(key);
465 
466  if (klen>*len) *len = klen;
467 }
468 
469 #if defined(ASSERTION_USED)
470 inline bool SLOW_is_pseudo_key(const char *key) {
471  return
472  strcmp(key, PSEUDO_FIELD_ANY_FIELD) == 0 ||
473  strcmp(key, PSEUDO_FIELD_ALL_FIELDS) == 0 ||
474  strcmp(key, PSEUDO_FIELD_ANY_FIELD_REC) == 0 ||
475  strcmp(key, PSEUDO_FIELD_ALL_FIELDS_REC) == 0;
476 }
477 #endif
478 inline bool is_pseudo_key(const char *key) {
479  // returns true, if 'key' is a pseudo-key
480  bool is_pseudo = key[0] == '[';
481  dbq_assert(is_pseudo == SLOW_is_pseudo_key(key));
482  return is_pseudo;
483 }
484 
487 
488  dbq_assert(query->hitlist);
489  query->hitlist->clear();
490 
491  AW_window *aww = query->aws;
492  AW_root *aw_root = aww->get_root();
493  QUERY_RANGE range = (QUERY_RANGE)aw_root->awar(query->awar_where)->read_int();
494  ItemSelector& selector = query->selector;
495 
496  // create array of hits
497  long count = count_queried_items(query, range);
498  GBDATA **sorted = ARB_alloc<GBDATA*>(count);
499  {
500  long s = 0;
501 
502  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
503  gb_item_container;
504  gb_item_container = selector.get_next_item_container(gb_item_container, range))
505  {
506  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
507  gb_item;
508  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
509  {
510  if (IS_QUERIED(gb_item, query)) sorted[s++] = gb_item;
511  }
512  }
513  }
514 
515  // sort hits
516 
517  hits_sort_params param(query, aww->get_root()->awar(query->awar_keys[0])->read_char_pntr());
518 
519  bool is_pseudo = is_pseudo_key(param.first_key);
520  bool show_value = !is_pseudo; // cannot refer to key-value of pseudo key
521 
522  if (query->sort_mask != QUERY_SORT_NONE) { // unsorted -> don't sort
523  split_sort_mask(query->sort_mask, param.order);
524  if (is_pseudo) {
526  }
527  if (show_value && find_display_determining_sort_order(param.order) == QUERY_SORT_BY_HIT_DESCRIPTION) {
528  show_value = false;
529  }
530  GB_sort((void**)sorted, 0, count, compare_hits, &param);
531  }
532 
533  // display hits
534 
535  int name_len = selector.item_name_length;
536  if (name_len == -1) { // if name_len is unknown -> detect
538  }
539 
540  long i;
541  for (i = 0; i<count && i<MAX_QUERY_LIST_LEN; i++) {
542  char *name = selector.generate_item_id(query->gb_main, sorted[i]);
543  if (name) {
544  char *toFree = NULp;
545  const char *info;
546 
547  if (show_value) {
548  toFree = GBT_read_as_string(sorted[i], param.first_key);
549  if (toFree) {
550  if (strlen(toFree)>MAX_SHOWN_DATA_SIZE) {
551  size_t shortened_len = GBS_shorten_repeated_data(toFree);
552  if (shortened_len>MAX_SHOWN_DATA_SIZE) {
553  strcpy(toFree+MAX_SHOWN_DATA_SIZE-5, "[...]");
554  }
555  }
556  }
557  else {
558  toFree = GBS_global_string_copy("<%s has no data>", param.first_key);
559  }
560  info = toFree;
561  }
562  else {
563  info = getHitInfo(name, query);
564  if (!info) info = "<no hit info>";
565  }
566 
567  dbq_assert(info);
568  const char *line = GBS_global_string("%c %-*s :%s",
569  GB_read_flag(sorted[i]) ? '*' : ' ',
570  name_len, name,
571  info);
572 
573  query->hitlist->insert(line, name);
574  free(toFree);
575  free(name);
576  }
577  }
578 
579  if (count>MAX_QUERY_LIST_LEN) {
580  query->hitlist->insert("***** List truncated *****", "");
581  }
582 
583  free(sorted);
584 
585  query->hitlist->insert_default("End of list", "");
586  query->hitlist->update();
587  aww->get_root()->awar(query->awar_count)->write_int((long)count);
588  GB_pop_transaction(query->gb_main);
589 }
590 
591 static void mark_queried_cb(AW_window*, DbQuery *query, int mark) {
592  // Mark listed species
593  // mark = 1 -> mark listed
594  // mark | 8 -> don't change rest
595 
596  ItemSelector& selector = query->selector;
598 
599  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, query->aws->get_root(), QUERY_ALL_ITEMS);
600  gb_item_container;
601  gb_item_container = selector.get_next_item_container(gb_item_container, QUERY_ALL_ITEMS))
602  {
603  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
604  gb_item;
605  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
606  {
607  if (IS_QUERIED(gb_item, query)) {
608  GB_write_flag(gb_item, mark&1);
609  }
610  else if ((mark&8) == 0) {
611  GB_write_flag(gb_item, 1-(mark&1));
612  }
613  }
614  }
615 
616  DbQuery_update_list(query);
617  GB_pop_transaction(query->gb_main);
618 }
619 
620 void QUERY::unquery_all(void *, DbQuery *query) {
622  GBDATA *gb_species;
623  for (gb_species = GBT_first_species(query->gb_main);
624  gb_species;
625  gb_species = GBT_next_species(gb_species)) {
626  CLEAR_QUERIED(gb_species, query);
627  }
628  DbQuery_update_list(query);
629  GB_pop_transaction(query->gb_main);
630 }
631 
633  ItemSelector& selector = query->selector;
635 
636  long cnt = 0;
637  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, query->aws->get_root(), QUERY_ALL_ITEMS);
638  gb_item_container;
639  gb_item_container = selector.get_next_item_container(gb_item_container, QUERY_ALL_ITEMS))
640  {
641  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
642  gb_item;
643  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
644  {
645  if (IS_QUERIED(gb_item, query)) cnt++;
646  }
647  }
648 
649  if (!cnt || !aw_ask_sure("delete_queried_species", GBS_global_string("Are you sure to delete %li %s", cnt, selector.items_name))) {
651  return;
652  }
653 
654  GB_ERROR error = NULp;
655 
656  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, query->aws->get_root(), QUERY_ALL_ITEMS);
657  !error && gb_item_container;
658  gb_item_container = selector.get_next_item_container(gb_item_container, QUERY_ALL_ITEMS))
659  {
660  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
661  !error && gb_item;
662  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
663  {
664  if (IS_QUERIED(gb_item, query)) {
665  error = GB_delete(gb_item);
666  }
667  }
668  }
669 
670  if (error) {
672  aw_message(error);
673  }
674  else {
675  DbQuery_update_list(query);
677  }
678 }
679 
680 static GB_HASH *create_ref_hash(const DbQuery *query, const char *key, bool split_words) {
681  GBDATA *gb_ref = query->gb_ref;
682  bool queried_only = query->expect_hit_in_ref_list;
684 
685  for (GBDATA *gb_species = GBT_first_species(gb_ref);
686  gb_species;
687  gb_species = GBT_next_species(gb_species))
688  {
689  if (!queried_only || IS_QUERIED(gb_species, query)) {
690  GBDATA *gb_name = GB_search(gb_species, key, GB_FIND);
691  if (gb_name) {
692  char *keyas = GB_read_as_string(gb_name);
693  if (keyas && strlen(keyas)) {
694  if (split_words) {
695  char *t;
696  for (t = strtok(keyas, " "); t; t = strtok(NULp, " ")) {
697  if (t[0]) GBS_write_hash(hash, t, (long)gb_species);
698  }
699  }
700  else {
701  GBS_write_hash(hash, keyas, (long)gb_species);
702  }
703  }
704  free(keyas);
705  }
706  }
707  }
708  return hash;
709 }
710 
711 class TargetItem : public QueryTarget {
712  RefPtr<GBDATA> gb_item;
713 public:
714  TargetItem(const DbQuery& query) :
715  QueryTarget(query.gb_main, query.get_tree_name()),
716  gb_item(NULp)
717  {}
718 
719  void aimTo(GBDATA *gb_next_item) {
720  dbq_assert(gb_next_item); // @@@ maybe allow? (to invalidate target)
721  gb_item = gb_next_item;
722  }
723  GBDATA *get_item() const {
724  dbq_assert(gb_item); // you have to call aimTo before!
725  return gb_item;
726  }
727 
728  // QueryTarget interface:
729  GBDATA *get_ACI_item() const OVERRIDE { return get_item(); }
730 };
731 
732 class ItemQueryKey FINAL_TYPE : public QueryKey, virtual Noncopyable {
733  char *key; // search key (=name of DB field or pseudo-field)
734  bool hierarchical; // is 'key' hierarchical?
735  GBQUARK keyquark; // valid only if get_type() == QKEY_EXPLICIT!
736 
737  typedef std::stack<GBDATA*> ParentStack;
738 
739  mutable GBDATA *gb_key; // last read key-entry
740  mutable ParentStack parent; // container(s) descended
741 
742  static query_key_type detect_key_type(const char *field_name) {
743  if (is_pseudo_key(field_name)) {
744  if (strcmp(field_name, PSEUDO_FIELD_ANY_FIELD) == 0) return QKEY_ANY;
745  if (strcmp(field_name, PSEUDO_FIELD_ANY_FIELD_REC) == 0) return QKEY_ANY_REC;
746  if (strcmp(field_name, PSEUDO_FIELD_ALL_FIELDS) == 0) return QKEY_ALL;
747  if (strcmp(field_name, PSEUDO_FIELD_ALL_FIELDS_REC) == 0) return QKEY_ALL_REC;
748  dbq_assert(0);
749  }
750  return QKEY_EXPLICIT;
751  }
752 
753 public:
754  ItemQueryKey(GBDATA *gb_main, const char *field_name) :
755  QueryKey(detect_key_type(field_name)),
756  key(strdup(field_name)),
757  hierarchical(false),
758  keyquark(0), // invalid quark
759  gb_key(NULp)
760  {
761  if (get_type() == QKEY_EXPLICIT) {
762  if (GB_first_non_key_char(key)) {
763  hierarchical = true;
764  }
765  else {
766  keyquark = GB_find_or_create_quark(gb_main, key);
767  }
768  }
769  }
771  free(key);
772  }
773 
774  // QueryKey interface:
775  char *get_target_data(const QueryTarget& target, GB_ERROR& error) const OVERRIDE {
776  // retrieve content of target key
777  if (!gb_key) {
778  const TargetItem& target_item = DOWNCAST_REFERENCE(const TargetItem, target);
779  gb_key = get_first_field(target_item.get_item());
780  }
781 
782  char *data;
783  if (gb_key) {
784  data = GB_read_as_string(gb_key);
785  if (!data) {
786  if (GB_readable_as_string(gb_key)) {
787  error = GB_await_error();
788  }
789  else {
791  error = GBS_global_string("field '%s' has wrong type", GB_read_key_pntr(gb_key));
792  }
793  }
794  }
795  else {
796  data = strdup(""); // non-existing field -> assume "" as default value
797  // (needed to search for missing fields using '!=*' ?)
798  }
799  return data;
800  }
801  const char *get_name() const OVERRIDE {
802  // name of target (e.g. for reports)
803  // - for explicit keys, it simply returns the specified key name
804  // - for iterating keys, it returns the name of the DB field at current iteration position,
805  // showing path to key relative to item (e.g. 'ali_16s/data')
806  // If not yet iterating, it returns the name of the pseudo-field.
807 
808  if (get_type() != QKEY_EXPLICIT && gb_key) {
809  const char *keyname = GB_read_key_pntr(gb_key);
810  if (!parent.empty()) {
811  const char *parent_path = GB_get_db_path(parent.top());
812  dbq_assert(parent.top() == GB_get_father(gb_key));
813  const char *rslash = strrchr(parent_path, '/');
814  for (int nest = parent.size()-1; rslash && nest; --nest) {
815  rslash = strrchr(rslash-1, '/');
816  }
817  return GBS_global_string("%s/%s", rslash ? rslash+1 : "<unknown>", keyname);
818  }
819  return keyname;
820  }
821  return key;
822  }
823 
824 private:
825  bool accept_or_iterate() const {
827  if (gb_key) {
828  GB_TYPES ktype = GB_read_type(gb_key);
829  if (ktype == GB_DB) {
830  switch (get_type()) {
831  case QKEY_ALL:
832  case QKEY_ANY:
833  return iterate(); // = skip over containers
834 
835  case QKEY_ALL_REC:
836  case QKEY_ANY_REC:
837  parent.push(gb_key); // remember position ..
838  gb_key = GB_child(gb_key); // .. and descend into container
839  break;
840 
841  case QKEY_EXPLICIT:
842  dbq_assert(0);
843  }
844  return accept_or_iterate();
845  }
846  if (!GB_TYPE_readable_as_string(ktype)) {
847  return iterate();
848  }
849  return true;
850  }
851  if (!parent.empty()) {
852  gb_key = parent.top();
853  parent.pop();
854  return iterate();
855  }
856  return false;
857  }
858 public:
859 
860  bool iterate() const OVERRIDE { // iterate key to next item
862  if (gb_key) gb_key = GB_nextChild(gb_key);
863  return accept_or_iterate();
864  }
865  void reset() const OVERRIDE {
866  // restart multi-key iteration
867  gb_key = NULp;
868  parent = ParentStack();
869  }
870  // ----------
871 
872 
873  GBDATA *get_first_field(GBDATA *gb_item) const {
874  GBDATA *gb_field = NULp;
875 
876  if (hierarchical) {
877  gb_field = GB_search(gb_item, key, GB_FIND);
878  }
879  else if (get_type() != QKEY_EXPLICIT) {
880  gb_field = GB_child(gb_item);
881  // no need to use same method as normal search (we just need any key here)
882  while (gb_field && GB_read_type(gb_field) == GB_DB) {
883  gb_field = GB_nextChild(gb_field);
884  }
885  }
886  else {
887  gb_field = GB_find_sub_by_quark(gb_item, keyquark, NULp, 0);
888  }
889 
890  return gb_field;
891  }
892 };
893 
894 inline query_operator awarvalue2query_operator(const char *awarvalue) {
895  if (strcmp(awarvalue, "and") == 0) return AND;
896  if (strcmp(awarvalue, "or") == 0) return OR;
897  return ILLEGAL;
898 }
899 
901  AW_root *aw_root = aws->get_root();
902  QueryExpr *first_qe = NULp;
903 
904  for (int idx = 0; idx<QUERY_EXPRESSIONS; ++idx) {
905  query_operator aqo = idx
907  : OR; // initial value is false, (false OR QUERY1) == QUERY1
908 
909  if (aqo != ILLEGAL) {
910  bool not_equal = aw_root->awar(awar_not[idx])->read_int() != 0;
911  const char *expression = aw_root->awar(awar_queries[idx])->read_char_pntr();
912  const char *field_name = aw_root->awar(awar_keys[idx])->read_char_pntr();
913  QueryKeyPtr qkey = new ItemQueryKey(gb_main, field_name);
914 
915  QueryExpr *qe = new QueryExpr(aqo, qkey, not_equal, expression);
916 
917  if (!field_name[0] || strcmp(field_name, NO_FIELD_SELECTED) == 0) {
918  qe->setError("No field selected");
919  }
920 
921  if (!first_qe) first_qe = qe;
922  else first_qe->append(qe);
923  }
924  }
925 
926  return first_qe;
927 }
928 
929 static void perform_query_cb(AW_window*, DbQuery *query, EXT_QUERY_TYPES ext_query) {
930  ItemSelector& selector = query->selector;
931 
933 
934  AW_root *aw_root = query->aws->get_root();
935  SmartPtr<QueryExpr> qexpr = query->buildQueryExpr();
936 
937  QUERY_MODES mode = (QUERY_MODES)aw_root->awar(query->awar_ere)->read_int();
938  QUERY_RANGE range = (QUERY_RANGE)aw_root->awar(query->awar_where)->read_int();
939  QUERY_TYPES type = (QUERY_TYPES)aw_root->awar(query->awar_by)->read_int();
940 
941  if (query->gb_ref && type != QUERY_MARKED) { // special for merge tool!
942  char *first_query = aw_root->awar(query->awar_queries[0])->read_string();
943  if (strlen(first_query) == 0) {
944  if (!ext_query) ext_query = EXT_QUERY_COMPARE_LINES;
945  }
946  free(first_query);
947  }
948 
949  GB_ERROR error = qexpr->getError();
950 
951  if (!error) {
952  size_t item_count = query_count_items(query, range, mode);
953  if (item_count) {
954  arb_progress progress("Searching", item_count);
955 
956  if (query->gb_ref && // merge tool only
957  (ext_query == EXT_QUERY_COMPARE_LINES || ext_query == EXT_QUERY_COMPARE_WORDS))
958  {
959  if (qexpr->get_key_type() != QKEY_EXPLICIT) {
960  error = "Please select an explicit field or specify a search string (for first expression)";
961  }
962  else {
963  GB_push_transaction(query->gb_ref);
964 
965  char *first_keyname = aw_root->awar(query->awar_keys[0])->read_string();
966  GB_HASH *ref_hash = create_ref_hash(query, first_keyname, ext_query == EXT_QUERY_COMPARE_WORDS);
967 
968  if (GBS_hash_elements(ref_hash) == 0) {
969  error = GBS_global_string("No data found in field '%s'", first_keyname);
970  }
971 
972 #if defined(DEBUG)
973  printf("query: search identical %s in field %s%s\n",
974  (ext_query == EXT_QUERY_COMPARE_WORDS ? "words" : "values"),
975  first_keyname,
976  query->expect_hit_in_ref_list ? " of species listed in other hitlist" : "");
977 #endif // DEBUG
978 
979  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
980  gb_item_container && !error;
981  gb_item_container = selector.get_next_item_container(gb_item_container, range))
982  {
983  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
984  gb_item && !error;
985  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
986  {
987  switch (mode) {
988  case QUERY_GENERATE: CLEAR_QUERIED(gb_item, query); break;
989  case QUERY_ENLARGE: if (IS_QUERIED(gb_item, query)) continue; break;
990  case QUERY_REDUCE: if (!IS_QUERIED(gb_item, query)) continue; break;
991  }
992 
993  // Note: here only the first query is used (special case in merge tool only)
994 
995  ItemQueryKey& query_key = DOWNCAST_REFERENCE(ItemQueryKey, qexpr->get_key());
996  GBDATA *gb_key = query_key.get_first_field(gb_item);
997  if (gb_key) {
998  char *data = GB_read_as_string(gb_key);
999 
1000  if (data && data[0]) {
1001  string hit_reason;
1002  bool this_hit = false;
1003 
1004  if (ext_query == EXT_QUERY_COMPARE_WORDS) {
1005  for (char *t = strtok(data, " "); t; t = strtok(NULp, " ")) {
1006  GBDATA *gb_ref_pntr = (GBDATA *)GBS_read_hash(ref_hash, t);
1007  if (gb_ref_pntr) { // found item in other DB, with 'first_keyname' containing word from 'gb_key'
1008  this_hit = true;
1009  hit_reason = GBS_global_string("%s%s has word '%s' in %s",
1010  query->expect_hit_in_ref_list ? "Hit " : "",
1011  selector.generate_item_id(query->gb_ref, gb_ref_pntr),
1012  t, first_keyname);
1013  }
1014  }
1015  }
1016  else {
1017  GBDATA *gb_ref_pntr = (GBDATA *)GBS_read_hash(ref_hash, data);
1018  if (gb_ref_pntr) { // found item in other DB, with identical 'first_keyname'
1019  this_hit = true;
1020  hit_reason = GBS_global_string("%s%s matches %s",
1021  query->expect_hit_in_ref_list ? "Hit " : "",
1022  selector.generate_item_id(query->gb_ref, gb_ref_pntr),
1023  first_keyname);
1024  }
1025  }
1026 
1027  if (type == QUERY_DONT_MATCH) {
1028  this_hit = !this_hit;
1029  if (this_hit) hit_reason = "<no matching entry>";
1030  }
1031 
1032  if (this_hit) {
1033  dbq_assert(!hit_reason.empty());
1034  SET_QUERIED(gb_item, query, hit_reason.c_str(), hit_reason.length());
1035  }
1036  else CLEAR_QUERIED(gb_item, query);
1037  }
1038  free(data);
1039  }
1040 
1041  progress.inc_and_check_user_abort(error);
1042  }
1043  }
1044 
1045  GBS_free_hash(ref_hash);
1046  GB_pop_transaction(query->gb_ref);
1047  }
1048  }
1049  else { // "normal" query
1050  if (type == QUERY_DONT_MATCH) {
1051 #if defined(DEBUG)
1052  fputs("query: !(", stdout); qexpr->dump();
1053 #endif // DEBUG
1054 
1055  qexpr->negate();
1056  type = QUERY_MATCH;
1057 
1058 #if defined(DEBUG)
1059  fputs(") => query: ", stdout); qexpr->dump(); fputc('\n', stdout);
1060 #endif // DEBUG
1061  }
1062 #if defined(DEBUG)
1063  else { fputs("query: ", stdout); qexpr->dump(); fputc('\n', stdout); }
1064 #endif // DEBUG
1065 
1066  TargetItem target_item(*query);
1067 
1068  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
1069  gb_item_container && !error;
1070  gb_item_container = selector.get_next_item_container(gb_item_container, range))
1071  {
1072  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1073  gb_item && !error;
1074  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
1075  {
1076  switch (mode) {
1077  case QUERY_GENERATE: CLEAR_QUERIED(gb_item, query); break;
1078  case QUERY_ENLARGE: if (IS_QUERIED(gb_item, query)) continue; break;
1079  case QUERY_REDUCE: if (!IS_QUERIED(gb_item, query)) continue; break;
1080  }
1081 
1082  bool hit = false;
1083  string hit_reason;
1084 
1085  switch (type) {
1086  case QUERY_MARKED:
1087  hit = GB_read_flag(gb_item);
1088  hit_reason = "<marked>";
1089  break;
1090 
1091  case QUERY_MATCH:
1092  dbq_assert(ext_query == EXT_QUERY_NONE);
1093  target_item.aimTo(gb_item);
1094  hit = qexpr->matches(target_item, hit_reason);
1095  break;
1096 
1097  default: dbq_assert(0); break;
1098  }
1099 
1100  if (hit) {
1101  dbq_assert(!hit_reason.empty());
1102 
1103  if (mode == QUERY_REDUCE) hit_reason = keptHitReason(hit_reason, gb_item, query);
1104  SET_QUERIED(gb_item, query, hit_reason.c_str(), hit_reason.length());
1105  }
1106  else CLEAR_QUERIED(gb_item, query);
1107 
1108  if (error) {
1109  error = GB_failedTo_error("query", GBT_get_name_or_description(gb_item), error);
1110  }
1111  else {
1112  progress.inc_and_check_user_abort(error);
1113  }
1114  }
1115  }
1116  }
1117 
1118  if (error) progress.done();
1119  }
1120  }
1121 
1122  if (!error) error = qexpr->getError(); // check for query error
1123 
1124  if (error) aw_message(error);
1125  else DbQuery_update_list(query);
1126 
1127  GB_pop_transaction(query->gb_main);
1128 }
1129 
1130 void QUERY::copy_selection_list_2_query_box(DbQuery *query, AW_selection_list *srclist, const char *hit_description) {
1131  GB_transaction ta(query->gb_main);
1132 
1133  dbq_assert(strstr(hit_description, "%s")); // hit_description needs '%s' (which is replaced by visible content of 'id')
1134 
1135  GB_ERROR error = NULp;
1136  AW_window *aww = query->aws;
1137  AW_root *aw_root = aww->get_root();
1138  GB_HASH *list_hash = srclist->to_hash(false);
1139  QUERY_MODES mode = (QUERY_MODES)aw_root->awar(query->awar_ere)->read_int();
1140  QUERY_TYPES type = (QUERY_TYPES)aw_root->awar(query->awar_by)->read_int();
1141 
1142  if (type == QUERY_MARKED) {
1143  error = "Query mode 'that are marked' does not apply here.\nEither select 'that match the query' or 'that don't match the q.'";
1144  }
1145 
1146  if (type != QUERY_MATCH || mode != QUERY_GENERATE) { // different behavior as in the past -> advice
1147  AW_advice("'Move to hitlist' now depends on the values selected for\n"
1148  " * 'Search/Add/Keep species' and\n"
1149  " * 'that match/don't match the query'\n"
1150  "in the search tool.",
1152  "Behavior changed",
1153  "next_neighbours.hlp");
1154  }
1155 
1156  long inHitlist = GBS_hash_elements(list_hash);
1157  long seenInDB = 0;
1158 
1159  for (GBDATA *gb_species = GBT_first_species(query->gb_main);
1160  gb_species && !error;
1161  gb_species = GBT_next_species(gb_species))
1162  {
1163  switch (mode) {
1164  case QUERY_GENERATE: CLEAR_QUERIED(gb_species, query); break;
1165  case QUERY_ENLARGE: if (IS_QUERIED(gb_species, query)) continue; break;
1166  case QUERY_REDUCE: if (!IS_QUERIED(gb_species, query)) continue; break;
1167  }
1168 
1169  const char *displayed = reinterpret_cast<const char*>(GBS_read_hash(list_hash, GBT_get_name_or_description(gb_species)));
1170 
1171  if (displayed) seenInDB++;
1172 
1173  if (contradicted(displayed, type == QUERY_DONT_MATCH)) {
1174  string hit_reason = GBS_global_string(hit_description, displayed ? displayed : "<no near neighbour>");
1175 
1176  if (mode == QUERY_REDUCE) hit_reason = keptHitReason(hit_reason, gb_species, query);
1177  SET_QUERIED(gb_species, query, hit_reason.c_str(), hit_reason.length());
1178  }
1179  else {
1180  CLEAR_QUERIED(gb_species, query);
1181  }
1182  }
1183 
1184  if (seenInDB < inHitlist) {
1185  aw_message(GBS_global_string("%li of %li hits were found in database", seenInDB, inHitlist));
1186  }
1187 
1188  GBS_free_hash(list_hash);
1189  if (error) aw_message(error);
1190  DbQuery_update_list(query);
1191 }
1192 
1193 
1195  AW_root *aw_root = query->aws->get_root();
1196  char *key = aw_root->awar(query->awar_keys[0])->read_string();
1197  GB_ERROR error = NULp;
1198 
1199  if (strlen(key) == 0) {
1200  error = "Please select a key (in the first query expression)";
1201  }
1202  else if (is_pseudo_key(key)) {
1203  error = "You have to select an explicit key (in the first query expression)";
1204  }
1205  else {
1206  GB_transaction dumy(query->gb_main);
1207  ItemSelector& selector = query->selector;
1208 
1210  long hashsize;
1211  QUERY_RANGE range = QUERY_ALL_ITEMS;
1212  QUERY_TYPES type = (QUERY_TYPES)aw_root->awar(query->awar_by)->read_int();
1213 
1214  switch (selector.type) {
1215  case QUERY_ITEM_SPECIES:
1216  case QUERY_ITEM_ORGANISM: {
1217  hashsize = GB_number_of_subentries(gb_species_data);
1218  break;
1219  }
1221  case QUERY_ITEM_GENES: {
1222  // handle species sub-items
1223  hashsize = 0;
1224 
1225  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
1226  gb_item_container;
1227  gb_item_container = selector.get_next_item_container(gb_item_container, range))
1228  {
1229  hashsize += GB_number_of_subentries(gb_item_container);
1230  }
1231 
1232  break;
1233  }
1234  default: {
1235  dbq_assert(0);
1236  hashsize = 0;
1237  break;
1238  }
1239  }
1240 
1241  if (!hashsize) {
1242  error = "No items exist";
1243  }
1244  else if (type == QUERY_MARKED) {
1245  error = "'that are marked' is not applicable here";
1246  }
1247 
1248  if (!error) {
1250 
1251  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
1252  gb_item_container;
1253  gb_item_container = selector.get_next_item_container(gb_item_container, range))
1254  {
1255  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1256  gb_item;
1257  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
1258  {
1259  CLEAR_QUERIED(gb_item, query);
1260  GB_write_flag(gb_item, 0);
1261 
1262  GBDATA *gb_key = GB_search(gb_item, key, GB_FIND); if (!gb_key) continue;
1263  char *data = GB_read_as_string(gb_key); if (!data) continue;
1264 
1265  if (tokenize) {
1266  char *s;
1267  for (s=strtok(data, ",; \t."); s; s = strtok(NULp, ",; \t.")) {
1268  GBDATA *gb_old = (GBDATA *)GBS_read_hash(hash, s);
1269  if (gb_old) {
1270  const char *oldInfo = NULp;
1271  char *firstInfo = GBS_global_string_copy("1st=%s", s);
1272 
1273  if (IS_QUERIED(gb_old, query)) {
1274  const char *prevInfo = getHitInfo(gb_old, query);
1275  if (!prevInfo) {
1276  oldInfo = firstInfo;
1277  }
1278  else if (!strstr(prevInfo, firstInfo)) { // not already have 1st-entry here
1279  oldInfo = GBS_global_string("%s %s", prevInfo, firstInfo);
1280  }
1281  }
1282  else {
1283  oldInfo = firstInfo;
1284  }
1285 
1286  if (oldInfo) SET_QUERIED(gb_old, query, oldInfo);
1287  SET_QUERIED(gb_item, query, GBS_global_string("dup=%s", s));
1288  GB_write_flag(gb_item, 1);
1289 
1290  free(firstInfo);
1291  }
1292  else {
1293  GBS_write_hash(hash, s, (long)gb_item);
1294  }
1295  }
1296  }
1297  else {
1298  GBDATA *gb_old = (GBDATA *)GBS_read_hash(hash, data);
1299  if (gb_old) {
1300  if (!IS_QUERIED(gb_old, query)) {
1301  SET_QUERIED(gb_old, query, GBS_global_string("%s (1st)", data));
1302  }
1303  SET_QUERIED(gb_item, query, GBS_global_string("%s (duplicate)", data));
1304  GB_write_flag(gb_item, 1);
1305  }
1306  else {
1307  GBS_write_hash(hash, data, (long)gb_item);
1308  }
1309  }
1310 
1311  free(data);
1312  }
1313 
1314  if (type == QUERY_DONT_MATCH) {
1315  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1316  gb_item;
1317  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
1318  {
1319  if (IS_QUERIED(gb_item, query)) {
1320  CLEAR_QUERIED(gb_item, query);
1321  GB_write_flag(gb_item, 0); // unmark
1322  }
1323  else {
1324  SET_QUERIED(gb_item, query, tokenize ? "<entry with unique words>" : "<unique entry>");
1325  }
1326  }
1327  }
1328  }
1329 
1330  GBS_free_hash(hash);
1331  }
1332 
1333  if (type != QUERY_MATCH) {
1334  AW_advice("'Find equal entries' now depends on the values selected for\n"
1335  " * 'that match/don't match the query'\n"
1336  "in the search tool.",
1338  "Behavior changed",
1339  "search_duplicates.hlp");
1340  }
1341  }
1342 
1343  free(key);
1344 
1345  if (error) aw_message(error);
1346  DbQuery_update_list(query);
1347 }
1348 
1350  ItemSelector& selector = query->selector;
1351  AW_root *aw_root = query->aws->get_root();
1353 
1354  const char *key;
1355  if (!error) {
1356  key = prepare_and_get_selected_itemfield(aw_root, query->awar_parskey, query->gb_main, selector);
1357  if (!key) error = GB_await_error();
1358  }
1359 
1360  if (!error) {
1361  GB_TYPES key_type = GBT_get_type_of_changekey(query->gb_main, key, selector.change_key_path);
1362  bool safe_conversion = (key_type != GB_STRING) && !aw_root->awar(query->awar_acceptConvError)->read_int();
1363  char *command = aw_root->awar(query->awar_parsvalue)->read_string();
1364 
1365  if (!strlen(command)) error = "Please enter a command";
1366 
1367  if (!error) {
1368  long ncount = aw_root->awar(query->awar_count)->read_int();
1369  char *deftag = aw_root->awar(query->awar_deftag)->read_string();
1370  char *tag = aw_root->awar(query->awar_tag)->read_string();
1371 
1372  {
1373  long use_tag = aw_root->awar(query->awar_use_tag)->read_int();
1374  if (!use_tag || !strlen(tag)) {
1375  freenull(tag);
1376  }
1377  }
1378  int double_pars = aw_root->awar(query->awar_double_pars)->read_int();
1379 
1380  arb_progress progress("Parse fields", ncount);
1381  QUERY_RANGE range = (QUERY_RANGE)aw_root->awar(query->awar_where)->read_int();
1382  GBL_env env(query->gb_main, query->get_tree_name());
1383 
1384  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
1385  !error && gb_item_container;
1386  gb_item_container = selector.get_next_item_container(gb_item_container, range))
1387  {
1388  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1389  !error && gb_item;
1390  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
1391  {
1392  if (IS_QUERIED(gb_item, query)) {
1393  GBDATA *gb_new = GB_search(gb_item, key, GB_FIND);
1394  error = GB_incur_error_if(!gb_new);
1395 
1396  if (!error) {
1397  GBL_call_env callEnv(gb_item, env);
1398 
1399  char *str = gb_new ? GB_read_as_string(gb_new) : strdup("");
1400  char *parsed = NULp;
1401 
1402  if (double_pars) {
1403  char *com2 = GB_command_interpreter_in_env(str, command, callEnv);
1404  if (com2) {
1405  if (tag) parsed = GBS_modify_tagged_string_with_ACI("", deftag, tag, com2, callEnv);
1406  else parsed = GB_command_interpreter_in_env ("", com2, callEnv);
1407 
1408  free(com2);
1409  }
1410  }
1411  else {
1412  if (tag) parsed = GBS_modify_tagged_string_with_ACI(str, deftag, tag, command, callEnv);
1413  else parsed = GB_command_interpreter_in_env (str, command, callEnv);
1414  }
1415 
1416  if (!parsed) error = GB_await_error();
1417  else {
1418  if (strcmp(parsed, str) != 0) { // any change?
1419  if (gb_new && parsed[0] == 0) { // empty result -> delete field
1420  error = GB_delete(gb_new);
1421  }
1422  else {
1423  if (!gb_new) {
1424  gb_new = GB_search(gb_item, key, key_type);
1425  if (!gb_new) error = GB_await_error();
1426  }
1427  if (!error) {
1428  error = GB_write_autoconv_string(gb_new, parsed); // <- field is actually written HERE
1429  if (!error && safe_conversion) {
1430  dbq_assert(key_type != GB_STRING);
1431  char *resulting = GB_read_as_string(gb_new);
1432  if (!resulting) {
1433  error = GB_await_error();
1434  }
1435  else {
1436  if (strcmp(resulting, parsed) != 0) {
1437  error = GBS_global_string("Conversion error: writing '%s'\n"
1438  "resulted in '%s'\n"
1439  "(mark checkbox to accept conversion errors)",
1440  parsed, resulting);
1441  }
1442  }
1443  }
1444  }
1445  }
1446  }
1447  free(parsed);
1448  }
1449  free(str);
1450  }
1451 
1452  if (error) {
1453  char *errCopy = strdup(error);
1454  char *itemId = selector.generate_item_id(query->gb_main, gb_item);
1455 
1456  error = GBS_global_string("While modifying field of %s '%s':\n%s",
1457  selector.item_name, itemId, errCopy);
1458 
1459  free(itemId);
1460  free(errCopy);
1461  }
1462 
1463  progress.inc_and_check_user_abort(error);
1464  }
1465  }
1466  }
1467 
1468  delete tag;
1469  free(deftag);
1470 
1471  if (error) progress.done();
1472  }
1473 
1474  free(command);
1475  }
1476 
1477  error = GB_end_transaction(query->gb_main, error);
1478  aw_message_if(error);
1479 }
1480 
1481 static void predef_prg(AW_root *aw_root, DbQuery *query) {
1482  char *str = aw_root->awar(query->awar_parspredefined)->read_string();
1483  char *brk = strchr(str, '#');
1484  if (brk) {
1485  *(brk++) = 0;
1486  char *kv = str;
1487  if (!strcmp(str, "ali_*/data")) {
1488  GB_transaction ta(query->gb_main);
1489  char *use = GBT_get_default_alignment(query->gb_main);
1490  kv = GBS_global_string_copy("%s/data", use);
1491  free(use);
1492  }
1493  aw_root->awar(query->awar_parskey)->write_string(kv);
1494  if (kv != str) free(kv);
1495  aw_root->awar(query->awar_parsvalue)->write_string(brk);
1496  }
1497  else {
1498  aw_root->awar(query->awar_parsvalue)->write_string(str);
1499  }
1500  free(str);
1501 }
1502 
1503 static void colorize_queried_cb(AW_window *, DbQuery *query) {
1504  ItemSelector& selector = query->selector;
1505  GB_transaction ta(query->gb_main);
1506  GB_ERROR error = NULp;
1507  AW_root *aw_root = query->aws->get_root();
1508  int color_group = aw_root->awar(AWAR_COLORIZE)->read_int();
1509  QUERY_RANGE range = (QUERY_RANGE)aw_root->awar(query->awar_where)->read_int();
1510  bool changed = false;
1511 
1512  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
1513  !error && gb_item_container;
1514  gb_item_container = selector.get_next_item_container(gb_item_container, range))
1515  {
1516  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1517  !error && gb_item;
1518  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
1519  {
1520  if (IS_QUERIED(gb_item, query)) {
1521  error = GBT_set_color_group(gb_item, color_group);
1522  if (!error) changed = true;
1523  }
1524  }
1525  }
1526 
1527  if (error) GB_export_error(error);
1528  else if (changed) selector.trigger_display_refresh();
1529 }
1530 
1531 static void colorize_marked_cb(AW_window *aww, BoundItemSel *cmd) {
1532  ItemSelector& sel = cmd->selector;
1533  GB_transaction ta(cmd->gb_main);
1534  GB_ERROR error = NULp;
1535  AW_root *aw_root = aww->get_root();
1536  int color_group = aw_root->awar(AWAR_COLORIZE)->read_int();
1537  QUERY_RANGE range = QUERY_ALL_ITEMS; // @@@ FIXME: make customizable
1538 
1539  for (GBDATA *gb_item_container = sel.get_first_item_container(cmd->gb_main, aw_root, range);
1540  !error && gb_item_container;
1541  gb_item_container = sel.get_next_item_container(gb_item_container, range))
1542  {
1543  for (GBDATA *gb_item = sel.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1544  !error && gb_item;
1545  gb_item = sel.get_next_item(gb_item, QUERY_ALL_ITEMS))
1546  {
1547  if (GB_read_flag(gb_item)) {
1548  error = GBT_set_color_group(gb_item, color_group);
1549  }
1550  }
1551  }
1552 
1553  if (error) GB_export_error(error);
1554 }
1555 
1560 };
1561 
1562 static void mark_colored_cb(AW_window *aww, BoundItemSel *cmd, mark_mode mode) {
1563  // @@@ mark_colored_cb is obsolete! (will be replaced by dynamic coloring in the future)
1564  ItemSelector& sel = cmd->selector;
1565  AW_root *aw_root = aww->get_root();
1566  int color_group = aw_root->awar(AWAR_COLORIZE)->read_int();
1567  QUERY_RANGE range = QUERY_ALL_ITEMS; // @@@ FIXME: make customizable
1568 
1569  GB_transaction ta(cmd->gb_main);
1570 
1571  for (GBDATA *gb_item_container = sel.get_first_item_container(cmd->gb_main, aw_root, range);
1572  gb_item_container;
1573  gb_item_container = sel.get_next_item_container(gb_item_container, range))
1574  {
1575  for (GBDATA *gb_item = sel.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1576  gb_item;
1577  gb_item = sel.get_next_item(gb_item, QUERY_ALL_ITEMS))
1578  {
1579  int my_color = GBT_get_color_group(gb_item);
1580  if (my_color == color_group) {
1581  bool marked = GB_read_flag(gb_item);
1582 
1583  switch (mode) {
1584  case UNMARK: marked = 0; break;
1585  case MARK: marked = 1; break;
1586  case INVERT: marked = !marked; break;
1587 
1588  default: dbq_assert(0); break;
1589  }
1590 
1591  GB_write_flag(gb_item, marked);
1592  }
1593  }
1594  }
1595 
1596 }
1597 
1598 // --------------------------------------------------------------------------------
1599 // color sets
1600 
1604 
1605  const char *get_items_name() const {
1606  return bsel->selector.items_name;
1607  }
1608 };
1609 
1610 #define AWAR_COLOR_LOADSAVE_NAME "tmp/colorset/name"
1611 
1613  return GBT_colorset_root(bsel->gb_main, bsel->selector.items_name);
1614 }
1615 
1617  ConstStrArray foundSets;
1618  {
1619  GB_transaction ta(csd->bsel->gb_main);
1620  GBT_get_colorset_names(foundSets, get_colorset_root(csd->bsel));
1621  }
1622 
1623  AW_selection_list *sel = csd->colorsets;
1624  sel->clear();
1625  sel->insert_default("<new colorset>", "");
1626  for (size_t i = 0; i<foundSets.size(); ++i) {
1627  sel->insert(foundSets[i], foundSets[i]);
1628  }
1629  sel->update();
1630 }
1631 
1632 static void colorset_changed_cb(GBDATA*, const color_save_data *csd, GB_CB_TYPE cbt) {
1633  if (cbt&GB_CB_CHANGED) {
1635  }
1636 }
1637 
1638 static void create_colorset_representation(BoundItemSel *bsel, AW_root *aw_root, StrArray& colordefs, GB_ERROR& error) {
1639  ItemSelector& sel = bsel->selector;
1640  GBDATA *gb_main = bsel->gb_main;
1641 
1642  dbq_assert(!error);
1643 
1644  for (GBDATA *gb_item_container = sel.get_first_item_container(gb_main, aw_root, QUERY_ALL_ITEMS);
1645  gb_item_container;
1646  gb_item_container = sel.get_next_item_container(gb_item_container, QUERY_ALL_ITEMS))
1647  {
1648  for (GBDATA *gb_item = sel.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1649  gb_item;
1650  gb_item = sel.get_next_item(gb_item, QUERY_ALL_ITEMS))
1651  {
1652  int color = GBT_get_color_group(gb_item);
1653  if (color>0) {
1654  char *id = sel.generate_item_id(gb_main, gb_item);
1655  char *color_def = GBS_global_string_copy("%s=%i", id, color);
1656 
1657  colordefs.put(color_def);
1658  free(id);
1659  }
1660  }
1661  }
1662 
1663  if (colordefs.empty()) {
1664  error = GBS_global_string("Could not find any colored %s", sel.items_name);
1665  }
1666 }
1667 
1669  ItemSelector& sel = bsel->selector;
1670  GB_ERROR error = NULp;
1671  bool changed = false;
1672 
1673  for (GBDATA *gb_item_container = sel.get_first_item_container(bsel->gb_main, aw_root, QUERY_ALL_ITEMS);
1674  !error && gb_item_container;
1675  gb_item_container = sel.get_next_item_container(gb_item_container, QUERY_ALL_ITEMS))
1676  {
1677  for (GBDATA *gb_item = sel.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
1678  !error && gb_item;
1679  gb_item = sel.get_next_item(gb_item, QUERY_ALL_ITEMS))
1680  {
1681  error = GBT_set_color_group(gb_item, 0); // clear colors
1682  if (!error) changed = true;
1683  }
1684  }
1685 
1686  if (changed && !error) sel.trigger_display_refresh();
1687  return error;
1688 }
1689 
1690 static void clear_all_colors_cb(AW_window *aww, BoundItemSel *bsel) {
1691  GB_transaction ta(bsel->gb_main);
1692  GB_ERROR error = clear_all_colors(bsel, aww->get_root());
1693 
1694  if (error) {
1695  error = ta.close(error);
1696  aw_message(error);
1697  }
1698 }
1699 
1701  ItemSelector& sel = bsel->selector;
1702  GBDATA *gb_main = bsel->gb_main;
1703  bool changed = false;
1704  GB_ERROR error = NULp;
1705  int ignores = 0;
1706 
1707  for (size_t d = 0; d<colordefs.size() && !error; ++d) {
1708  const char *def = colordefs[d];
1709  const char *equal = strchr(def, '=');
1710 
1711  if (equal) {
1712  LocallyModify<char> tempSplit(const_cast<char*>(equal)[0], 0);
1713 
1714  const char *id = def;
1715  GBDATA *gb_item = sel.find_item_by_id(gb_main, id);
1716  if (!gb_item) {
1717  aw_message(GBS_global_string("No such %s: '%s' (ignored)", sel.item_name, id)); // only warn
1718  ++ignores;
1719  }
1720  else {
1721  int color_group = atoi(equal+1);
1722  if (color_group>0) { // bugfix: saved color groups contained zero (which means "no color") by mistake; ignore
1723  error = GBT_set_color_group(gb_item, color_group);
1724  if (!error) changed = true;
1725  }
1726  }
1727  }
1728  else {
1729  aw_message(GBS_global_string("Invalid colordef '%s' (ignored)", def));
1730  ++ignores;
1731  }
1732  }
1733  if (changed && !error) sel.trigger_display_refresh();
1734  if (ignores>0 && !error) {
1735  aw_message(GBS_global_string("Warning: failed to restore color assignment for %i %s", ignores, sel.items_name));
1736  }
1737 
1738  return error;
1739 }
1740 
1746 };
1747 
1749  AW_root *aw_root = aws->get_root();
1750  char *name = aw_root->awar(AWAR_COLOR_LOADSAVE_NAME)->read_string();
1751  GB_ERROR error = NULp;
1752 
1753  if (name[0] == 0) error = "Please enter a name for the colorset.";
1754  else {
1755  GB_transaction ta(bsel->gb_main);
1756 
1757  GBDATA *gb_colorset_root = get_colorset_root(bsel);
1758  GBDATA *gb_colorset = gb_colorset_root ? GBT_find_colorset(gb_colorset_root, name) : NULp;
1759 
1760  error = GB_incur_error();
1761  if (!error) {
1762  if (mode == SAVE) {
1763  if (!gb_colorset) { // create new colorset
1764  gb_colorset = GBT_find_or_create_colorset(gb_colorset_root, name);
1765  if (!gb_colorset) error = GB_await_error();
1766  }
1767  dbq_assert(gb_colorset || error);
1768 
1769  if (!error) {
1770  StrArray colordefs;
1771  create_colorset_representation(bsel, aw_root, colordefs, error);
1772  if (!error) error = GBT_save_colorset(gb_colorset, colordefs);
1773  }
1774  }
1775  else {
1776  if (!gb_colorset) error = GBS_global_string("Colorset '%s' not found", name);
1777  else {
1778  if (mode == LOAD || mode == OVERLAY) {
1779  ConstStrArray colordefs;
1780  error = GBT_load_colorset(gb_colorset, colordefs);
1781 
1782  if (!error && colordefs.empty()) error = "oops.. empty colorset";
1783  if (!error && mode == LOAD) error = clear_all_colors(bsel, aw_root);
1784  if (!error) error = restore_colorset_representation(bsel, colordefs);
1785  }
1786  else {
1787  dbq_assert(mode == DELETE);
1788  error = GB_delete(gb_colorset);
1789  }
1790  }
1791  }
1792  }
1793  error = ta.close(error);
1794  }
1795  free(name);
1796 
1797  if (error) aw_message(error);
1798 }
1799 
1801  static AW_window **aw_loadsave = NULp;
1802  if (!aw_loadsave) {
1803  // init data
1805  ARB_calloc(aw_loadsave, QUERY_ITEM_TYPES); // contains loadsave windows for each item type
1806  }
1807 
1809 
1811 
1812  if (!aw_loadsave[type]) {
1813  // init window
1814  AW_window_simple *aws = new AW_window_simple;
1815  {
1816  char *window_id = GBS_global_string_copy("colorset_loadsave_%s", csd->get_items_name());
1817  aws->init(aw_root, window_id, GBS_global_string("Load/Save %s colorset", csd->get_items_name()));
1818  free(window_id);
1819  }
1820 
1821  aws->load_xfig("query/color_loadsave.fig");
1822 
1823  aws->at("close");
1824  aws->callback(AW_POPDOWN);
1825  aws->create_button("CLOSE", "CLOSE", "C");
1826 
1827  aws->at("help");
1828  aws->callback(makeHelpCallback("color_loadsave.hlp"));
1829  aws->create_button("HELP", "HELP", "H");
1830 
1831  dbq_assert(!csd->colorsets);
1833 
1835 
1836  aws->at("save"); aws->callback(makeWindowCallback(loadsave_colorset_cb, csd->bsel, SAVE)); aws->create_button("save", "Save", "S");
1837  aws->at("load"); aws->callback(makeWindowCallback(loadsave_colorset_cb, csd->bsel, LOAD)); aws->create_button("load", "Load", "L");
1838  aws->at("overlay"); aws->callback(makeWindowCallback(loadsave_colorset_cb, csd->bsel, OVERLAY)); aws->create_button("overlay", "Overlay", "O");
1839  aws->at("delete"); aws->callback(makeWindowCallback(loadsave_colorset_cb, csd->bsel, DELETE)); aws->create_button("delete", "Delete", "D");
1840 
1841  aws->at("reset");
1842  aws->callback(makeWindowCallback(clear_all_colors_cb, csd->bsel));
1843  aws->create_button("reset", "Reset", "R");
1844 
1845  // callbacks
1846  {
1847  GB_transaction ta(csd->bsel->gb_main);
1848  GBDATA *gb_colorset = get_colorset_root(csd->bsel);
1849  GB_add_callback(gb_colorset, GB_CB_CHANGED, makeDatabaseCallback(colorset_changed_cb, csd));
1850  }
1851 
1852  aw_loadsave[type] = aws;
1853  }
1854 
1855  return aw_loadsave[type];
1856 }
1857 
1859  // invoked by 'colorize listed' (sel != 0)
1860  // and 'colorize marked/mark colored' (query != 0)
1861 
1862  enum { COLORIZE_INVALID, COLORIZE_LISTED, COLORIZE_MARKED } mode = COLORIZE_INVALID;
1863 
1865 
1866  AW_window_simple *aws = new AW_window_simple;
1867 
1868  dbq_assert(contradicted(query, sel));
1869 
1870  if (query) {
1871  dbq_assert(mode == COLORIZE_INVALID);
1872  mode = COLORIZE_LISTED;
1873  }
1874  if (sel) {
1875  dbq_assert(mode == COLORIZE_INVALID);
1876  mode = COLORIZE_MARKED;
1877  }
1878  dbq_assert(!(mode == COLORIZE_INVALID));
1879 
1880  ItemSelector& Sel = mode == COLORIZE_LISTED ? query->selector : *sel;
1881  const char *what = mode == COLORIZE_LISTED ? "listed" : "marked";
1882 
1883  {
1884  char *macro_name = GBS_global_string_copy("COLORIZE_%s_%s", what, Sel.items_name);
1885  char *window_name = GBS_global_string_copy("Colorize %s %s", what, Sel.items_name);
1886 
1887  aws->init(aw_root, macro_name, window_name);
1888 
1889  free(window_name);
1890  free(macro_name);
1891  }
1892 
1893  aws->load_xfig("query/colorize.fig");
1894 
1895  aws->auto_space(10, 10);
1896 
1897  aws->at("close");
1898  aws->callback(AW_POPDOWN);
1899  aws->create_button("CLOSE", "CLOSE", "C");
1900 
1901  aws->at("help");
1902  aws->callback(makeHelpCallback(mode == COLORIZE_LISTED ? "set_color_of_listed.hlp" : "colorize.hlp"));
1903  aws->create_button("HELP", "HELP", "H");
1904 
1905  aws->at("colorize");
1906 
1907  BoundItemSel *bsel = new BoundItemSel(gb_main, ((mode == COLORIZE_MARKED) ? *sel : query->selector)); // do not free, bound to CB
1908 
1909  if (mode == COLORIZE_LISTED) aws->callback(makeWindowCallback(colorize_queried_cb, query));
1910  else aws->callback(makeWindowCallback(colorize_marked_cb, bsel));
1911 
1912  aws->create_autosize_button("COLORIZE", GBS_global_string_copy("Set color of %s %s to ...", what, Sel.items_name), "S", 2);
1913 
1914  {
1915  int color_group;
1916 
1917  aws->create_option_menu(AWAR_COLORIZE, true);
1918  aws->insert_default_option("No color group", "none", 0);
1919  for (color_group = 1; color_group <= AW_COLOR_GROUPS; ++color_group) {
1920  char *name = AW_get_color_group_name(aw_root, color_group);
1921  aws->insert_option(name, "", color_group);
1922  free(name);
1923  }
1924  aws->update_option_menu();
1925  }
1926 
1927  color_save_data *csd = new color_save_data; // do not free, bound to CB
1928  csd->bsel = bsel;
1929  csd->colorsets = NULp;
1930 
1931  aws->at("loadsave");
1932  aws->callback(makeCreateWindowCallback(create_loadsave_colored_window, csd));
1933  aws->create_autosize_button("LOADSAVE_COLORED", "Load/Save", "L");
1934 
1935  if (mode == COLORIZE_MARKED) {
1936  aws->at("mark");
1937  aws->callback(makeWindowCallback(mark_colored_cb, bsel, MARK));
1938  aws->create_autosize_button("MARK_COLORED", GBS_global_string_copy("Mark all %s of ...", Sel.items_name), "M", 2);
1939 
1940  aws->at("unmark");
1941  aws->callback(makeWindowCallback(mark_colored_cb, bsel, UNMARK));
1942  aws->create_autosize_button("UNMARK_COLORED", GBS_global_string_copy("Unmark all %s of ...", Sel.items_name), "U", 2);
1943 
1944  aws->at("invert");
1945  aws->callback(makeWindowCallback(mark_colored_cb, bsel, INVERT));
1946  aws->create_autosize_button("INVERT_COLORED", GBS_global_string_copy("Invert all %s of ...", Sel.items_name), "I", 2);
1947  }
1948 
1949  aws->at_newline();
1950  aws->window_fit();
1951 
1952  return aws;
1953 }
1954 
1956  return create_colorize_window(aw_root, query->gb_main, query, NULp);
1957 }
1958 
1960  return create_colorize_window(aw_root, gb_main, NULp, &sel);
1961 }
1962 
1964  const char *typeawar = get_itemfield_type_awarname(query->awar_parskey);
1965  dbq_assert(typeawar);
1966 
1967  cdef.add(query->awar_parskey, "key");
1968  cdef.add(typeawar, "type");
1969  cdef.add(query->awar_use_tag, "usetag");
1970  cdef.add(query->awar_deftag, "deftag");
1971  cdef.add(query->awar_tag, "modtag");
1972  cdef.add(query->awar_double_pars, "doubleparse");
1973  cdef.add(query->awar_acceptConvError, "acceptconv");
1974  cdef.add(query->awar_parsvalue, "aci");
1975 }
1976 
1978  AW_window_simple *aws = new AW_window_simple;
1979 
1980  {
1981  char *macro_name = GBS_global_string_copy("MODIFY_DATABASE_FIELD_%s", query->selector.items_name);
1982  char *window_name = GBS_global_string_copy("MODIFY DATABASE FIELD of listed %s", query->selector.items_name);
1983 
1984  aws->init(aw_root, macro_name, window_name);
1985 
1986  free(window_name);
1987  free(macro_name);
1988  }
1989 
1990  aws->load_xfig("query/modify_fields.fig");
1991 
1992  aws->at("close");
1993  aws->callback(AW_POPDOWN);
1994  aws->create_button("CLOSE", "CLOSE", "C");
1995 
1996  aws->at("help");
1997  aws->callback(makeHelpCallback("mod_field_list.hlp"));
1998  aws->create_button("HELP", "HELP", "H");
1999 
2000  aws->at("helptags");
2001  aws->callback(makeHelpCallback("tags.hlp"));
2002  aws->create_button("HELP_TAGS", "Help tags", "H");
2003 
2005  aws->at("accept"); aws->create_toggle(query->awar_acceptConvError);
2006 
2007  // ------------------------
2008  // expert section
2009  aws->at("usetag"); aws->create_toggle(query->awar_use_tag);
2010  aws->at("deftag"); aws->create_input_field(query->awar_deftag);
2011  aws->at("tag"); aws->create_input_field(query->awar_tag);
2012  aws->at("double"); aws->create_toggle(query->awar_double_pars);
2013 
2014  aws->at("parser");
2015  aws->create_text_field(query->awar_parsvalue);
2016 
2017  aws->at("go");
2018  aws->callback(makeWindowCallback(modify_fields_of_queried_cb, query));
2019  aws->create_button("GO", "GO", "G");
2020 
2021  aws->at("pre");
2022  AW_selection_list *programs = aws->create_selection_list(query->awar_parspredefined, true);
2023 
2024  const char *sellst = NULp;
2025  switch (query->selector.type) {
2026  case QUERY_ITEM_SPECIES:
2027  case QUERY_ITEM_ORGANISM: sellst = "mod_fields*.sellst"; break;
2028  case QUERY_ITEM_GENES: sellst = "mod_gene_fields*.sellst"; break;
2029  case QUERY_ITEM_EXPERIMENTS: sellst = "mod_experiment_fields*.sellst"; break;
2030  default: dbq_assert(0); break;
2031  }
2032 
2033  GB_ERROR error;
2034  if (sellst) {
2035  StorableSelectionList storable_sellist(TypedSelectionList("sellst", programs, "field modification scripts", "mod_fields"));
2036  error = storable_sellist.load(GB_path_in_ARBLIB("sellists", sellst), false);
2037  }
2038  else {
2039  error = "No default selection list for query-type";
2040  }
2041 
2042  if (error) {
2043  aw_message(error);
2044  }
2045  else {
2046  aws->get_root()->awar(query->awar_parspredefined)->add_callback(makeRootCallback(predef_prg, query));
2047  }
2048 
2049  aws->at("config");
2051  GBS_global_string("mod_%s_fields", query->selector.item_name),
2052  makeConfigSetupCallback(setup_modify_fields_config, query));
2053 
2054  return aws;
2055 }
2056 
2057 static void set_field_of_queried_cb(AW_window*, DbQuery *query, bool append) {
2058  // set fields of listed items
2059  ItemSelector& selector = query->selector;
2060  GB_ERROR error = NULp;
2061  AW_root *aw_root = query->aws->get_root();
2062  bool allow_loss = aw_root->awar(query->awar_writelossy)->read_int();
2063 
2064  char *value = aw_root->awar(query->awar_setvalue)->read_string();
2065  if (value[0] == 0) freenull(value);
2066 
2067  size_t value_len = value ? strlen(value) : 0;
2068 
2069  GB_begin_transaction(query->gb_main);
2070 
2071  const char *key = prepare_and_get_selected_itemfield(aw_root, query->awar_writekey, query->gb_main, selector);
2072  if (!key) error = GB_await_error();
2073 
2074  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, QUERY_ALL_ITEMS);
2075  !error && gb_item_container;
2076  gb_item_container = selector.get_next_item_container(gb_item_container, QUERY_ALL_ITEMS))
2077  {
2078  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
2079  !error && gb_item;
2080  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
2081  {
2082  if (IS_QUERIED(gb_item, query)) {
2083  if (!value) { // empty value -> delete field
2084  if (!append) {
2085  GBDATA *gb_field = GB_search(gb_item, key, GB_FIND);
2086  if (gb_field) error = GB_delete(gb_field);
2087  }
2088  // otherwise "nothing" is appended (=noop)
2089  }
2090  else {
2092  if (!gb_field) error = GB_await_error();
2093  else {
2094  const char *new_content = value;
2095  SmartCharPtr content;
2096 
2097  if (append) {
2098  char *old = GB_read_as_string(gb_field);
2099  if (!old) error = "field has incompatible type";
2100  else {
2101  size_t old_len = strlen(old);
2102  GBS_strstruct *strstr = GBS_stropen(old_len+value_len+2);
2103 
2104  GBS_strncat(strstr, old, old_len);
2105  GBS_strncat(strstr, value, value_len);
2106 
2107  content = GBS_strclose(strstr);
2108  new_content = &*content;
2109  }
2110  }
2111 
2112  error = GB_write_autoconv_string(gb_field, new_content);
2113 
2114  if (!allow_loss && !error) {
2115  char *result = GB_read_as_string(gb_field);
2116  dbq_assert(result);
2117 
2118  if (strcmp(new_content, result) != 0) {
2119  error = GBS_global_string("value modified by type conversion\n('%s' -> '%s')", new_content, result);
2120  }
2121  free(result);
2122  }
2123  }
2124  }
2125 
2126  if (error) { // add name of current item to error
2127  const char *name = GBT_read_char_pntr(gb_item, "name");
2128  error = GBS_global_string("Error while writing to %s '%s':\n%s", selector.item_name, name, error);
2129  }
2130  }
2131  }
2132  }
2133 
2135 
2136  free(value);
2137 }
2138 
2140  AW_window_simple *aws = new AW_window_simple;
2141  init_itemType_specific_window(aw_root, aws, query->selector, "WRITE_DB_FIELD_OF_LISTED", "Write field of listed %s", true);
2142  aws->load_xfig("query/write_fields.fig");
2143 
2144  aws->at("close");
2145  aws->callback(AW_POPDOWN);
2146  aws->create_button("CLOSE", "CLOSE", "C");
2147 
2148  aws->at("help");
2149  aws->callback(makeHelpCallback("write_field_list.hlp"));
2150  aws->create_button("HELP", "HELP", "H");
2151 
2153 
2154  aws->at("val");
2155  aws->create_text_field(query->awar_setvalue, 2, 2);
2156 
2157  aws->at("lossy");
2158  aws->label("Allow lossy conversion?");
2159  aws->create_toggle(query->awar_writelossy);
2160 
2161  aws->at("create");
2162  aws->callback(makeWindowCallback(set_field_of_queried_cb, query, false));
2163  aws->create_button("SET_SINGLE_FIELD_OF_LISTED", "WRITE");
2164 
2165  aws->at("do");
2166  aws->callback(makeWindowCallback(set_field_of_queried_cb, query, true));
2167  aws->create_button("APPEND_SINGLE_FIELD_OF_LISTED", "APPEND");
2168 
2169  return aws;
2170 }
2171 
2173  // set protection of listed items
2174  ItemSelector& selector = query->selector;
2175  AW_root *aw_root = query->aws->get_root();
2176  char *key = aw_root->awar(query->awar_protectkey)->read_string();
2177 
2178  if (strcmp(key, NO_FIELD_SELECTED) == 0) {
2179  aw_message("Please select a field for which you want to set the protection");
2180  }
2181  else {
2182  GB_begin_transaction(query->gb_main);
2183 
2184  GB_ERROR error = NULp;
2185  GBDATA *gb_key_data = GB_search(query->gb_main, selector.change_key_path, GB_CREATE_CONTAINER);
2186  GBDATA *gb_key_name = GB_find_string(gb_key_data, CHANGEKEY_NAME, key, GB_IGNORE_CASE, SEARCH_GRANDCHILD);
2187 
2188  if (!gb_key_name) {
2189  error = GBS_global_string("The destination field '%s' does not exists", key);
2190  }
2191  else {
2192  int level = aw_root->awar(query->awar_setprotection)->read_int();
2193  QUERY_RANGE range = (QUERY_RANGE)aw_root->awar(query->awar_where)->read_int();
2194 
2195  for (GBDATA *gb_item_container = selector.get_first_item_container(query->gb_main, aw_root, range);
2196  !error && gb_item_container;
2197  gb_item_container = selector.get_next_item_container(gb_item_container, range))
2198  {
2199  for (GBDATA *gb_item = selector.get_first_item(gb_item_container, QUERY_ALL_ITEMS);
2200  !error && gb_item;
2201  gb_item = selector.get_next_item(gb_item, QUERY_ALL_ITEMS))
2202  {
2203  if (IS_QUERIED(gb_item, query)) {
2204  GBDATA *gb_new = GB_search(gb_item, key, GB_FIND);
2205  if (gb_new) {
2206  error = GB_write_security_delete(gb_new, level);
2207  if (!error) error = GB_write_security_write(gb_new, level);
2208  }
2209  }
2210  }
2211  }
2212  }
2214  }
2215 
2216  free(key);
2217 }
2218 
2220  AW_window_simple *aws = new AW_window_simple;
2221  init_itemType_specific_window(aw_root, aws, query->selector, "SET_PROTECTION_OF_FIELD_OF_LISTED", "Protect field of listed %s", true);
2222  aws->load_xfig("query/set_protection.fig");
2223 
2224  aws->at("close");
2225  aws->callback(AW_POPDOWN);
2226  aws->create_button("CLOSE", "CLOSE", "C");
2227 
2228  aws->at("help");
2229  aws->callback(makeHelpCallback("set_protection.hlp"));
2230  aws->create_button("HELP", "HELP", "H");
2231 
2232 
2233  aws->at("prot");
2234  aws->create_toggle_field(query->awar_setprotection, 0);
2235  aws->insert_toggle("0 temporary", "0", 0);
2236  aws->insert_toggle("1 checked", "1", 1);
2237  aws->insert_toggle("2", "2", 2);
2238  aws->insert_toggle("3", "3", 3);
2239  aws->insert_toggle("4 normal", "4", 4);
2240  aws->insert_toggle("5 ", "5", 5);
2241  aws->insert_toggle("6 the truth", "5", 6);
2242  aws->update_toggle_field();
2243 
2244  create_itemfield_selection_list(aws, FieldSelDef(query->awar_protectkey, query->gb_main, query->selector, FIELD_UNFILTERED, "field to protect"), "list");
2245 
2246  aws->at("go");
2247  aws->callback(makeWindowCallback(set_protection_of_queried_cb, query));
2248  aws->create_autosize_button("SET_PROTECTION_OF_FIELD_OF_LISTED", "Assign\nprotection\nto field\nof listed");
2249 
2250  return aws;
2251 }
2252 
2253 static void toggle_flag_cb(AW_window *aww, DbQuery *query) {
2254  GB_transaction ta(query->gb_main);
2255  GBDATA *gb_item = query->selector.get_selected_item(query->gb_main, aww->get_root());
2256  if (gb_item) {
2257  long flag = GB_read_flag(gb_item);
2258  GB_write_flag(gb_item, 1-flag);
2259  }
2260  DbQuery_update_list(query);
2261 }
2262 
2263 static void new_selection_made_cb(AW_root *aw_root, const char *awar_selection, DbQuery *query) {
2264  char *item_name = aw_root->awar(awar_selection)->read_as_string();
2265  query->selector.update_item_awars(query->gb_main, aw_root, item_name);
2266  free(item_name);
2267 }
2268 
2270  // this defines what is saved/restored to/from configs
2271  for (int key_id = 0; key_id<QUERY_EXPRESSIONS; ++key_id) {
2272  cdef.add(query->awar_keys[key_id], "key", key_id);
2273  cdef.add(query->awar_queries[key_id], "query", key_id);
2274  cdef.add(query->awar_not[key_id], "not", key_id);
2275  cdef.add(query->awar_operator[key_id], "operator", key_id);
2276  }
2277 }
2278 
2279 template<typename CB>
2280 static void query_rel_menu_entry(AW_window *aws, const char *id, const char *query_id, const char* label, const char *mnemonic, const char *helpText, AW_active Mask, const CB& cb) {
2281  char *rel_id = GBS_global_string_copy("%s_%s", query_id, id);
2282  aws->insert_menu_topic(rel_id, label, mnemonic, helpText, Mask, cb);
2283  free(rel_id);
2284 }
2285 
2286 const char *DbQuery::get_tree_name() const {
2287  if (!awar_tree_name)
2288  return NULp;
2289  else
2290  return aws->get_root()->awar(awar_tree_name)->read_char_pntr();
2291 }
2292 
2294  for (int s = 0; s<QUERY_EXPRESSIONS; ++s) {
2295  free(awar_keys[s]);
2296  free(awar_queries[s]);
2297  free(awar_not[s]);
2298  free(awar_operator[s]);
2299  }
2300 
2301  free(species_name);
2302 
2303  free(awar_writekey);
2304  free(awar_writelossy);
2305  free(awar_protectkey);
2306  free(awar_setprotection);
2307  free(awar_setvalue);
2308 
2309  free(awar_parskey);
2310  free(awar_parsvalue);
2311  free(awar_parspredefined);
2312  free(awar_acceptConvError);
2313 
2314  free(awar_ere);
2315  free(awar_where);
2316  free(awar_by);
2317  free(awar_use_tag);
2318  free(awar_double_pars);
2319  free(awar_deftag);
2320  free(awar_tag);
2321  free(awar_count);
2322  free(awar_sort);
2323 
2325 }
2326 
2327 // ----------------------------------------
2328 // store query data until DB close
2329 
2331 template<> void Keeper<DbQuery*>::destroy(DbQuery *q) { delete q; }
2333 static void destroyKeptQueries() {
2334  queryKeeper.setNull();
2335 }
2336 static void keepQuery(GBDATA *gbmain, DbQuery *q) {
2337  if (queryKeeper.isNull()) {
2338  queryKeeper = new QueryKeeper;
2339  GB_atclose_callback(gbmain, makeDatabaseCallback(destroyKeptQueries));
2340  }
2341  queryKeeper->keep(q);
2342 }
2343 
2344 // ----------------------------------------
2345 
2346 DbQuery *QUERY::create_query_box(AW_window *aws, query_spec *awtqs, const char *query_id) {
2347  char buffer[256];
2348  AW_root *aw_root = aws->get_root();
2349  GBDATA *gb_main = awtqs->gb_main;
2350  DbQuery *query = new DbQuery(awtqs->get_queried_itemtype());
2351 
2352  keepQuery(gb_main, query); // transfers ownership of query
2353 
2354  // @@@ set all the things below via ctor!
2355  // @@@ create a copyable object containing everything query_spec and DbQuery have in common -> pass that object to DbQuery-ctor
2356 
2357  query->gb_main = awtqs->gb_main;
2358  query->aws = aws;
2359  query->gb_ref = awtqs->gb_ref;
2361  query->select_bit = awtqs->select_bit;
2362  query->species_name = strdup(awtqs->species_name);
2363 
2364  query->set_tree_awar_name(awtqs->tree_name);
2366 
2367  GB_push_transaction(gb_main);
2368 
2369  // Create query box AWARS
2371 
2372  {
2373  const char *default_key[QUERY_EXPRESSIONS+1] = { "name", "name", "name", NULp };
2374 
2375  for (int key_id = 0; key_id<QUERY_EXPRESSIONS; ++key_id) {
2376  sprintf(buffer, "tmp/dbquery_%s/key_%i", query_id, key_id);
2377  query->awar_keys[key_id] = strdup(buffer);
2378  dbq_assert(default_key[key_id]);
2379  aw_root->awar_string(query->awar_keys[key_id], default_key[key_id], AW_ROOT_DEFAULT);
2380 
2381  sprintf(buffer, "tmp/dbquery_%s/query_%i", query_id, key_id);
2382  query->awar_queries[key_id] = strdup(buffer);
2383  aw_root->awar_string(query->awar_queries[key_id], "*", AW_ROOT_DEFAULT);
2384 
2385  sprintf(buffer, "tmp/dbquery_%s/not_%i", query_id, key_id);
2386  query->awar_not[key_id] = strdup(buffer);
2387  aw_root->awar_int(query->awar_not[key_id], 0, AW_ROOT_DEFAULT);
2388 
2389  sprintf(buffer, "tmp/dbquery_%s/operator_%i", query_id, key_id);
2390  query->awar_operator[key_id] = strdup(buffer);
2391  aw_root->awar_string(query->awar_operator[key_id], "ign", AW_ROOT_DEFAULT);
2392  }
2393  aw_root->awar(query->awar_keys[0])->add_callback(makeRootCallback(first_searchkey_changed_cb, query));
2394  }
2395 
2396  sprintf(buffer, "tmp/dbquery_%s/ere", query_id);
2397  query->awar_ere = strdup(buffer);
2398  aw_root->awar_int(query->awar_ere, QUERY_GENERATE);
2399 
2400  sprintf(buffer, "tmp/dbquery_%s/where", query_id);
2401  query->awar_where = strdup(buffer);
2402  aw_root->awar_int(query->awar_where, QUERY_ALL_ITEMS);
2403 
2404  sprintf(buffer, "tmp/dbquery_%s/count", query_id);
2405  query->awar_count = strdup(buffer);
2406  aw_root->awar_int(query->awar_count, 0);
2407 
2408  sprintf(buffer, "tmp/dbquery_%s/sort", query_id);
2409  query->awar_sort = strdup(buffer);
2410  aw_root->awar_int(query->awar_sort, QUERY_SORT_NONE)->add_callback(makeRootCallback(result_sort_order_changed_cb, query));
2411  query->sort_mask = QUERY_SORT_NONE; // default to unsorted
2412 
2413  sprintf(buffer, "tmp/dbquery_%s/by", query_id);
2414  query->awar_by = strdup(buffer);
2415  aw_root->awar_int(query->awar_by, QUERY_MATCH);
2416 
2417  if (awtqs->ere_pos_fig) {
2418  aws->at(awtqs->ere_pos_fig);
2419  aws->create_toggle_field(query->awar_ere, "", "");
2420 
2421  aws->insert_toggle(GBS_global_string("Search %s", query->selector.items_name), "G", (int)QUERY_GENERATE);
2422  aws->insert_toggle(GBS_global_string("Add %s", query->selector.items_name), "E", (int)QUERY_ENLARGE);
2423  aws->insert_toggle(GBS_global_string("Keep %s", query->selector.items_name), "R", (int)QUERY_REDUCE);
2424 
2425  aws->update_toggle_field();
2426  }
2427  if (awtqs->where_pos_fig) {
2428  aws->at(awtqs->where_pos_fig);
2429  aws->create_toggle_field(query->awar_where, "", "");
2430  aws->insert_toggle("of current organism", "C", (int)QUERY_CURRENT_ITEM);
2431  aws->insert_toggle("of marked organisms", "M", (int)QUERY_MARKED_ITEMS);
2432  aws->insert_toggle("of all organisms", "A", (int)QUERY_ALL_ITEMS);
2433  aws->update_toggle_field();
2434 
2435  }
2436  if (awtqs->by_pos_fig) {
2437  aws->at(awtqs->by_pos_fig);
2438  aws->create_toggle_field(query->awar_by, "", "");
2439  aws->insert_toggle("that match the query", "M", (int)QUERY_MATCH);
2440  aws->insert_toggle("that don't match the q.", "D", (int)QUERY_DONT_MATCH);
2441  aws->insert_toggle("that are marked", "A", (int)QUERY_MARKED);
2442  aws->update_toggle_field();
2443  }
2444 
2445  // distances for multiple queries :
2446 
2447 #define KEY_Y_OFFSET 32
2448 
2449  int xpos_calc[3] = { -1, -1, -1 }; // X-positions for elements in search expressions
2450 
2451  if (awtqs->qbox_pos_fig) {
2452  aws->auto_space(1, 1);
2453  aws->at(awtqs->qbox_pos_fig);
2454 
2456 
2457  int xpos, ypos;
2458  aws->get_at_position(&xpos, &ypos);
2459 
2460  int ypos_dummy;
2461 
2462  for (int key = QUERY_EXPRESSIONS-1; key >= 0; --key) {
2463  if (key) {
2464  aws->at(xpos, ypos+key*KEY_Y_OFFSET);
2465  aws->create_option_menu(query->awar_operator[key], true);
2466  aws->insert_option("and", "", "and");
2467  aws->insert_option("or", "", "or");
2468  aws->insert_option("ign", "", "ign");
2469  aws->update_option_menu();
2470 
2471  if (xpos_calc[0] == -1) aws->get_at_position(&xpos_calc[0], &ypos_dummy);
2472  }
2473 
2474  aws->at(xpos_calc[0], ypos+key*KEY_Y_OFFSET);
2475  aws->restore_at_from(*at_size);
2476 
2478 
2479  if (xpos_calc[1] == -1) aws->get_at_position(&xpos_calc[1], &ypos_dummy);
2480 
2481  aws->at(xpos_calc[1], ypos+key*KEY_Y_OFFSET);
2482  aws->create_toggle(query->awar_not[key], "#equal.xpm", "#notEqual.xpm");
2483 
2484  if (xpos_calc[2] == -1) aws->get_at_position(&xpos_calc[2], &ypos_dummy);
2485  }
2486  }
2487  if (awtqs->key_pos_fig) {
2488  aws->at(awtqs->key_pos_fig);
2489  aws->create_input_field(query->awar_keys[0], 12);
2490  }
2491 
2492  if (awtqs->query_pos_fig) {
2493  aws->at(awtqs->query_pos_fig);
2494 
2496 
2497  int xpos, ypos;
2498  aws->get_at_position(&xpos, &ypos);
2499 
2500  for (int key = 0; key<QUERY_EXPRESSIONS; ++key) {
2501  aws->at(xpos_calc[2], ypos+key*KEY_Y_OFFSET);
2502  aws->restore_at_from(*at_size);
2503  aws->d_callback(makeWindowCallback(perform_query_cb, query, EXT_QUERY_NONE)); // enable ENTER in searchfield to start search
2504  aws->create_input_field(query->awar_queries[key], 12);
2505  }
2506  }
2507 
2508  if (awtqs->result_pos_fig) {
2509  aws->at(awtqs->result_pos_fig);
2510  aws->d_callback(makeWindowCallback(toggle_flag_cb, query));
2511 
2512  {
2513  const char *this_awar_name = ARB_keep_string(GBS_global_string_copy("tmp/dbquery_%s/select", query_id)); // do not free this cause it's passed to new_selection_made_cb
2514  AW_awar *awar = aw_root->awar_string(this_awar_name, "", AW_ROOT_DEFAULT);
2515 
2516  query->hitlist = aws->create_selection_list(this_awar_name, 5, 5, true);
2517  awar->add_callback(makeRootCallback(new_selection_made_cb, this_awar_name, query));
2518  }
2519  query->hitlist->insert_default("end of list", "");
2520  query->hitlist->update();
2521  }
2522 
2523  if (awtqs->count_pos_fig) {
2524  aws->button_length(13);
2525  aws->at(awtqs->count_pos_fig);
2526  aws->label("Hits:");
2527  aws->create_button(NULp, query->awar_count, NULp, "+");
2528 
2529  if (awtqs->popup_info_window) {
2531  aws->create_button("popinfo", "Info");
2532  }
2533  }
2534  else {
2535  dbq_assert(!awtqs->popup_info_window); // dont know where to display
2536  }
2537 
2538  if (awtqs->config_pos_fig) {
2539  aws->button_length(0);
2540  aws->at(awtqs->config_pos_fig);
2541  char *macro_id = GBS_global_string_copy("SAVELOAD_CONFIG_%s", query_id);
2542  AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "query_box", makeConfigSetupCallback(query_box_setup_config, query), macro_id);
2543  free(macro_id);
2544  }
2545 
2546  aws->button_length(18);
2547 
2548  if (awtqs->do_query_pos_fig) {
2549  aws->at(awtqs->do_query_pos_fig);
2550  aws->callback(makeWindowCallback(perform_query_cb, query, EXT_QUERY_NONE));
2551  char *macro_id = GBS_global_string_copy("SEARCH_%s", query_id);
2552  aws->create_button(macro_id, "Search", "S", "+");
2553  free(macro_id);
2554  }
2555  if (awtqs->do_refresh_pos_fig) {
2556  aws->at(awtqs->do_refresh_pos_fig);
2557  aws->create_option_menu(query->awar_sort, true);
2558  aws->insert_default_option("unsorted", "u", QUERY_SORT_NONE);
2559  aws->insert_option ("by value", "v", QUERY_SORT_BY_1STFIELD_CONTENT);
2560  aws->insert_option ("by number", "n", QUERY_SORT_NUM_BY_1STFIELD_CONTENT);
2561  aws->insert_option ("by id", "i", QUERY_SORT_BY_ID);
2562  if (query->selector.parent_selector) {
2563  aws->insert_option ("by parent", "p", QUERY_SORT_BY_NESTED_PID);
2564  }
2565  aws->insert_option ("by marked", "m", QUERY_SORT_BY_MARKED);
2566  aws->insert_option ("by hit", "h", QUERY_SORT_BY_HIT_DESCRIPTION);
2567  aws->insert_option ("reverse", "r", QUERY_SORT_REVERSE);
2568  aws->update_option_menu();
2569  }
2570  else {
2571  dbq_assert(0); // hmm - no sort button here. -> tell ralf where this happens
2572  }
2573 
2574  if (awtqs->do_mark_pos_fig) {
2575  aws->at(awtqs->do_mark_pos_fig);
2576  aws->help_text("mark_list.hlp");
2577  aws->callback(makeWindowCallback(mark_queried_cb, query, 1));
2578  aws->create_button("MARK_LISTED_UNMARK_REST", "Mark Listed\nUnmark Rest", "M");
2579  }
2580  if (awtqs->do_unmark_pos_fig) {
2581  aws->at(awtqs->do_unmark_pos_fig);
2582  aws->help_text("unmark_list.hlp");
2583  aws->callback(makeWindowCallback(mark_queried_cb, query, 0));
2584  aws->create_button("UNMARK_LISTED_MARK_REST", "Unmark Listed\nMark Rest", "U");
2585  }
2586  if (awtqs->do_delete_pos_fig) {
2587  aws->at(awtqs->do_delete_pos_fig);
2588  aws->help_text("del_list.hlp");
2589  aws->callback(makeWindowCallback(delete_queried_species_cb, query));
2590  char *macro_id = GBS_global_string_copy("DELETE_LISTED_%s", query_id);
2591  aws->create_button(macro_id, "Delete Listed", "D");
2592  free(macro_id);
2593  }
2594  if (awtqs->do_set_pos_fig) {
2595  query->awar_writekey = GBS_global_string_copy("tmp/dbquery_%s/write_key", query_id); aw_root->awar_string(query->awar_writekey);
2596  query->awar_writelossy = GBS_global_string_copy("tmp/dbquery_%s/write_lossy", query_id); aw_root->awar_int (query->awar_writelossy);
2597  query->awar_protectkey = GBS_global_string_copy("tmp/dbquery_%s/protect_key", query_id); aw_root->awar_string(query->awar_protectkey);
2598  query->awar_setprotection = GBS_global_string_copy("tmp/dbquery_%s/set_protection", query_id); aw_root->awar_int (query->awar_setprotection, 4);
2599  query->awar_setvalue = GBS_global_string_copy("tmp/dbquery_%s/set_value", query_id); aw_root->awar_string(query->awar_setvalue);
2600 
2601  aws->at(awtqs->do_set_pos_fig);
2602  aws->help_text("mod_field_list.hlp");
2603  aws->callback(makeCreateWindowCallback(create_writeFieldOfListed_window, query));
2604  char *macro_id = GBS_global_string_copy("WRITE_TO_FIELDS_OF_LISTED_%s", query_id);
2605  aws->create_button(macro_id, "Write to Fields\nof Listed", "S");
2606  free(macro_id);
2607  }
2608 
2609  char *Items = strdup(query->selector.items_name);
2610  Items[0] = toupper(Items[0]);
2611 
2612  if ((awtqs->use_menu || awtqs->open_parser_pos_fig)) {
2613  sprintf(buffer, "tmp/dbquery_%s/tag", query_id); query->awar_tag = strdup(buffer); aw_root->awar_string(query->awar_tag);
2614  sprintf(buffer, "tmp/dbquery_%s/use_tag", query_id); query->awar_use_tag = strdup(buffer); aw_root->awar_int (query->awar_use_tag);
2615  sprintf(buffer, "tmp/dbquery_%s/deftag", query_id); query->awar_deftag = strdup(buffer); aw_root->awar_string(query->awar_deftag);
2616  sprintf(buffer, "tmp/dbquery_%s/double_pars", query_id); query->awar_double_pars = strdup(buffer); aw_root->awar_int (query->awar_double_pars);
2617  sprintf(buffer, "tmp/dbquery_%s/parskey", query_id); query->awar_parskey = strdup(buffer); aw_root->awar_string(query->awar_parskey);
2618  sprintf(buffer, "tmp/dbquery_%s/parsvalue", query_id); query->awar_parsvalue = strdup(buffer); aw_root->awar_string(query->awar_parsvalue);
2619  sprintf(buffer, "tmp/dbquery_%s/awar_parspredefined", query_id); query->awar_parspredefined = strdup(buffer); aw_root->awar_string(query->awar_parspredefined);
2620  sprintf(buffer, "tmp/dbquery_%s/acceptConvError", query_id); query->awar_acceptConvError = strdup(buffer); aw_root->awar_int (query->awar_acceptConvError);
2621 
2622  if (awtqs->use_menu) {
2623  sprintf(buffer, "Modify Fields of Listed %s", Items); query_rel_menu_entry(aws, "mod_fields_of_listed", query_id, buffer, "F", "mod_field_list.hlp", AWM_ALL, makeCreateWindowCallback(create_modify_fields_window, query));
2624  }
2625  else {
2626  aws->at(awtqs->open_parser_pos_fig);
2627  aws->callback(makeCreateWindowCallback(create_modify_fields_window, query));
2628  aws->create_button("MODIFY_FIELDS_OF_LISTED", "MODIFY FIELDS\nOF LISTED", "F");
2629  }
2630  }
2631  if (awtqs->use_menu) {
2632  sprintf(buffer, "Set Protection of Fields of Listed %s", Items); query_rel_menu_entry(aws, "s_prot_of_listed", query_id, buffer, "P", "set_protection.hlp", AWM_ALL, makeCreateWindowCallback(create_set_protection_window, query));
2633  aws->sep______________();
2634  sprintf(buffer, "Mark Listed %s, don't Change Rest", Items); query_rel_menu_entry(aws, "mark_listed", query_id, buffer, "M", "mark.hlp", AWM_ALL, makeWindowCallback(mark_queried_cb, query, 1|8));
2635  sprintf(buffer, "Mark Listed %s, Unmark Rest", Items); query_rel_menu_entry(aws, "mark_listed_unmark_rest", query_id, buffer, "L", "mark.hlp", AWM_ALL, makeWindowCallback(mark_queried_cb, query, 1 ));
2636  sprintf(buffer, "Unmark Listed %s, don't Change Rest", Items); query_rel_menu_entry(aws, "unmark_listed", query_id, buffer, "U", "mark.hlp", AWM_ALL, makeWindowCallback(mark_queried_cb, query, 0|8));
2637  sprintf(buffer, "Unmark Listed %s, Mark Rest", Items); query_rel_menu_entry(aws, "unmark_listed_mark_rest", query_id, buffer, "R", "mark.hlp", AWM_ALL, makeWindowCallback(mark_queried_cb, query, 0 ));
2638  aws->sep______________();
2639 
2640 
2641  sprintf(buffer, "Set Color of Listed %s", Items); query_rel_menu_entry(aws, "set_color_of_listed", query_id, buffer, "C", "set_color_of_listed.hlp", AWM_ALL, makeCreateWindowCallback(create_colorize_queried_window, query));
2642 
2643  if (query->gb_ref) {
2644  dbq_assert(speciesOrOrganism(query->selector.type)); // stuff below works only for species/organisms
2645  aws->sep______________();
2646  if (query->expect_hit_in_ref_list) {
2647  aws->insert_menu_topic("search_equal_fields_and_listed_in_I", "Search entries existing in both DBs and listed in the source DB hitlist", "S",
2648  "search_equal_fields.hlp", AWM_ALL, makeWindowCallback(perform_query_cb, query, EXT_QUERY_COMPARE_LINES));
2649  aws->insert_menu_topic("search_equal_words_and_listed_in_I", "Search words existing in entries of both DBs and listed in the source DB hitlist", "w",
2650  "search_equal_fields.hlp", AWM_ALL, makeWindowCallback(perform_query_cb, query, EXT_QUERY_COMPARE_WORDS));
2651  }
2652  else {
2653  aws->insert_menu_topic("search_equal_field_in_both_db", "Search entries existing in both DBs", "S",
2654  "search_equal_fields.hlp", AWM_ALL, makeWindowCallback(perform_query_cb, query, EXT_QUERY_COMPARE_LINES));
2655  aws->insert_menu_topic("search_equal_word_in_both_db", "Search words existing in entries of both DBs", "w",
2656  "search_equal_fields.hlp", AWM_ALL, makeWindowCallback(perform_query_cb, query, EXT_QUERY_COMPARE_WORDS));
2657  }
2658  }
2659  }
2660 
2661  free(Items);
2662 
2663  GB_pop_transaction(gb_main);
2664  return query;
2665 }
2666 
2667 // --------------------------------------------------------------------------------
2668 
2669 #ifdef UNIT_TESTS
2670 #ifndef TEST_UNIT_H
2671 #include <test_unit.h>
2672 #endif
2673 
2674 void TEST_nullcmp() {
2675  const char *whatever = "bla";
2677  TEST_EXPECT_EQUAL(ARB_strNULLcmp(whatever, whatever), 0);
2678  TEST_EXPECT_EQUAL(ARB_strNULLcmp("a", "b"), -1);
2679 
2680  // document uncommon behavior: NULp is bigger than any other text!
2681  TEST_EXPECT_EQUAL(ARB_strNULLcmp(whatever, NULp), -1);
2682  TEST_EXPECT_EQUAL(ARB_strNULLcmp(NULp, whatever), 1);
2683 }
2684 
2685 #endif // UNIT_TESTS
2686 
2687 // --------------------------------------------------------------------------------
2688 
GB_ERROR GB_begin_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2516
void keep(T elem)
Definition: Keeper.h:32
static void mark_colored_cb(AW_window *aww, BoundItemSel *cmd, mark_mode mode)
Definition: db_query.cxx:1562
void insert_option(AW_label choice_label, const char *mnemonic, const char *var_value, const char *name_of_color=NULp)
static GB_ERROR clear_all_colors(BoundItemSel *bsel, AW_root *aw_root)
Definition: db_query.cxx:1668
#define MAX_QUERY_LIST_LEN
Definition: db_query.cxx:43
const char * GB_ERROR
Definition: arb_core.h:25
const char * get_items_name() const
Definition: db_query.cxx:1605
void get_at_position(int *x, int *y) const
Definition: AW_at.cxx:291
AW_bitset AW_active
Definition: aw_base.hxx:45
const char * item_name
Definition: items.h:65
#define PSEUDO_FIELD_ALL_FIELDS_REC
Definition: item_sel_list.h:30
string result
GB_TYPES type
static void toggle_flag_cb(AW_window *aww, DbQuery *query)
Definition: db_query.cxx:2253
void insert_toggle(AW_label toggle_label, const char *mnemonic, const char *var_value)
GB_ERROR GB_commit_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2539
void set_tree_awar_name(const char *tree_awar_name)
bool GB_TYPE_readable_as_string(GB_TYPES type)
Definition: arbdb.h:90
void button_length(int length)
Definition: AW_at.cxx:283
void add(const char *awar_name, const char *config_name)
const char * getHitInfo(const char *item_id, DbQuery *query)
Definition: db_query.cxx:85
size_t size() const
Definition: arb_strarray.h:85
mark_mode
Definition: db_query.cxx:1556
ItemSelector * parent_selector
Definition: items.h:78
GBDATA * GBT_colorset_root(GBDATA *gb_main, const char *itemsname)
Definition: ad_colorset.cxx:52
void d_callback(const WindowCallback &cb)
Definition: AW_window.cxx:138
static QUERY_RESULT_ORDER find_display_determining_sort_order(QUERY_RESULT_ORDER *order)
Definition: db_query.cxx:220
char * awar_writekey
GBDATA * GB_child(GBDATA *father)
Definition: adquery.cxx:322
char * awar_writelossy
GB_ERROR GB_incur_error()
Definition: arb_msg.h:49
char * awar_parsvalue
static void destroyKeptQueries()
Definition: db_query.cxx:2333
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
Definition: adhash.cxx:457
return string(buffer, length)
const char * config_pos_fig
Definition: db_query.h:61
AwarName species_name
Definition: db_query.h:42
void insert_menu_topic(const char *id, const char *name, const char *mnemonic, const char *help_text_, AW_active mask, const WindowCallback &wcb)
Definition: AW_window.cxx:592
void GB_atclose_callback(GBDATA *gbd, const DatabaseCallback &atClose)
Definition: ad_cb.cxx:458
static GB_ERROR restore_colorset_representation(BoundItemSel *bsel, CharPtrArray &colordefs)
Definition: db_query.cxx:1700
static void keepQuery(GBDATA *gbmain, DbQuery *q)
Definition: db_query.cxx:2336
void DbQuery_update_list(DbQuery *query)
Definition: db_query.cxx:485
Definition: AP_filter.hxx:36
void insert_default(const char *displayed, const AW_scalar &value)
Definition: AW_select.cxx:385
GB_ERROR GB_add_callback(GBDATA *gbd, GB_CB_TYPE type, const DatabaseCallback &dbcb)
Definition: ad_cb.cxx:356
#define DOWNCAST_REFERENCE(totype, expr)
Definition: downcast.h:152
static void iterate(GBDATA *gbd)
const char * key_pos_fig
Definition: db_query.h:53
const char * ARB_keep_string(char *str)
Definition: arb_string.cxx:63
void GB_sort(void **array, size_t first, size_t behind_last, gb_compare_function compare, void *client_data)
Definition: arb_sort.cxx:27
bool GB_readable_as_string(GBDATA *gbd)
Definition: arbdb.cxx:1074
#define PSEUDO_FIELD_ALL_FIELDS
Definition: item_sel_list.h:28
GBDATA * query_get_gb_main(DbQuery *query)
Definition: db_query.cxx:106
loadsave_mode
Definition: db_query.cxx:1741
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2549
void at(int x, int y)
Definition: AW_at.cxx:93
static void set_protection_of_queried_cb(AW_window *, DbQuery *query)
Definition: db_query.cxx:2172
static void detectMaxNameLength(const char *key, long, void *cl_len)
Definition: db_query.cxx:462
const char * ere_pos_fig
Definition: db_query.h:48
static void create_colorset_representation(BoundItemSel *bsel, AW_root *aw_root, StrArray &colordefs, GB_ERROR &error)
Definition: db_query.cxx:1638
#define AW_COLOR_GROUPS
void copy_selection_list_2_query_box(DbQuery *query, AW_selection_list *srclist, const char *hit_description)
Definition: db_query.cxx:1130
const char * where_pos_fig
Definition: db_query.h:49
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)
void GB_end_transaction_show_error(GBDATA *gbd, GB_ERROR error, void(*error_handler)(GB_ERROR))
Definition: arbdb.cxx:2572
char * GB_read_as_string(GBDATA *gbd)
Definition: arbdb.cxx:1054
void CLEAR_QUERIED(GBDATA *gb_species, DbQuery *query)
Definition: db_query.cxx:77
static GB_HASH * create_ref_hash(const DbQuery *query, const char *key, bool split_words)
Definition: db_query.cxx:680
long read_int() const
Definition: AW_awar.cxx:187
GBDATA *(* get_parent)(GBDATA *gb_item)
Definition: items.h:79
bool iterate() const OVERRIDE
Definition: db_query.cxx:860
GBDATA * get_first_field(GBDATA *gb_item) const
Definition: db_query.cxx:873
size_t GBS_shorten_repeated_data(char *data)
Definition: adstring.cxx:358
#define QUERY_EXPRESSIONS
DbQuery * create_query_box(AW_window *aws, query_spec *awtqs, const char *query_id)
Definition: db_query.cxx:2346
GBDATA * GBT_find_or_create_colorset(GBDATA *gb_colorset_root, const char *name)
Definition: ad_colorset.cxx:85
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
static int query_count_items(DbQuery *query, QUERY_RANGE range, QUERY_MODES mode)
Definition: db_query.cxx:183
const char * result_pos_fig
Definition: db_query.h:57
void AW_advice(const char *message, AW_Advice_Type type, const char *title, const char *corresponding_help)
Show a message box with an advice for the user.
Definition: AW_advice.cxx:160
GB_HASH * GBS_create_dynaval_hash(long estimated_elements, GB_CASE case_sens, void(*freefun)(long))
Definition: adhash.cxx:271
GBDATA * get_colorset_root(BoundItemSel *bsel)
Definition: db_query.cxx:1612
bool GB_have_error()
Definition: arb_msg.cxx:349
STL namespace.
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
void unquery_all(void *dummy, DbQuery *query)
Definition: db_query.cxx:620
void GBS_strncat(GBS_strstruct *strstr, const char *ptr, size_t len)
Definition: arb_strbuf.cxx:101
void GBS_free_hash(GB_HASH *hs)
Definition: adhash.cxx:541
static void result_sort_order_changed_cb(AW_root *aw_root, DbQuery *query)
Definition: db_query.cxx:268
#define KEY_Y_OFFSET
bool isNull() const
test if SmartPtr is NULp
Definition: smartptr.h:248
static SmartPtr< QueryKeeper > queryKeeper
Definition: db_query.cxx:2332
char * awar_acceptConvError
char * awar_keys[QUERY_EXPRESSIONS]
GB_TYPES first_type
Definition: db_query.cxx:303
static void modify_fields_of_queried_cb(AW_window *, DbQuery *query)
Definition: db_query.cxx:1349
query_operator awarvalue2query_operator(const char *awarvalue)
Definition: db_query.cxx:894
long count_queried_items(DbQuery *query, QUERY_RANGE range)
Definition: db_query.cxx:159
const char * open_parser_pos_fig
Definition: db_query.h:66
const int MAX_CRITERIA
Definition: db_query.cxx:207
ItemQueryKey(GBDATA *gb_main, const char *field_name)
Definition: db_query.cxx:754
void setNull()
set SmartPtr to NULp
Definition: smartptr.h:251
const char * get_tree_name() const
Definition: db_query.cxx:2286
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1720
void update_option_menu()
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2482
bool SLOW_is_pseudo_key(const char *key)
Definition: db_query.cxx:470
int ARB_strNULLcmp(const char *s1, const char *s2)
Definition: arb_str.h:52
EXT_QUERY_TYPES
Definition: db_query.cxx:114
bool empty() const
Definition: arb_strarray.h:86
#define cb(action)
bool speciesOrOrganism(QUERY_ITEM_TYPE type)
Definition: items.h:36
#define NO_FIELD_SELECTED
void update_toggle_field()
GB_ERROR GB_incur_error_if(bool error_may_occur)
Definition: arb_msg.h:56
static void loadsave_colorset_cb(AW_window *aws, BoundItemSel *bsel, loadsave_mode mode)
Definition: db_query.cxx:1748
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:234
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1904
void insert(const char *displayed, const AW_scalar &value)
Definition: AW_select.cxx:380
char * GBS_modify_tagged_string_with_ACI(const char *s, const char *dt, const char *tag, const char *aci, GBL_call_env &env)
Definition: adstring.cxx:750
void create_itemfield_selection_button(AW_window *aws, const FieldSelDef &selDef, const char *at)
TargetItem(const DbQuery &query)
Definition: db_query.cxx:714
NOT4PERL float * GBT_read_float(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:349
void GB_raise_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2743
static AW_window * create_writeFieldOfListed_window(AW_root *aw_root, DbQuery *query)
Definition: db_query.cxx:2139
static void colorset_changed_cb(GBDATA *, const color_save_data *csd, GB_CB_TYPE cbt)
Definition: db_query.cxx:1632
const char * read_char_pntr() const
Definition: AW_awar.cxx:171
char * get_target_data(const QueryTarget &target, GB_ERROR &error) const OVERRIDE
Definition: db_query.cxx:775
bool GB_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2738
QUERY_RESULT_ORDER order[MAX_CRITERIA]
Definition: db_query.cxx:304
GB_ERROR GB_export_error(const char *error)
Definition: arb_msg.cxx:259
char * awar_setprotection
GBS_strstruct * GBS_stropen(long init_size)
Definition: arb_strbuf.cxx:39
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:353
static void first_searchkey_changed_cb(AW_root *, DbQuery *query)
Definition: db_query.cxx:251
NOT4PERL long * GBT_read_int(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:327
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
Definition: arbdb.h:67
Definition: arbdb.h:78
GB_TYPES GB_read_type(GBDATA *gbd)
Definition: arbdb.cxx:1641
static AW_window * create_colorize_queried_window(AW_root *aw_root, DbQuery *query)
Definition: db_query.cxx:1955
GB_HASH * hit_description
GB_CSTR GB_read_key_pntr(GBDATA *gbd)
Definition: arbdb.cxx:1654
void create_toggle_field(const char *awar_name, AW_label label, const char *mnemonic)
bool expect_hit_in_ref_list
QUERY_RESULT_ORDER
AW_selection_list * create_selection_list(const char *awar_name, int columns, int rows, bool fallback2default)
Definition: AW_button.cxx:1212
GB_HASH * to_hash(bool case_sens)
Definition: AW_select.cxx:532
#define PSEUDO_FIELD_ANY_FIELD
Definition: item_sel_list.h:27
GBDATA * get_item() const
Definition: db_query.cxx:723
char * awar_setvalue
GBDATA * gb_species_data
Definition: adname.cxx:34
long GB_number_of_subentries(GBDATA *gbd)
Definition: arbdb.cxx:2880
bool is_pseudo_key(const char *key)
Definition: db_query.cxx:478
const char * GB_first_non_key_char(const char *str)
Definition: adquery.cxx:416
ItemSelector & get_queried_itemtype(DbQuery *query)
Definition: db_query.cxx:110
void GBS_hash_do_const_loop(const GB_HASH *hs, gb_hash_const_loop_type func, void *client_data)
Definition: adhash.cxx:562
GBDATA * gb_ref
Definition: db_query.h:40
int GBT_get_color_group(GBDATA *gb_item)
Definition: ad_colorset.cxx:16
const char * change_key_path
Definition: items.h:64
void init_itemType_specific_window(AW_root *aw_root, class AW_window_simple *aws, const ItemSelector &itemType, const char *id, const char *title_format, bool plural=false)
Definition: itemtools.cxx:32
GBDATA *(* get_selected_item)(GBDATA *gb_main, AW_root *aw_root)
Definition: items.h:75
void aimTo(GBDATA *gb_next_item)
Definition: db_query.cxx:719
string keptHitReason(const string &currentHitReason, GBDATA *gb_item, DbQuery *query)
Definition: db_query.cxx:95
ItemSelector & selector
Definition: items.h:86
int numeric_string_cmp(const char *str1, const char *str2)
Definition: db_query.cxx:318
AW_selection_list * hitlist
static AW_window * create_set_protection_window(AW_root *aw_root, DbQuery *query)
Definition: db_query.cxx:2219
#define false
Definition: ureadseq.h:13
BoundItemSel * bsel
Definition: db_query.cxx:1602
GBDATA * gb_main
GBDATA * get_ACI_item() const OVERRIDE
Definition: db_query.cxx:729
AW_window * aws
CONSTEXPR_INLINE int float_cmp(const float f1, const float f2)
Definition: arbtools.h:189
const char * qbox_pos_fig
Definition: db_query.h:52
void help_text(const char *id)
Definition: AW_window.cxx:113
static char const * macro_name
Definition: mkptypes.cxx:81
DbQuery * query
Definition: db_query.cxx:301
GBDATA *(* get_first_item_container)(GBDATA *, AW_root *, QUERY_RANGE)
Definition: items.h:69
static void error(const char *msg)
Definition: mkptypes.cxx:96
GBDATA *(* get_next_item_container)(GBDATA *, QUERY_RANGE)
Definition: items.h:70
GB_ERROR GB_abort_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2527
void reset() const OVERRIDE
Definition: db_query.cxx:865
void(* trigger_display_refresh)()
Definition: items.h:81
const char * mnemonic
void restore_at_from(const AW_at_storage &stored)
Definition: aw_window.hxx:549
fputc('\n', stderr)
query_key_type
Definition: query_expr.h:81
static void new_selection_made_cb(AW_root *aw_root, const char *awar_selection, DbQuery *query)
Definition: db_query.cxx:2263
ItemSelector & selector
static void colorize_marked_cb(AW_window *aww, BoundItemSel *cmd)
Definition: db_query.cxx:1531
char * awar_operator[QUERY_EXPRESSIONS]
GBQUARK GB_find_or_create_quark(GBDATA *gbd, const char *key)
Definition: arbdb.cxx:1693
#define CHANGEKEY_NAME
Definition: arbdbt.h:91
static void delete_queried_species_cb(AW_window *, DbQuery *query)
Definition: db_query.cxx:632
void label(const char *label)
Definition: AW_window.cxx:102
char * str
Definition: defines.h:20
size_t GBS_hash_elements(const GB_HASH *hs)
Definition: adhash.cxx:573
char * read_as_string() const
GB_ERROR GBT_save_colorset(GBDATA *gb_colorset, CharPtrArray &colorsetDefs)
const char * items_name
Definition: items.h:66
#define MAX_SHOWN_DATA_SIZE
Definition: query_expr.h:62
static void colorize_queried_cb(AW_window *, DbQuery *query)
Definition: db_query.cxx:1503
GB_ERROR GBT_load_colorset(GBDATA *gb_colorset, ConstStrArray &colorsetDefs)
Definition: ad_colorset.cxx:94
const char * count_pos_fig
Definition: db_query.h:58
GBDATA * GB_find_sub_by_quark(GBDATA *father, GBQUARK key_quark, GBDATA *after, size_t skip_over)
Definition: adquery.cxx:174
static AW_window * create_colorize_window(AW_root *aw_root, GBDATA *gb_main, DbQuery *query, ItemSelector *sel)
Definition: db_query.cxx:1858
int item_name_length
Definition: items.h:62
#define cmp(h1, h2)
Definition: admap.cxx:50
static void free_hit_description(long info)
Definition: db_query.cxx:47
#define AWAR_COLOR_LOADSAVE_NAME
Definition: db_query.cxx:1610
const char * by_pos_fig
Definition: db_query.h:50
const char * prepare_and_get_selected_itemfield(AW_root *awr, const char *awar_name, GBDATA *gb_main, const ItemSelector &itemtype, FailIfField failIf)
int GB_read_flag(GBDATA *gbd)
Definition: arbdb.cxx:2784
char *(* generate_item_id)(GBDATA *gb_main, GBDATA *gb_item)
Definition: items.h:58
char * read_string() const
Definition: AW_awar.cxx:201
static void create_query_independent_awars(AW_root *aw_root, AW_default aw_def)
Definition: db_query.cxx:102
GB_CSTR GB_path_in_ARBLIB(const char *relative_path)
Definition: adsocket.cxx:1124
GB_ERROR GB_write_security_write(GBDATA *gbd, unsigned long level)
Definition: arbdb.cxx:1582
static WindowCallback simple(void(*root_cb)(AW_root *, T), T t)
Definition: rootAsWin.h:47
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2512
GB_TYPES GBT_get_type_of_changekey(GBDATA *gb_main, const char *field_name, const char *change_key_path)
Definition: adChangeKey.cxx:34
AW_selection_list * colorsets
Definition: db_query.cxx:1603
bool expect_hit_in_ref_list
Definition: db_query.h:41
Definition: arbdb.h:86
#define AWAR_COLORIZE
Definition: db_query.cxx:45
GBDATA *(* get_first_item)(GBDATA *, QUERY_RANGE)
Definition: items.h:72
AW_option_menu_struct * create_option_menu(const char *awar_name, bool fallback2default)
void search_duplicated_field_content(AW_window *dummy, DbQuery *query, bool tokenize)
Definition: db_query.cxx:1194
char * awar_parspredefined
static void clear_all_colors_cb(AW_window *aww, BoundItemSel *bsel)
Definition: db_query.cxx:1690
void append(QueryExpr *&tail)
Definition: query_expr.cxx:46
Definition: db_query.h:24
static AW_at_storage * make(AW_window *aww, AW_at_storage_type type)
Definition: AW_at.cxx:444
AW_selection_list * awt_create_selection_list_with_input_field(AW_window *aww, const char *awar_name, const char *at_box, const char *at_field)
void insert_default_option(AW_label choice_label, const char *mnemonic, const char *var_value, const char *name_of_color=NULp)
QUERY_RANGE
Definition: items.h:40
char * awar_not[QUERY_EXPRESSIONS]
static void query_rel_menu_entry(AW_window *aws, const char *id, const char *query_id, const char *label, const char *mnemonic, const char *helpText, AW_active Mask, const CB &cb)
Definition: db_query.cxx:2280
TYPE get_type() const
Definition: probe_tree.h:64
QUERY_ITEM_TYPE
Definition: items.h:27
long int flag
Definition: f2c.h:39
GBDATA * GBT_searchOrCreate_itemfield_according_to_changekey(GBDATA *gb_item, const char *field_name, const char *change_key_path)
Definition: adChangeKey.cxx:62
GBDATA *(* get_next_item)(GBDATA *, QUERY_RANGE)
Definition: items.h:73
SmartPtr< QueryExpr > buildQueryExpr()
Definition: db_query.cxx:900
static void remove_keydependent_sort_criteria(QUERY_RESULT_ORDER *order)
Definition: db_query.cxx:237
bool aw_ask_sure(const char *unique_id, const char *msg)
void(* update_item_awars)(GBDATA *gb_main, AW_root *aw_root, const char *item_name)
Definition: items.h:57
static void split_sort_mask(unsigned long sort_mask, QUERY_RESULT_ORDER *order)
Definition: db_query.cxx:209
TokLPtr tokenize(const std::string &description, TokLPtr tokenLP)
void create_input_field(const char *awar_name, int columns=0)
Definition: AW_button.cxx:855
const char * get_name() const OVERRIDE
Definition: db_query.cxx:801
fputs(TRACE_PREFIX, stderr)
static void setup_modify_fields_config(AWT_config_definition &cdef, const DbQuery *query)
Definition: db_query.cxx:1963
AW_window * create_colorize_items_window(AW_root *aw_root, GBDATA *gb_main, ItemSelector &sel)
Definition: db_query.cxx:1959
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
TYPE * ARB_calloc(size_t nelem)
Definition: arb_mem.h:81
void auto_space(int xspace, int yspace)
Definition: AW_at.cxx:259
static void query_box_setup_config(AWT_config_definition &cdef, DbQuery *query)
Definition: db_query.cxx:2269
popup_info_window_cb popup_info_window
Definition: db_query.h:69
#define gb_assert(cond)
Definition: arbdbt.h:11
xml element
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:32
void GB_write_flag(GBDATA *gbd, long flag)
Definition: arbdb.cxx:2761
void SET_QUERIED(GBDATA *gb_species, DbQuery *query, const char *hitInfo, size_t hitInfoLen=0)
Definition: db_query.cxx:51
#define QUERY_SORT_CRITERIA_MASK
#define OVERRIDE
Definition: cxxforward.h:93
const char * do_mark_pos_fig
Definition: db_query.h:62
bool IS_QUERIED(GBDATA *gb_item, const query_spec *aqs)
Definition: db_query.h:84
Itemfield_Selection * create_itemfield_selection_list(AW_window *aws, const FieldSelDef &selDef, const char *at)
GB_ERROR GB_failedTo_error(const char *do_something, const char *special, GB_ERROR error)
Definition: arb_msg.cxx:387
bool matches(const QueryTarget &target, std::string &hit_reason) const
Definition: query_expr.cxx:277
unsigned long sort_mask
char * AW_get_color_group_name(AW_root *awr, int color_group)
Definition: AW_preset.cxx:1173
char * GBS_strclose(GBS_strstruct *strstr)
Definition: arb_strbuf.cxx:69
#define QUERY_SORT_CRITERIA_BITS
GBDATA * GBT_first_species(GBDATA *gb_main)
Definition: aditem.cxx:124
char * GBT_read_as_string(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:290
GBDATA * gb_main
Definition: items.h:85
query_operator
Definition: query_expr.h:64
GB_ERROR GB_write_security_delete(GBDATA *gbd, unsigned long level)
Definition: arbdb.cxx:1603
static void update_colorset_selection_list(const color_save_data *csd)
Definition: db_query.cxx:1616
void negate()
Definition: query_expr.cxx:56
const char * query_pos_fig
Definition: db_query.h:54
const char * GB_get_db_path(GBDATA *gbd)
Definition: adTest.cxx:14
#define dbq_assert(cond)
void aw_message(const char *msg)
Definition: AW_status.cxx:932
const char * do_query_pos_fig
Definition: db_query.h:60
GBDATA * GBT_find_colorset(GBDATA *gb_colorset_root, const char *name)
Definition: ad_colorset.cxx:76
void GB_clear_user_flag(GBDATA *gbd, unsigned char user_bit)
Definition: arbdb.cxx:2748
Definition: Keeper.h:19
GBDATA * GB_find_string(GBDATA *gbd, const char *key, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:302
query_key_type get_key_type() const
Definition: query_expr.h:200
AW_root * get_root()
Definition: aw_window.hxx:348
Keeper< DbQuery * > QueryKeeper
Definition: db_query.cxx:2330
static int compare_hits(const void *cl_item1, const void *cl_item2, void *cl_param)
Definition: db_query.cxx:349
static int line
Definition: arb_a2ps.c:296
GBDATA * GBT_next_species(GBDATA *gb_species)
Definition: aditem.cxx:128
#define NULp
Definition: cxxforward.h:97
GBDATA *(* find_item_by_id)(GBDATA *gb_main, const char *id)
Definition: items.h:59
GB_ERROR getError(int count=0) const
Definition: query_expr.cxx:77
GB_ERROR write_string(const char *aw_string)
static char * command
Definition: arb_a2ps.c:319
char * GBT_get_default_alignment(GBDATA *gb_main)
Definition: adali.cxx:675
void sep______________()
Definition: AW_window.cxx:750
#define GB_USERFLAG_QUERY
Definition: arbdb.h:55
static void predef_prg(AW_root *aw_root, DbQuery *query)
Definition: db_query.cxx:1481
NOT4PERL char * GB_command_interpreter_in_env(const char *str, const char *commands, const GBL_call_env &callEnv)
Definition: gb_aci.cxx:361
GB_TYPES
Definition: arbdb.h:62
GBDATA * GB_nextChild(GBDATA *child)
Definition: adquery.cxx:326
bool keep_criteria(QUERY_RESULT_ORDER old_criteria, QUERY_RESULT_ORDER new_criteria)
Definition: db_query.cxx:261
void GBT_get_colorset_names(ConstStrArray &colorsetNames, GBDATA *gb_colorset_root)
Definition: ad_colorset.cxx:62
long GBT_get_species_count(GBDATA *gb_main)
Definition: aditem.cxx:207
static void perform_query_cb(AW_window *, DbQuery *query, EXT_QUERY_TYPES ext_query)
Definition: db_query.cxx:929
GB_ERROR load(const char *filemask, bool append) const
char * awar_protectkey
GB_transaction ta(gb_var)
void callback(const WindowCallback &cb)
Definition: AW_window.cxx:130
void setError(GB_ERROR error_) const
Definition: query_expr.h:210
GBDATA * gb_main
Definition: db_query.h:39
GBDATA * gb_main
Definition: adname.cxx:33
hits_sort_params(DbQuery *q, const char *fk)
Definition: db_query.cxx:306
ItemSelector & get_queried_itemtype() const
Definition: db_query.h:37
bool is_queried(GBDATA *gb_item) const
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
GB_ERROR GBT_set_color_group(GBDATA *gb_item, int color_group)
Definition: ad_colorset.cxx:31
QueryKey & get_key()
Definition: query_expr.h:202
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
Definition: adquery.cxx:531
GB_CSTR GBT_get_name_or_description(GBDATA *gb_item)
Definition: aditem.cxx:441
static AW_window * create_modify_fields_window(AW_root *aw_root, DbQuery *query)
Definition: db_query.cxx:1977
const char * do_set_pos_fig
Definition: db_query.h:65
GB_CB_TYPE
Definition: arbdb_base.h:46
static int info[maxsites+1]
CONSTEXPR_INLINE int double_cmp(const double d1, const double d2)
Definition: arbtools.h:182
const char * GBT_read_char_pntr(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:307
bool is_queried(GBDATA *gb_item) const
Definition: db_query.cxx:151
char * awar_double_pars
AwarName tree_name
Definition: db_query.h:43
#define AW_ROOT_DEFAULT
Definition: aw_base.hxx:106
static void set_field_of_queried_cb(AW_window *, DbQuery *query, bool append)
Definition: db_query.cxx:2057
char * awar_queries[QUERY_EXPRESSIONS]
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1283
GB_ERROR write_int(long aw_int)
const MutableBoundItemSel BoundItemSel
Definition: items.h:105
static AW_window * create_loadsave_colored_window(AW_root *aw_root, color_save_data *csd)
Definition: db_query.cxx:1800
long GBS_read_hash(const GB_HASH *hs, const char *key)
Definition: adhash.cxx:395
void inc_and_check_user_abort(GB_ERROR &error)
Definition: arb_progress.h:274
static void mark_queried_cb(AW_window *, DbQuery *query, int mark)
Definition: db_query.cxx:591
#define PSEUDO_FIELD_ANY_FIELD_REC
Definition: item_sel_list.h:29
const char * do_delete_pos_fig
Definition: db_query.h:64
void aw_message_if(GB_ERROR error)
Definition: aw_msg.hxx:21
CONSTEXPR long FIELD_FILTER_STRING_READABLE
Definition: item_sel_list.h:47
const char * do_unmark_pos_fig
Definition: db_query.h:63
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:195
const char * do_refresh_pos_fig
Definition: db_query.h:67
const char * id_field
Definition: items.h:67
QUERY_ITEM_TYPE type
Definition: items.h:50
CONSTEXPR long FIELD_UNFILTERED
Definition: item_sel_list.h:49
const char * label
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)
Definition: adhash.cxx:253
void create_button(const char *macro_name, AW_label label, const char *mnemonic=NULp, const char *color=NULp)
Definition: AW_button.cxx:446
Definition: arbdb.h:66
CONSTEXPR_INLINE int long_cmp(const long L1, const long L2)
Definition: arbtools.h:196
const char * get_itemfield_type_awarname(const char *itemfield_awarname)
GBDATA * GBT_get_species_data(GBDATA *gb_main)
Definition: aditem.cxx:105
GB_ERROR GB_write_autoconv_string(GBDATA *gbd, const char *val)
Definition: arbdb.cxx:1477
GB_write_int const char s
Definition: AW_awar.cxx:156