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