| 1 | #include <stdio.h> |
|---|
| 2 | #include <stdlib.h> |
|---|
| 3 | #include <unistd.h> |
|---|
| 4 | #include <time.h> |
|---|
| 5 | #include <string.h> |
|---|
| 6 | // #include <malloc.h> |
|---|
| 7 | #include <memory.h> |
|---|
| 8 | #include <ctype.h> |
|---|
| 9 | |
|---|
| 10 | #include <list> |
|---|
| 11 | #include <string> |
|---|
| 12 | |
|---|
| 13 | #include <arbdb.h> |
|---|
| 14 | #include <arbdbt.h> |
|---|
| 15 | #include <aw_root.hxx> |
|---|
| 16 | #include <aw_device.hxx> |
|---|
| 17 | #include <aw_window.hxx> |
|---|
| 18 | #include <aw_awars.hxx> |
|---|
| 19 | #include <aw_preset.hxx> |
|---|
| 20 | #include <aw_color_groups.hxx> |
|---|
| 21 | #include "awt.hxx" |
|---|
| 22 | #include "awtlocal.hxx" |
|---|
| 23 | #include "awt_config_manager.hxx" |
|---|
| 24 | #include "awt_item_sel_list.hxx" |
|---|
| 25 | #include "awt_sel_boxes.hxx" |
|---|
| 26 | #include "awt_advice.hxx" |
|---|
| 27 | |
|---|
| 28 | #include "GEN.hxx" |
|---|
| 29 | |
|---|
| 30 | using namespace std; |
|---|
| 31 | |
|---|
| 32 | #define AWT_MAX_QUERY_LIST_LEN 100000 |
|---|
| 33 | #define AWT_MAX_SHOWN_DATA_SIZE 500 |
|---|
| 34 | |
|---|
| 35 | /***************** Create the database query box and functions *************************/ |
|---|
| 36 | |
|---|
| 37 | #define AWAR_COLORIZE "tmp/dbquery_all/colorize" |
|---|
| 38 | |
|---|
| 39 | inline void SET_QUERIED(GBDATA *gb_species, adaqbsstruct *cbs, const char *hitInfo, size_t hitInfoLen = 0) { |
|---|
| 40 | awt_assert(hitInfo); |
|---|
| 41 | |
|---|
| 42 | GB_write_usr_private(gb_species, cbs->select_bit | GB_read_usr_private(gb_species)); |
|---|
| 43 | |
|---|
| 44 | char *name = cbs->selector->generate_item_id(cbs->gb_main, gb_species); |
|---|
| 45 | char *info; |
|---|
| 46 | |
|---|
| 47 | if (hitInfoLen == 0) hitInfoLen = strlen(hitInfo); |
|---|
| 48 | if (hitInfoLen>AWT_MAX_SHOWN_DATA_SIZE) { |
|---|
| 49 | char *dupInfo = strdup(hitInfo); |
|---|
| 50 | hitInfoLen = GBS_shorten_repeated_data(dupInfo); |
|---|
| 51 | if (hitInfoLen>AWT_MAX_SHOWN_DATA_SIZE) { |
|---|
| 52 | strcpy(dupInfo+hitInfoLen-5, "[...]"); |
|---|
| 53 | } |
|---|
| 54 | info = strdup(dupInfo); |
|---|
| 55 | free(dupInfo); |
|---|
| 56 | } |
|---|
| 57 | else { |
|---|
| 58 | info = strdup(hitInfo); |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | long toFree = GBS_write_hash(cbs->hit_description, name, reinterpret_cast<long>(info)); |
|---|
| 62 | if (toFree) free(reinterpret_cast<char*>(toFree)); // free old value (from hash) |
|---|
| 63 | free(name); |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | inline void CLEAR_QUERIED(GBDATA *gb_species, adaqbsstruct *cbs) { |
|---|
| 67 | GB_write_usr_private(gb_species, (~cbs->select_bit) & GB_read_usr_private(gb_species)); |
|---|
| 68 | |
|---|
| 69 | char *name = cbs->selector->generate_item_id(cbs->gb_main, gb_species); |
|---|
| 70 | long toFree = GBS_write_hash(cbs->hit_description, name, 0); // delete hit info |
|---|
| 71 | if (toFree) free(reinterpret_cast<char*>(toFree)); |
|---|
| 72 | free(name); |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | inline const char *getHitInfo(GBDATA *gb_species, adaqbsstruct *cbs) { |
|---|
| 76 | char *name = cbs->selector->generate_item_id(cbs->gb_main, gb_species); |
|---|
| 77 | long info = GBS_read_hash(cbs->hit_description, name); |
|---|
| 78 | free(name); |
|---|
| 79 | return reinterpret_cast<const char*>(info); |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | static void awt_query_create_global_awars(AW_root *aw_root, AW_default aw_def) { |
|---|
| 83 | aw_root->awar_int(AWAR_COLORIZE, 0, aw_def); |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | enum AWT_EXT_QUERY_TYPES { |
|---|
| 87 | AWT_EXT_QUERY_NONE, |
|---|
| 88 | AWT_EXT_QUERY_COMPARE_LINES, |
|---|
| 89 | AWT_EXT_QUERY_COMPARE_WORDS |
|---|
| 90 | }; |
|---|
| 91 | |
|---|
| 92 | awt_query_struct::awt_query_struct(void){ |
|---|
| 93 | memset((char *)this,0,sizeof(awt_query_struct)); |
|---|
| 94 | select_bit = 1; |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | long awt_count_queried_items(struct adaqbsstruct *cbs, AWT_QUERY_RANGE range) { |
|---|
| 98 | GBDATA *gb_main = cbs->gb_main; |
|---|
| 99 | const ad_item_selector *selector = cbs->selector; |
|---|
| 100 | |
|---|
| 101 | long count = 0; |
|---|
| 102 | |
|---|
| 103 | for (GBDATA *gb_item_container = selector->get_first_item_container(gb_main, cbs->aws->get_root(), range); |
|---|
| 104 | gb_item_container; |
|---|
| 105 | gb_item_container = selector->get_next_item_container(gb_item_container, range)) |
|---|
| 106 | { |
|---|
| 107 | for (GBDATA *gb_item = selector->get_first_item(gb_item_container); |
|---|
| 108 | gb_item; |
|---|
| 109 | gb_item = selector->get_next_item(gb_item)) |
|---|
| 110 | { |
|---|
| 111 | if (IS_QUERIED(gb_item,cbs)) count++; |
|---|
| 112 | } |
|---|
| 113 | } |
|---|
| 114 | return count; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | #if defined(DEVEL_RALF) |
|---|
| 118 | #warning replace awt_count_items by "method" of selector |
|---|
| 119 | #endif // DEVEL_RALF |
|---|
| 120 | |
|---|
| 121 | static int awt_count_items(struct adaqbsstruct *cbs, AWT_QUERY_RANGE range) { |
|---|
| 122 | int count = 0; |
|---|
| 123 | GBDATA *gb_main = cbs->gb_main; |
|---|
| 124 | const ad_item_selector *selector = cbs->selector; |
|---|
| 125 | GB_transaction ta(gb_main); |
|---|
| 126 | |
|---|
| 127 | for (GBDATA *gb_item_container = selector->get_first_item_container(gb_main, cbs->aws->get_root(), range); |
|---|
| 128 | gb_item_container; |
|---|
| 129 | gb_item_container = selector->get_next_item_container(gb_item_container, range)) |
|---|
| 130 | { |
|---|
| 131 | for (GBDATA *gb_item = selector->get_first_item(gb_item_container); |
|---|
| 132 | gb_item; |
|---|
| 133 | gb_item = selector->get_next_item(gb_item)) |
|---|
| 134 | { |
|---|
| 135 | count++; |
|---|
| 136 | } |
|---|
| 137 | } |
|---|
| 138 | return count; |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | const int MAX_CRITERIA = int(sizeof(unsigned long)*8/AWT_QUERY_SORT_CRITERIA_BITS); |
|---|
| 142 | |
|---|
| 143 | static AWT_QUERY_RESULT_ORDER split_sort_mask(unsigned long sort_mask, AWT_QUERY_RESULT_ORDER *order) { |
|---|
| 144 | // splits the sort order bit mask 'sort_mask' into single sort criteria |
|---|
| 145 | // (order[0] contains the primary sort criteria) |
|---|
| 146 | // |
|---|
| 147 | // Returns the first criteria matching |
|---|
| 148 | // AWT_QUERY_SORT_BY_1STFIELD_CONTENT or AWT_QUERY_SORT_BY_HIT_DESCRIPTION |
|---|
| 149 | // (or AWT_QUERY_SORT_NONE if no sort order defined) |
|---|
| 150 | |
|---|
| 151 | AWT_QUERY_RESULT_ORDER first = AWT_QUERY_SORT_NONE; |
|---|
| 152 | |
|---|
| 153 | for (int o = 0; o<MAX_CRITERIA; o++) { |
|---|
| 154 | order[o] = AWT_QUERY_RESULT_ORDER(sort_mask&AWT_QUERY_SORT_CRITERIA_MASK); |
|---|
| 155 | awt_assert(order[o] == (order[o]&AWT_QUERY_SORT_CRITERIA_MASK)); |
|---|
| 156 | |
|---|
| 157 | if (first == AWT_QUERY_SORT_NONE) { |
|---|
| 158 | if (order[o] & (AWT_QUERY_SORT_BY_1STFIELD_CONTENT|AWT_QUERY_SORT_BY_HIT_DESCRIPTION)) { |
|---|
| 159 | first = order[o]; |
|---|
| 160 | } |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | sort_mask = sort_mask>>AWT_QUERY_SORT_CRITERIA_BITS; |
|---|
| 164 | } |
|---|
| 165 | return first; |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | static void awt_first_searchkey_changed_cb(AW_root *, AW_CL cl_cbs) { |
|---|
| 169 | struct adaqbsstruct *cbs = reinterpret_cast<struct adaqbsstruct*>(cl_cbs); |
|---|
| 170 | |
|---|
| 171 | AWT_QUERY_RESULT_ORDER order[MAX_CRITERIA]; |
|---|
| 172 | AWT_QUERY_RESULT_ORDER first = split_sort_mask(cbs->sort_mask, order); |
|---|
| 173 | |
|---|
| 174 | if (first != AWT_QUERY_SORT_BY_HIT_DESCRIPTION) { // do we display values? |
|---|
| 175 | awt_query_update_list(NULL, cbs); |
|---|
| 176 | } |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | inline bool keep_criteria(AWT_QUERY_RESULT_ORDER old_criteria, AWT_QUERY_RESULT_ORDER new_criteria) { |
|---|
| 180 | return |
|---|
| 181 | old_criteria != AWT_QUERY_SORT_NONE && // do not keep 'unsorted' (it is no real criteria) |
|---|
| 182 | (old_criteria != new_criteria || // do not keep new criteria (added later) |
|---|
| 183 | old_criteria == AWT_QUERY_SORT_REVERSE); // reverse may occur several times -> always keep |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | static void awt_sort_order_changed_cb(AW_root *aw_root, AW_CL cl_cbs) { |
|---|
| 187 | // adds the new selected sort order to the sort order mask |
|---|
| 188 | // (removes itself, if previously existed in sort order mask) |
|---|
| 189 | // |
|---|
| 190 | // if 'unsorted' is selected -> delete sort order |
|---|
| 191 | |
|---|
| 192 | struct adaqbsstruct *cbs = reinterpret_cast<struct adaqbsstruct*>(cl_cbs); |
|---|
| 193 | AWT_QUERY_RESULT_ORDER new_criteria = (AWT_QUERY_RESULT_ORDER)aw_root->awar(cbs->awar_sort)->read_int(); |
|---|
| 194 | |
|---|
| 195 | if (new_criteria == AWT_QUERY_SORT_NONE) { |
|---|
| 196 | cbs->sort_mask = AWT_QUERY_SORT_NONE; // clear sort_mask |
|---|
| 197 | } |
|---|
| 198 | else { |
|---|
| 199 | AWT_QUERY_RESULT_ORDER order[MAX_CRITERIA]; |
|---|
| 200 | split_sort_mask(cbs->sort_mask, order); |
|---|
| 201 | |
|---|
| 202 | int empty_or_same = 0; |
|---|
| 203 | for (int o = 0; o<MAX_CRITERIA; o++) { |
|---|
| 204 | if (!keep_criteria(order[o], new_criteria)) { |
|---|
| 205 | empty_or_same++; // these criteria will be skipped below |
|---|
| 206 | } |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | unsigned long new_sort_mask = 0; |
|---|
| 210 | for (int o = MAX_CRITERIA-(empty_or_same>0 ? 1 : 2); o >= 0; o--) { |
|---|
| 211 | if (keep_criteria(order[o], new_criteria)) { |
|---|
| 212 | new_sort_mask = (new_sort_mask<<AWT_QUERY_SORT_CRITERIA_BITS)|order[o]; |
|---|
| 213 | } |
|---|
| 214 | } |
|---|
| 215 | cbs->sort_mask = (new_sort_mask<<AWT_QUERY_SORT_CRITERIA_BITS)|new_criteria; // add new primary key |
|---|
| 216 | } |
|---|
| 217 | awt_query_update_list(NULL, cbs); |
|---|
| 218 | } |
|---|
| 219 | |
|---|
| 220 | struct awt_sort_query_hits_param { |
|---|
| 221 | struct adaqbsstruct *cbs; |
|---|
| 222 | char *first_key; |
|---|
| 223 | AWT_QUERY_RESULT_ORDER order[MAX_CRITERIA]; |
|---|
| 224 | }; |
|---|
| 225 | |
|---|
| 226 | inline int strNULLcmp(const char *str1, const char *str2) { |
|---|
| 227 | return |
|---|
| 228 | str1 |
|---|
| 229 | ? (str2 ? strcmp(str1, str2) : -1) |
|---|
| 230 | : (str2 ? 1 : 0); |
|---|
| 231 | } |
|---|
| 232 | |
|---|
| 233 | static int awt_sort_query_hits(const void *cl_item1, const void *cl_item2, void *cl_param) { |
|---|
| 234 | awt_sort_query_hits_param *param = static_cast<awt_sort_query_hits_param*>(cl_param); |
|---|
| 235 | |
|---|
| 236 | GBDATA *gb_item1 = (GBDATA*)cl_item1; |
|---|
| 237 | GBDATA *gb_item2 = (GBDATA*)cl_item2; |
|---|
| 238 | |
|---|
| 239 | struct adaqbsstruct *cbs = param->cbs; |
|---|
| 240 | const ad_item_selector *selector = cbs->selector; |
|---|
| 241 | |
|---|
| 242 | int cmp = 0; |
|---|
| 243 | |
|---|
| 244 | for (int o = 0; o<MAX_CRITERIA && cmp == 0; o++) { |
|---|
| 245 | AWT_QUERY_RESULT_ORDER criteria = param->order[o]; |
|---|
| 246 | |
|---|
| 247 | switch (criteria) { |
|---|
| 248 | case AWT_QUERY_SORT_NONE: |
|---|
| 249 | o = MAX_CRITERIA; // don't sort further |
|---|
| 250 | break; |
|---|
| 251 | |
|---|
| 252 | case AWT_QUERY_SORT_BY_1STFIELD_CONTENT: { |
|---|
| 253 | char *field1 = GBT_read_as_string(gb_item1, param->first_key); |
|---|
| 254 | char *field2 = GBT_read_as_string(gb_item2, param->first_key); |
|---|
| 255 | |
|---|
| 256 | cmp = strNULLcmp(field1, field2); |
|---|
| 257 | |
|---|
| 258 | free(field2); |
|---|
| 259 | free(field1); |
|---|
| 260 | break; |
|---|
| 261 | } |
|---|
| 262 | case AWT_QUERY_SORT_BY_NESTED_PID: { |
|---|
| 263 | if (selector->parent_selector) { |
|---|
| 264 | GBDATA *gb_parent1 = selector->get_parent(gb_item1); |
|---|
| 265 | GBDATA *gb_parent2 = selector->get_parent(gb_item2); |
|---|
| 266 | char *pid1 = AWT_get_item_id(cbs->gb_main, selector, gb_parent1); |
|---|
| 267 | char *pid2 = AWT_get_item_id(cbs->gb_main, selector, gb_parent2); |
|---|
| 268 | |
|---|
| 269 | cmp = strNULLcmp(pid1, pid2); |
|---|
| 270 | |
|---|
| 271 | free(pid2); |
|---|
| 272 | free(pid1); |
|---|
| 273 | } |
|---|
| 274 | break; |
|---|
| 275 | } |
|---|
| 276 | case AWT_QUERY_SORT_BY_ID: { |
|---|
| 277 | const char *id1 = GBT_read_char_pntr(gb_item1, selector->id_field); |
|---|
| 278 | const char *id2 = GBT_read_char_pntr(gb_item2, selector->id_field); |
|---|
| 279 | |
|---|
| 280 | cmp = strcmp(id1, id2); |
|---|
| 281 | break; |
|---|
| 282 | } |
|---|
| 283 | case AWT_QUERY_SORT_BY_MARKED: |
|---|
| 284 | cmp = GB_read_flag(gb_item2)-GB_read_flag(gb_item1); |
|---|
| 285 | break; |
|---|
| 286 | |
|---|
| 287 | case AWT_QUERY_SORT_BY_HIT_DESCRIPTION: { |
|---|
| 288 | const char *id1 = GBT_read_char_pntr(gb_item1, selector->id_field); |
|---|
| 289 | const char *id2 = GBT_read_char_pntr(gb_item2, selector->id_field); |
|---|
| 290 | const char *info1 = reinterpret_cast<const char *>(GBS_read_hash(cbs->hit_description, id1)); |
|---|
| 291 | const char *info2 = reinterpret_cast<const char *>(GBS_read_hash(cbs->hit_description, id2)); |
|---|
| 292 | cmp = strNULLcmp(info1, info2); |
|---|
| 293 | break; |
|---|
| 294 | } |
|---|
| 295 | case AWT_QUERY_SORT_REVERSE: { |
|---|
| 296 | GBDATA *tmp = gb_item1; // swap items for following compares (this is a prefix revert!) |
|---|
| 297 | gb_item1 = gb_item2; |
|---|
| 298 | gb_item2 = tmp;; |
|---|
| 299 | break; |
|---|
| 300 | } |
|---|
| 301 | } |
|---|
| 302 | } |
|---|
| 303 | |
|---|
| 304 | return cmp; |
|---|
| 305 | } |
|---|
| 306 | |
|---|
| 307 | static long detectMaxNameLength(const char *key, long val, void *cl_len) { |
|---|
| 308 | int *len = (int*)cl_len; |
|---|
| 309 | int klen = strlen(key); |
|---|
| 310 | |
|---|
| 311 | if (klen>*len) *len = klen; |
|---|
| 312 | return val; |
|---|
| 313 | } |
|---|
| 314 | |
|---|
| 315 | long awt_query_update_list(void *dummy, struct adaqbsstruct *cbs) { |
|---|
| 316 | AWUSE(dummy); |
|---|
| 317 | GB_push_transaction(cbs->gb_main); |
|---|
| 318 | |
|---|
| 319 | // clear |
|---|
| 320 | cbs->aws->clear_selection_list(cbs->result_id); |
|---|
| 321 | |
|---|
| 322 | AW_root *aw_root = cbs->aws->get_root(); |
|---|
| 323 | AWT_QUERY_RANGE range = (AWT_QUERY_RANGE)aw_root->awar(cbs->awar_where)->read_int(); |
|---|
| 324 | |
|---|
| 325 | // create array of hits |
|---|
| 326 | long count = awt_count_queried_items(cbs, range); |
|---|
| 327 | GBDATA **sorted = static_cast<GBDATA**>(malloc(count*sizeof(*sorted))); |
|---|
| 328 | { |
|---|
| 329 | long s = 0; |
|---|
| 330 | |
|---|
| 331 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, aw_root, range); |
|---|
| 332 | gb_item_container; |
|---|
| 333 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 334 | { |
|---|
| 335 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 336 | gb_item; |
|---|
| 337 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 338 | { |
|---|
| 339 | if (IS_QUERIED(gb_item,cbs)) sorted[s++] = gb_item; |
|---|
| 340 | } |
|---|
| 341 | } |
|---|
| 342 | } |
|---|
| 343 | |
|---|
| 344 | // sort hits |
|---|
| 345 | |
|---|
| 346 | bool show_value = true; // default |
|---|
| 347 | awt_sort_query_hits_param param = { cbs, NULL, {} }; |
|---|
| 348 | param.first_key = cbs->aws->get_root()->awar(cbs->awar_keys[0])->read_string(); |
|---|
| 349 | |
|---|
| 350 | if (cbs->sort_mask != AWT_QUERY_SORT_NONE) { // unsorted -> don't sort |
|---|
| 351 | AWT_QUERY_RESULT_ORDER main_criteria = split_sort_mask(cbs->sort_mask, param.order); |
|---|
| 352 | |
|---|
| 353 | if (main_criteria == AWT_QUERY_SORT_BY_HIT_DESCRIPTION) { |
|---|
| 354 | show_value = false; |
|---|
| 355 | } |
|---|
| 356 | GB_sort((void**)sorted, 0, count, awt_sort_query_hits, ¶m); |
|---|
| 357 | } |
|---|
| 358 | |
|---|
| 359 | // display hits |
|---|
| 360 | |
|---|
| 361 | int name_len = cbs->selector->item_name_length; |
|---|
| 362 | if (name_len == -1) { // if name_len is unknown -> detect |
|---|
| 363 | GBS_hash_do_loop(cbs->hit_description, detectMaxNameLength, &name_len); |
|---|
| 364 | } |
|---|
| 365 | |
|---|
| 366 | long i; |
|---|
| 367 | for (i = 0; i<count && i<AWT_MAX_QUERY_LIST_LEN; i++) { |
|---|
| 368 | char *name = cbs->selector->generate_item_id(cbs->gb_main, sorted[i]); |
|---|
| 369 | if (name) { |
|---|
| 370 | char *toFree = 0; |
|---|
| 371 | const char *info; |
|---|
| 372 | |
|---|
| 373 | if (show_value) { |
|---|
| 374 | toFree = GBT_read_as_string(sorted[i], param.first_key); |
|---|
| 375 | if (toFree) { |
|---|
| 376 | if (strlen(toFree)>AWT_MAX_SHOWN_DATA_SIZE) { |
|---|
| 377 | size_t shortened_len = GBS_shorten_repeated_data(toFree); |
|---|
| 378 | if (shortened_len>AWT_MAX_SHOWN_DATA_SIZE) { |
|---|
| 379 | strcpy(toFree+AWT_MAX_SHOWN_DATA_SIZE-5, "[...]"); |
|---|
| 380 | } |
|---|
| 381 | } |
|---|
| 382 | } |
|---|
| 383 | else { |
|---|
| 384 | toFree = GBS_global_string_copy("<%s has no data>", param.first_key); |
|---|
| 385 | } |
|---|
| 386 | info = toFree; |
|---|
| 387 | } |
|---|
| 388 | else { |
|---|
| 389 | info = reinterpret_cast<const char *>(GBS_read_hash(cbs->hit_description, name)); |
|---|
| 390 | if (!info) info = "<no hit info>"; |
|---|
| 391 | } |
|---|
| 392 | |
|---|
| 393 | awt_assert(info); |
|---|
| 394 | const char *line = GBS_global_string("%c %-*s :%s", |
|---|
| 395 | GB_read_flag(sorted[i]) ? '*' : ' ', |
|---|
| 396 | name_len, name, |
|---|
| 397 | info); |
|---|
| 398 | |
|---|
| 399 | cbs->aws->insert_selection(cbs->result_id, line, name); |
|---|
| 400 | free(toFree); |
|---|
| 401 | free(name); |
|---|
| 402 | } |
|---|
| 403 | } |
|---|
| 404 | |
|---|
| 405 | if (count>AWT_MAX_QUERY_LIST_LEN) { |
|---|
| 406 | cbs->aws->insert_selection(cbs->result_id, "***** List truncated *****", ""); |
|---|
| 407 | } |
|---|
| 408 | |
|---|
| 409 | free(sorted); |
|---|
| 410 | |
|---|
| 411 | cbs->aws->insert_default_selection( cbs->result_id, "End of list", "" ); |
|---|
| 412 | cbs->aws->update_selection_list( cbs->result_id ); |
|---|
| 413 | cbs->aws->get_root()->awar(cbs->awar_count)->write_int( (long)count); |
|---|
| 414 | GB_pop_transaction(cbs->gb_main); |
|---|
| 415 | |
|---|
| 416 | return count; |
|---|
| 417 | } |
|---|
| 418 | // Mark listed species |
|---|
| 419 | // mark = 1 -> mark listed |
|---|
| 420 | // mark | 8 -> don't change rest |
|---|
| 421 | void awt_do_mark_list(void *dummy, struct adaqbsstruct *cbs, long mark) |
|---|
| 422 | { |
|---|
| 423 | AWUSE(dummy); |
|---|
| 424 | GB_push_transaction(cbs->gb_main); |
|---|
| 425 | |
|---|
| 426 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, cbs->aws->get_root(), AWT_QUERY_ALL_SPECIES); |
|---|
| 427 | gb_item_container; |
|---|
| 428 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, AWT_QUERY_ALL_SPECIES)) |
|---|
| 429 | { |
|---|
| 430 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 431 | gb_item; |
|---|
| 432 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 433 | { |
|---|
| 434 | if (IS_QUERIED(gb_item, cbs)) { |
|---|
| 435 | GB_write_flag(gb_item, mark&1); |
|---|
| 436 | } |
|---|
| 437 | else if ((mark&8) == 0) { |
|---|
| 438 | GB_write_flag(gb_item, 1-(mark&1)); |
|---|
| 439 | } |
|---|
| 440 | } |
|---|
| 441 | } |
|---|
| 442 | |
|---|
| 443 | awt_query_update_list(0,cbs); |
|---|
| 444 | GB_pop_transaction(cbs->gb_main); |
|---|
| 445 | } |
|---|
| 446 | |
|---|
| 447 | void awt_unquery_all(void *dummy, struct adaqbsstruct *cbs){ |
|---|
| 448 | AWUSE(dummy); |
|---|
| 449 | GB_push_transaction(cbs->gb_main); |
|---|
| 450 | GBDATA *gb_species; |
|---|
| 451 | for ( gb_species = GBT_first_species(cbs->gb_main); |
|---|
| 452 | gb_species; |
|---|
| 453 | gb_species = GBT_next_species(gb_species)){ |
|---|
| 454 | CLEAR_QUERIED(gb_species,cbs); |
|---|
| 455 | } |
|---|
| 456 | awt_query_update_list(0,cbs); |
|---|
| 457 | GB_pop_transaction(cbs->gb_main); |
|---|
| 458 | } |
|---|
| 459 | |
|---|
| 460 | void awt_delete_species_in_list(void *dummy, struct adaqbsstruct *cbs) |
|---|
| 461 | { |
|---|
| 462 | GB_begin_transaction(cbs->gb_main); |
|---|
| 463 | long cnt = 0; |
|---|
| 464 | |
|---|
| 465 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, cbs->aws->get_root(), AWT_QUERY_ALL_SPECIES); |
|---|
| 466 | gb_item_container; |
|---|
| 467 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, AWT_QUERY_ALL_SPECIES)) |
|---|
| 468 | { |
|---|
| 469 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 470 | gb_item; |
|---|
| 471 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 472 | { |
|---|
| 473 | if (IS_QUERIED(gb_item, cbs)) cnt++; |
|---|
| 474 | } |
|---|
| 475 | } |
|---|
| 476 | |
|---|
| 477 | sprintf(AW_ERROR_BUFFER,"Are you sure to delete %li %s",cnt, cbs->selector->items_name); |
|---|
| 478 | if (aw_question(AW_ERROR_BUFFER,"OK,CANCEL")){ |
|---|
| 479 | GB_abort_transaction(cbs->gb_main); |
|---|
| 480 | return; |
|---|
| 481 | } |
|---|
| 482 | |
|---|
| 483 | GB_ERROR error = 0; |
|---|
| 484 | |
|---|
| 485 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, cbs->aws->get_root(), AWT_QUERY_ALL_SPECIES); |
|---|
| 486 | !error && gb_item_container; |
|---|
| 487 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, AWT_QUERY_ALL_SPECIES)) |
|---|
| 488 | { |
|---|
| 489 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 490 | !error && gb_item; |
|---|
| 491 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 492 | { |
|---|
| 493 | if (IS_QUERIED(gb_item,cbs)) { |
|---|
| 494 | error = GB_delete(gb_item); |
|---|
| 495 | } |
|---|
| 496 | } |
|---|
| 497 | } |
|---|
| 498 | |
|---|
| 499 | if (error) { |
|---|
| 500 | GB_abort_transaction(cbs->gb_main); |
|---|
| 501 | aw_message(error); |
|---|
| 502 | }else{ |
|---|
| 503 | awt_query_update_list(dummy,cbs); |
|---|
| 504 | GB_commit_transaction(cbs->gb_main); |
|---|
| 505 | } |
|---|
| 506 | } |
|---|
| 507 | |
|---|
| 508 | static GB_HASH *awt_create_ref_hash(const struct adaqbsstruct *cbs, const char *key, bool split_words) { |
|---|
| 509 | GBDATA *gb_ref = cbs->gb_ref; |
|---|
| 510 | bool queried_only = cbs->expect_hit_in_ref_list; |
|---|
| 511 | GB_HASH *hash = GBS_create_hash(GBT_get_species_hash_size(gb_ref), GB_IGNORE_CASE); |
|---|
| 512 | |
|---|
| 513 | for (GBDATA *gb_species = GBT_first_species(gb_ref); |
|---|
| 514 | gb_species; |
|---|
| 515 | gb_species = GBT_next_species(gb_species)) |
|---|
| 516 | { |
|---|
| 517 | if (!queried_only || IS_QUERIED(gb_species, cbs)) { |
|---|
| 518 | GBDATA *gb_name = GB_search(gb_species,key,GB_FIND); |
|---|
| 519 | if (gb_name) { |
|---|
| 520 | char *keyas = GB_read_as_string(gb_name); |
|---|
| 521 | if (keyas && strlen(keyas)) { |
|---|
| 522 | if (split_words) { |
|---|
| 523 | char *t; |
|---|
| 524 | for (t = strtok(keyas," "); t; t = strtok(0," ")) { |
|---|
| 525 | if (t[0]) GBS_write_hash(hash, t, (long)gb_species); |
|---|
| 526 | } |
|---|
| 527 | } |
|---|
| 528 | else { |
|---|
| 529 | GBS_write_hash(hash, keyas, (long)gb_species); |
|---|
| 530 | } |
|---|
| 531 | } |
|---|
| 532 | free(keyas); |
|---|
| 533 | } |
|---|
| 534 | } |
|---|
| 535 | } |
|---|
| 536 | return hash; |
|---|
| 537 | } |
|---|
| 538 | |
|---|
| 539 | // ------------------------ |
|---|
| 540 | // class awt_query |
|---|
| 541 | // ------------------------ |
|---|
| 542 | typedef enum { ILLEGAL, AND, OR } awt_query_operator; |
|---|
| 543 | |
|---|
| 544 | typedef enum { |
|---|
| 545 | AQT_INVALID, |
|---|
| 546 | AQT_EMPTY, |
|---|
| 547 | AQT_NON_EMPTY, |
|---|
| 548 | AQT_LOWER, |
|---|
| 549 | AQT_GREATER, |
|---|
| 550 | AQT_EXACT_MATCH, |
|---|
| 551 | AQT_OCCURS, |
|---|
| 552 | AQT_STARTS_WITH, |
|---|
| 553 | AQT_ENDS_WITH, |
|---|
| 554 | AQT_WILDCARD, |
|---|
| 555 | AQT_REGEXPR, |
|---|
| 556 | AQT_ACI, |
|---|
| 557 | } awt_query_type; |
|---|
| 558 | |
|---|
| 559 | typedef enum { |
|---|
| 560 | AQFT_EXPLICIT, // query should match one explicit field |
|---|
| 561 | AQFT_ANY_FIELD, // query should match one field (no matter which) |
|---|
| 562 | AQFT_ALL_FIELDS, // query should match all fields |
|---|
| 563 | } awt_query_field_type; |
|---|
| 564 | |
|---|
| 565 | class awt_query { |
|---|
| 566 | awt_query_operator op; // operator (AND or OR) |
|---|
| 567 | char *key; // search key |
|---|
| 568 | bool Not; // true means "don't match" |
|---|
| 569 | char *query; // search expression |
|---|
| 570 | |
|---|
| 571 | GBDATA *gb_main; |
|---|
| 572 | const char *tree; // name of current default tree (needed for ACI) |
|---|
| 573 | |
|---|
| 574 | bool rek; // is 'key' hierarchical ? |
|---|
| 575 | awt_query_field_type match_field; // type of search key |
|---|
| 576 | GBQUARK keyquark; // valid only if match_field == AQFT_EXPLICIT |
|---|
| 577 | awt_query_type type; // type of 'query' |
|---|
| 578 | struct { // used for some values of 'type' |
|---|
| 579 | string str; |
|---|
| 580 | GBS_REGEX *regexp; |
|---|
| 581 | float number; |
|---|
| 582 | } xquery; |
|---|
| 583 | |
|---|
| 584 | mutable char *error; // set by matches(), once set all future matches fail |
|---|
| 585 | mutable char *lastACIresult; // result of last ACI query |
|---|
| 586 | |
|---|
| 587 | awt_query *next; |
|---|
| 588 | int index; // number of query (0 = first query, 1 = second query); not always consecutive! |
|---|
| 589 | |
|---|
| 590 | // -------------------- |
|---|
| 591 | |
|---|
| 592 | void initFields(struct adaqbsstruct *cbs, int idx, awt_query_operator aqo, AW_root *aw_root); |
|---|
| 593 | awt_query() {} |
|---|
| 594 | |
|---|
| 595 | void detect_query_type(); |
|---|
| 596 | awt_query *remove_tail(); |
|---|
| 597 | void append(awt_query *tail); |
|---|
| 598 | |
|---|
| 599 | public: |
|---|
| 600 | |
|---|
| 601 | awt_query(struct adaqbsstruct *cbs); |
|---|
| 602 | |
|---|
| 603 | ~awt_query() { |
|---|
| 604 | free(key); |
|---|
| 605 | free(query); |
|---|
| 606 | free(lastACIresult); |
|---|
| 607 | if (xquery.regexp) GBS_free_regexpr(xquery.regexp); |
|---|
| 608 | free(error); |
|---|
| 609 | delete next; |
|---|
| 610 | } |
|---|
| 611 | |
|---|
| 612 | awt_query_operator getOperator() const { return op; } |
|---|
| 613 | const char *getKey() const { return key; } |
|---|
| 614 | bool applyNot(bool matched) const { return Not ? !matched : matched; } |
|---|
| 615 | bool shallMatch() const { return !Not; } |
|---|
| 616 | awt_query_type getType() const { return type; } |
|---|
| 617 | int getIndex() const { return index; } |
|---|
| 618 | |
|---|
| 619 | bool matches(const char *data, GBDATA *gb_item) const; |
|---|
| 620 | GB_ERROR getError(int count = 0) const; |
|---|
| 621 | const char *get_last_ACI_result() const { return type == AQT_ACI ? lastACIresult : 0; } |
|---|
| 622 | |
|---|
| 623 | awt_query *getNext() { return next; } |
|---|
| 624 | |
|---|
| 625 | bool is_rek() const { return rek; } |
|---|
| 626 | awt_query_field_type get_match_field() const { return match_field; } |
|---|
| 627 | GBQUARK getKeyquark() const { return keyquark; } |
|---|
| 628 | |
|---|
| 629 | GBDATA *get_first_key(GBDATA *gb_item) const { |
|---|
| 630 | GBDATA *gb_key = 0; |
|---|
| 631 | |
|---|
| 632 | if (is_rek()) { |
|---|
| 633 | gb_key = GB_search(gb_item, getKey(), GB_FIND); |
|---|
| 634 | } |
|---|
| 635 | else if (match_field != AQFT_EXPLICIT) { |
|---|
| 636 | gb_key = GB_child(gb_item); |
|---|
| 637 | while (gb_key && GB_read_type(gb_key) == GB_DB) { |
|---|
| 638 | gb_key = GB_nextChild(gb_key); |
|---|
| 639 | } |
|---|
| 640 | } |
|---|
| 641 | else { |
|---|
| 642 | gb_key = GB_find_sub_by_quark(gb_item, getKeyquark(), 0); |
|---|
| 643 | } |
|---|
| 644 | |
|---|
| 645 | return gb_key; |
|---|
| 646 | } |
|---|
| 647 | |
|---|
| 648 | void negate(); |
|---|
| 649 | |
|---|
| 650 | bool prefers_sort_by_hit() { |
|---|
| 651 | return |
|---|
| 652 | match_field == AQFT_ALL_FIELDS || |
|---|
| 653 | match_field == AQFT_ANY_FIELD || |
|---|
| 654 | (next && next->prefers_sort_by_hit()); |
|---|
| 655 | } |
|---|
| 656 | |
|---|
| 657 | #if defined(DEBUG) |
|---|
| 658 | string dump_str() const { return string(key)+(Not ? "!=" : "==")+query; } |
|---|
| 659 | void dump(string *prev = 0) const { |
|---|
| 660 | string mine = dump_str(); |
|---|
| 661 | if (prev) { |
|---|
| 662 | string both = *prev+' '; |
|---|
| 663 | switch (op) { |
|---|
| 664 | case AND: both += "&&"; break; |
|---|
| 665 | case OR: both += "||"; break; |
|---|
| 666 | default : awt_assert(0); break; |
|---|
| 667 | } |
|---|
| 668 | both += ' '+mine; |
|---|
| 669 | mine = both; |
|---|
| 670 | |
|---|
| 671 | if (next) mine = '('+mine+')'; |
|---|
| 672 | } |
|---|
| 673 | |
|---|
| 674 | if (next) next->dump(&mine); |
|---|
| 675 | else fputs(mine.c_str(), stdout); |
|---|
| 676 | } |
|---|
| 677 | #endif // DEBUG |
|---|
| 678 | }; |
|---|
| 679 | |
|---|
| 680 | void awt_query::initFields(struct adaqbsstruct *cbs, int idx, awt_query_operator aqo, AW_root *aw_root) { |
|---|
| 681 | awt_assert(aqo == OR || aqo == AND); |
|---|
| 682 | |
|---|
| 683 | error = 0; |
|---|
| 684 | lastACIresult = 0; |
|---|
| 685 | next = 0; |
|---|
| 686 | index = idx; |
|---|
| 687 | xquery.regexp = 0; |
|---|
| 688 | |
|---|
| 689 | op = aqo; |
|---|
| 690 | key = aw_root->awar(cbs->awar_keys[idx])->read_string(); |
|---|
| 691 | Not = aw_root->awar(cbs->awar_not[idx])->read_int() != 0; |
|---|
| 692 | query = aw_root->awar(cbs->awar_queries[idx])->read_string(); |
|---|
| 693 | |
|---|
| 694 | gb_main = cbs->gb_main; |
|---|
| 695 | tree = cbs->tree_name; |
|---|
| 696 | |
|---|
| 697 | rek = false; |
|---|
| 698 | match_field = AQFT_EXPLICIT;; |
|---|
| 699 | keyquark = -1; |
|---|
| 700 | if (GB_first_non_key_char(key)) { |
|---|
| 701 | if (strcmp(key, PSEUDO_FIELD_ANY_FIELD) == 0) match_field = AQFT_ANY_FIELD; |
|---|
| 702 | else if (strcmp(key, PSEUDO_FIELD_ALL_FIELDS) == 0) match_field = AQFT_ALL_FIELDS; |
|---|
| 703 | else rek = true; |
|---|
| 704 | } |
|---|
| 705 | else { |
|---|
| 706 | keyquark = GB_key_2_quark(gb_main, key); |
|---|
| 707 | } |
|---|
| 708 | |
|---|
| 709 | detect_query_type(); |
|---|
| 710 | } |
|---|
| 711 | |
|---|
| 712 | awt_query::awt_query(struct adaqbsstruct *cbs) { |
|---|
| 713 | AW_root *aw_root = cbs->aws->get_root(); |
|---|
| 714 | |
|---|
| 715 | initFields(cbs, 0, OR, aw_root); // initial value is false, (false OR QUERY1) == QUERY1 |
|---|
| 716 | |
|---|
| 717 | awt_query *tail = this; |
|---|
| 718 | for (size_t keyidx = 1; keyidx<AWT_QUERY_SEARCHES; ++keyidx) { |
|---|
| 719 | char *opstr = aw_root->awar(cbs->awar_operator[keyidx])->read_string(); |
|---|
| 720 | |
|---|
| 721 | if (strcmp(opstr, "ign") != 0) { // not ignore |
|---|
| 722 | awt_query_operator next_op = ILLEGAL; |
|---|
| 723 | |
|---|
| 724 | if (strcmp(opstr, "and") == 0) next_op = AND; |
|---|
| 725 | else if (strcmp(opstr, "or") == 0) next_op = OR; |
|---|
| 726 | #if defined(ASSERTION_USED) |
|---|
| 727 | else aw_assert(0); |
|---|
| 728 | #endif // ASSERTION_USED |
|---|
| 729 | |
|---|
| 730 | if (next_op != ILLEGAL) { |
|---|
| 731 | awt_query *next_query = new awt_query; |
|---|
| 732 | |
|---|
| 733 | next_query->initFields(cbs, keyidx, next_op, aw_root); |
|---|
| 734 | |
|---|
| 735 | tail->next = next_query; |
|---|
| 736 | tail = next_query; |
|---|
| 737 | } |
|---|
| 738 | } |
|---|
| 739 | free(opstr); |
|---|
| 740 | } |
|---|
| 741 | } |
|---|
| 742 | |
|---|
| 743 | awt_query *awt_query::remove_tail() { |
|---|
| 744 | awt_query *tail = 0; |
|---|
| 745 | if (next) { |
|---|
| 746 | awt_query *body_last = this; |
|---|
| 747 | while (body_last->next && body_last->next->next) { |
|---|
| 748 | body_last = body_last->next; |
|---|
| 749 | } |
|---|
| 750 | awt_assert(body_last->next); |
|---|
| 751 | awt_assert(body_last->next->next == 0); |
|---|
| 752 | |
|---|
| 753 | tail = body_last->next; |
|---|
| 754 | body_last->next = 0; |
|---|
| 755 | } |
|---|
| 756 | return tail; |
|---|
| 757 | } |
|---|
| 758 | |
|---|
| 759 | void awt_query::append(awt_query *tail) { |
|---|
| 760 | awt_assert(this != tail); |
|---|
| 761 | if (next) next->append(tail); |
|---|
| 762 | else next = tail; |
|---|
| 763 | } |
|---|
| 764 | |
|---|
| 765 | void awt_query::negate() { |
|---|
| 766 | if (next) { |
|---|
| 767 | awt_query *tail = remove_tail(); |
|---|
| 768 | |
|---|
| 769 | negate(); |
|---|
| 770 | tail->negate(); |
|---|
| 771 | |
|---|
| 772 | switch (tail->op) { |
|---|
| 773 | case AND: tail->op = OR; break; |
|---|
| 774 | case OR: tail->op = AND; break; |
|---|
| 775 | default : awt_assert(0); break; |
|---|
| 776 | } |
|---|
| 777 | |
|---|
| 778 | append(tail); |
|---|
| 779 | } |
|---|
| 780 | else { |
|---|
| 781 | Not = !Not; |
|---|
| 782 | switch (match_field) { |
|---|
| 783 | case AQFT_EXPLICIT: break; |
|---|
| 784 | case AQFT_ALL_FIELDS: match_field = AQFT_ANY_FIELD; break; // not match allFields <=> mismatch anyField |
|---|
| 785 | case AQFT_ANY_FIELD: match_field = AQFT_ALL_FIELDS; break; // not match anyField <=> mismatch allFields |
|---|
| 786 | } |
|---|
| 787 | } |
|---|
| 788 | } |
|---|
| 789 | |
|---|
| 790 | GB_ERROR awt_query::getError(int count) const { |
|---|
| 791 | GB_ERROR err = error; |
|---|
| 792 | error = NULL; |
|---|
| 793 | |
|---|
| 794 | if (err) { |
|---|
| 795 | err = GBS_global_string("%s (in query #%i)", err, count+1); |
|---|
| 796 | } |
|---|
| 797 | |
|---|
| 798 | if (next) { |
|---|
| 799 | if (err) { |
|---|
| 800 | char *dup = strdup(err); |
|---|
| 801 | |
|---|
| 802 | err = next->getError(count+1); |
|---|
| 803 | if (err) err = GBS_global_string("%s\n%s", dup, err); |
|---|
| 804 | else err = GBS_global_string("%s", dup); |
|---|
| 805 | free(dup); |
|---|
| 806 | } |
|---|
| 807 | else { |
|---|
| 808 | err = next->getError(count+1); |
|---|
| 809 | } |
|---|
| 810 | } |
|---|
| 811 | |
|---|
| 812 | return err; |
|---|
| 813 | } |
|---|
| 814 | |
|---|
| 815 | |
|---|
| 816 | inline bool containsWildcards(const char *str) { return strpbrk(str, "*?") != 0; } |
|---|
| 817 | inline bool containsWildcards(const string& str) { return str.find_first_of("*?") != string::npos; } |
|---|
| 818 | |
|---|
| 819 | void awt_query::detect_query_type() { |
|---|
| 820 | char first = query[0]; |
|---|
| 821 | string& str = xquery.str; |
|---|
| 822 | str = query; |
|---|
| 823 | |
|---|
| 824 | type = AQT_INVALID; |
|---|
| 825 | |
|---|
| 826 | if (!first) type = AQT_EMPTY; |
|---|
| 827 | else if (first == '/') { |
|---|
| 828 | GB_CASE case_flag; |
|---|
| 829 | GB_ERROR err = 0; |
|---|
| 830 | const char *unwrapped = GBS_unwrap_regexpr(query, &case_flag, &err); |
|---|
| 831 | if (unwrapped) { |
|---|
| 832 | xquery.regexp = GBS_compile_regexpr(unwrapped, case_flag, &err); |
|---|
| 833 | if (xquery.regexp) type = AQT_REGEXPR; |
|---|
| 834 | } |
|---|
| 835 | if (err) freedup(error, err); |
|---|
| 836 | } |
|---|
| 837 | else if (first == '|') type = AQT_ACI; |
|---|
| 838 | else if (first == '<' || first == '>') { |
|---|
| 839 | const char *rest = query+1; |
|---|
| 840 | const char *end; |
|---|
| 841 | float f = strtof(rest, const_cast<char**>(&end)); |
|---|
| 842 | |
|---|
| 843 | if (end != rest) { // did convert part or all of rest to float |
|---|
| 844 | if (end[0] == 0) { // all of rest has been converted |
|---|
| 845 | type = query[0] == '<' ? AQT_LOWER : AQT_GREATER; |
|---|
| 846 | xquery.number = f; |
|---|
| 847 | } |
|---|
| 848 | else { |
|---|
| 849 | freeset(error, GBS_global_string_copy("Could not convert '%s' to number (unexpected content '%s')", rest, end)); |
|---|
| 850 | } |
|---|
| 851 | } |
|---|
| 852 | // otherwise handle as non-special search string |
|---|
| 853 | } |
|---|
| 854 | |
|---|
| 855 | if (type == AQT_INVALID && !error) { // no type detected above |
|---|
| 856 | if (containsWildcards(query)) { |
|---|
| 857 | size_t qlen = strlen(query); |
|---|
| 858 | char last = query[qlen-1]; |
|---|
| 859 | |
|---|
| 860 | if (first == '*') { |
|---|
| 861 | if (last == '*') { |
|---|
| 862 | str = string(str, 1, str.length()-2); // cut off first and last |
|---|
| 863 | type = str.length() ? AQT_OCCURS : AQT_NON_EMPTY; |
|---|
| 864 | } |
|---|
| 865 | else { |
|---|
| 866 | str = string(str, 1); // cut of first |
|---|
| 867 | type = AQT_ENDS_WITH; |
|---|
| 868 | } |
|---|
| 869 | } |
|---|
| 870 | else { |
|---|
| 871 | if (last == '*') { |
|---|
| 872 | str = string(str, 0, str.length()-1); // cut of last |
|---|
| 873 | type = AQT_STARTS_WITH; |
|---|
| 874 | } |
|---|
| 875 | else type = AQT_WILDCARD; |
|---|
| 876 | } |
|---|
| 877 | |
|---|
| 878 | if (type != AQT_WILDCARD && containsWildcards(str)) { // still contains wildcards -> fallback |
|---|
| 879 | str = query; |
|---|
| 880 | type = AQT_WILDCARD; |
|---|
| 881 | } |
|---|
| 882 | } |
|---|
| 883 | else type = AQT_EXACT_MATCH; |
|---|
| 884 | } |
|---|
| 885 | |
|---|
| 886 | awt_assert(type != AQT_INVALID || error); |
|---|
| 887 | } |
|---|
| 888 | |
|---|
| 889 | bool awt_query::matches(const char *data, GBDATA *gb_item) const { |
|---|
| 890 | // 'data' is the content of the searched field (read as string) |
|---|
| 891 | // 'gb_item' is the DB item (e.g. species, gene). Used in ACI-search only. |
|---|
| 892 | |
|---|
| 893 | bool hit = false; |
|---|
| 894 | |
|---|
| 895 | awt_assert(data); |
|---|
| 896 | awt_assert(gb_item); |
|---|
| 897 | |
|---|
| 898 | if (error) hit = false; |
|---|
| 899 | else switch (type) { |
|---|
| 900 | case AQT_EMPTY: { |
|---|
| 901 | hit = (data[0] == 0); |
|---|
| 902 | break; |
|---|
| 903 | } |
|---|
| 904 | case AQT_NON_EMPTY: { |
|---|
| 905 | hit = (data[0] != 0); |
|---|
| 906 | break; |
|---|
| 907 | } |
|---|
| 908 | case AQT_EXACT_MATCH: { // exact match (but ignoring case) |
|---|
| 909 | hit = strcasecmp(data, query) == 0; |
|---|
| 910 | break; |
|---|
| 911 | } |
|---|
| 912 | case AQT_OCCURS: { // query expression occurs in data (equiv to '*expr*') |
|---|
| 913 | // hit = GBS_find_string(xquery.str.c_str(), data, 1) != 0; |
|---|
| 914 | hit = GBS_find_string(data, xquery.str.c_str(), 1) != 0; |
|---|
| 915 | break; |
|---|
| 916 | } |
|---|
| 917 | case AQT_STARTS_WITH: { // data starts with query expression (equiv to 'expr*') |
|---|
| 918 | hit = strncasecmp(data, xquery.str.c_str(), xquery.str.length()) == 0; |
|---|
| 919 | break; |
|---|
| 920 | } |
|---|
| 921 | case AQT_ENDS_WITH: { // data ends with query expression (equiv to '*expr') |
|---|
| 922 | int dlen = strlen(data); |
|---|
| 923 | hit = strcasecmp(data+dlen-xquery.str.length(), xquery.str.c_str()) == 0; |
|---|
| 924 | break; |
|---|
| 925 | } |
|---|
| 926 | case AQT_WILDCARD: { // expr contains wildcards (use GBS_string_matches for compare) |
|---|
| 927 | hit = GBS_string_matches(data,query,GB_IGNORE_CASE); |
|---|
| 928 | break; |
|---|
| 929 | } |
|---|
| 930 | case AQT_GREATER: // data is greater than query |
|---|
| 931 | case AQT_LOWER: { // data is lower than query |
|---|
| 932 | const char *start = data; |
|---|
| 933 | while (start[0] == ' ') ++start; |
|---|
| 934 | |
|---|
| 935 | const char *end; |
|---|
| 936 | float f = strtof(start, const_cast<char**>(&end)); |
|---|
| 937 | |
|---|
| 938 | if (end == start) { // nothing was converted |
|---|
| 939 | hit = false; |
|---|
| 940 | } |
|---|
| 941 | else { |
|---|
| 942 | bool is_numeric = (end[0] == 0); |
|---|
| 943 | |
|---|
| 944 | if (!is_numeric) { |
|---|
| 945 | while (end[0] == ' ') ++end; |
|---|
| 946 | is_numeric = (end[0] == 0); |
|---|
| 947 | } |
|---|
| 948 | if (is_numeric) { |
|---|
| 949 | hit = (type == AQT_GREATER) |
|---|
| 950 | ? f > xquery.number |
|---|
| 951 | : f < xquery.number; |
|---|
| 952 | } |
|---|
| 953 | else { |
|---|
| 954 | hit = false; |
|---|
| 955 | } |
|---|
| 956 | } |
|---|
| 957 | break; |
|---|
| 958 | } |
|---|
| 959 | case AQT_REGEXPR: { // expr is a regexpr ('/.../') |
|---|
| 960 | hit = GBS_regmatch_compiled(data, xquery.regexp, NULL) != 0; |
|---|
| 961 | break; |
|---|
| 962 | } |
|---|
| 963 | case AQT_ACI: { // expr is a ACI ('|...'); result = "0" -> no hit; otherwise hit |
|---|
| 964 | char *aci_result = GB_command_interpreter(gb_main, data, query, gb_item, tree); |
|---|
| 965 | if (!aci_result) { |
|---|
| 966 | freedup(error, GB_await_error()); |
|---|
| 967 | hit = false; |
|---|
| 968 | } |
|---|
| 969 | else { |
|---|
| 970 | hit = strcmp(aci_result, "0") != 0; |
|---|
| 971 | } |
|---|
| 972 | freeset(lastACIresult, aci_result); |
|---|
| 973 | break; |
|---|
| 974 | } |
|---|
| 975 | case AQT_INVALID: { // invalid |
|---|
| 976 | awt_assert(0); |
|---|
| 977 | freedup(error, "Invalid search expression"); |
|---|
| 978 | hit = false; |
|---|
| 979 | break; |
|---|
| 980 | } |
|---|
| 981 | } |
|---|
| 982 | return applyNot(hit); |
|---|
| 983 | } |
|---|
| 984 | |
|---|
| 985 | static void awt_do_query(void *dummy, struct adaqbsstruct *cbs, AW_CL cl_ext_query) { |
|---|
| 986 | AWUSE(dummy); |
|---|
| 987 | |
|---|
| 988 | GB_push_transaction(cbs->gb_main); |
|---|
| 989 | |
|---|
| 990 | AWT_EXT_QUERY_TYPES ext_query = (AWT_EXT_QUERY_TYPES)cl_ext_query; |
|---|
| 991 | AW_root *aw_root = cbs->aws->get_root(); |
|---|
| 992 | awt_query query(cbs); |
|---|
| 993 | |
|---|
| 994 | AWT_QUERY_MODES mode = (AWT_QUERY_MODES)aw_root->awar(cbs->awar_ere)->read_int(); |
|---|
| 995 | AWT_QUERY_RANGE range = (AWT_QUERY_RANGE)aw_root->awar(cbs->awar_where)->read_int(); |
|---|
| 996 | AWT_QUERY_TYPES type = (AWT_QUERY_TYPES)aw_root->awar(cbs->awar_by)->read_int(); |
|---|
| 997 | |
|---|
| 998 | if (cbs->gb_ref && type != AWT_QUERY_MARKED) { // special for merge tool! |
|---|
| 999 | char *first_query = aw_root->awar(cbs->awar_queries[0])->read_string(); |
|---|
| 1000 | if (strlen(first_query) == 0) { |
|---|
| 1001 | if (!ext_query) ext_query = AWT_EXT_QUERY_COMPARE_LINES; |
|---|
| 1002 | } |
|---|
| 1003 | free(first_query); |
|---|
| 1004 | } |
|---|
| 1005 | |
|---|
| 1006 | GB_ERROR error = query.getError(); |
|---|
| 1007 | |
|---|
| 1008 | if (!error) { |
|---|
| 1009 | size_t item_count = awt_count_items(cbs, range); |
|---|
| 1010 | size_t searched_count = 0; |
|---|
| 1011 | |
|---|
| 1012 | aw_openstatus("Searching"); |
|---|
| 1013 | aw_status(0.0); |
|---|
| 1014 | |
|---|
| 1015 | if (cbs->gb_ref && // merge tool only |
|---|
| 1016 | (ext_query == AWT_EXT_QUERY_COMPARE_LINES || ext_query == AWT_EXT_QUERY_COMPARE_WORDS)) |
|---|
| 1017 | { |
|---|
| 1018 | GB_push_transaction(cbs->gb_ref); |
|---|
| 1019 | const char *first_key = query.getKey(); |
|---|
| 1020 | GB_HASH *ref_hash = awt_create_ref_hash(cbs, first_key, ext_query == AWT_EXT_QUERY_COMPARE_WORDS); |
|---|
| 1021 | |
|---|
| 1022 | #if defined(DEBUG) |
|---|
| 1023 | printf("query: search identical %s in field %s%s\n", |
|---|
| 1024 | (ext_query == AWT_EXT_QUERY_COMPARE_WORDS ? "words" : "values"), |
|---|
| 1025 | first_key, |
|---|
| 1026 | cbs->expect_hit_in_ref_list ? " of species listed in other hitlist" : ""); |
|---|
| 1027 | #endif // DEBUG |
|---|
| 1028 | |
|---|
| 1029 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, aw_root, range); |
|---|
| 1030 | gb_item_container && !error; |
|---|
| 1031 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 1032 | { |
|---|
| 1033 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 1034 | gb_item && !error; |
|---|
| 1035 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 1036 | { |
|---|
| 1037 | switch (mode) { |
|---|
| 1038 | case AWT_QUERY_GENERATE: CLEAR_QUERIED(gb_item, cbs); break; |
|---|
| 1039 | case AWT_QUERY_ENLARGE: if (IS_QUERIED(gb_item, cbs)) continue; break; |
|---|
| 1040 | case AWT_QUERY_REDUCE: if (!IS_QUERIED(gb_item, cbs)) continue; break; |
|---|
| 1041 | } |
|---|
| 1042 | |
|---|
| 1043 | GBDATA *gb_key = query.get_first_key(gb_item); |
|---|
| 1044 | |
|---|
| 1045 | if (gb_key) { |
|---|
| 1046 | char *data = GB_read_as_string(gb_key); |
|---|
| 1047 | GBDATA *gb_ref_pntr = 0; |
|---|
| 1048 | |
|---|
| 1049 | if (data && data[0]) { |
|---|
| 1050 | string hit_reason; |
|---|
| 1051 | bool this_hit = false; |
|---|
| 1052 | |
|---|
| 1053 | if (ext_query == AWT_EXT_QUERY_COMPARE_WORDS){ |
|---|
| 1054 | for (char *t = strtok(data," "); t; t = strtok(0," ")) { |
|---|
| 1055 | gb_ref_pntr = (GBDATA *)GBS_read_hash(ref_hash,t); |
|---|
| 1056 | if (gb_ref_pntr) { // found item in other DB, with 'first_key' containing word from 'gb_key' |
|---|
| 1057 | this_hit = true; |
|---|
| 1058 | hit_reason = GBS_global_string("%s%s has word '%s' in %s", |
|---|
| 1059 | cbs->expect_hit_in_ref_list ? "Hit " : "", |
|---|
| 1060 | cbs->selector->generate_item_id(cbs->gb_ref, gb_ref_pntr), |
|---|
| 1061 | t, first_key); |
|---|
| 1062 | } |
|---|
| 1063 | } |
|---|
| 1064 | } |
|---|
| 1065 | else { |
|---|
| 1066 | gb_ref_pntr = (GBDATA *)GBS_read_hash(ref_hash,data); |
|---|
| 1067 | if (gb_ref_pntr) { // found item in other DB, with identical 'first_key' |
|---|
| 1068 | this_hit = true; |
|---|
| 1069 | hit_reason = GBS_global_string("%s%s matches %s", |
|---|
| 1070 | cbs->expect_hit_in_ref_list ? "Hit " : "", |
|---|
| 1071 | cbs->selector->generate_item_id(cbs->gb_ref, gb_ref_pntr), |
|---|
| 1072 | first_key); |
|---|
| 1073 | } |
|---|
| 1074 | } |
|---|
| 1075 | |
|---|
| 1076 | if (type == AWT_QUERY_DONT_MATCH) { |
|---|
| 1077 | this_hit = !this_hit; |
|---|
| 1078 | if (this_hit) hit_reason = "<no matching entry>"; |
|---|
| 1079 | } |
|---|
| 1080 | |
|---|
| 1081 | if (this_hit) { |
|---|
| 1082 | awt_assert(!hit_reason.empty()); |
|---|
| 1083 | SET_QUERIED(gb_item, cbs, hit_reason.c_str(), hit_reason.length()); |
|---|
| 1084 | } |
|---|
| 1085 | else CLEAR_QUERIED(gb_item, cbs); |
|---|
| 1086 | } |
|---|
| 1087 | free(data); |
|---|
| 1088 | } |
|---|
| 1089 | |
|---|
| 1090 | if (aw_status(searched_count++/double(item_count))) error = "aborted"; |
|---|
| 1091 | } |
|---|
| 1092 | } |
|---|
| 1093 | |
|---|
| 1094 | GBS_free_hash(ref_hash); |
|---|
| 1095 | GB_pop_transaction(cbs->gb_ref); |
|---|
| 1096 | } |
|---|
| 1097 | else { // "normal" query |
|---|
| 1098 | if (type == AWT_QUERY_DONT_MATCH) { |
|---|
| 1099 | #if defined(DEBUG) |
|---|
| 1100 | fputs("query: !(", stdout); query.dump(); |
|---|
| 1101 | #endif // DEBUG |
|---|
| 1102 | |
|---|
| 1103 | query.negate(); |
|---|
| 1104 | type = AWT_QUERY_MATCH; |
|---|
| 1105 | |
|---|
| 1106 | #if defined(DEBUG) |
|---|
| 1107 | fputs(") => query: ", stdout); query.dump(); fputc('\n', stdout); |
|---|
| 1108 | #endif // DEBUG |
|---|
| 1109 | } |
|---|
| 1110 | #if defined(DEBUG) |
|---|
| 1111 | else { fputs("query: ", stdout); query.dump(); fputc('\n', stdout); } |
|---|
| 1112 | #endif // DEBUG |
|---|
| 1113 | |
|---|
| 1114 | if (query.prefers_sort_by_hit()) { |
|---|
| 1115 | // automatically switch to sorting 'by hit' if 'any field' or 'all fields' is selected |
|---|
| 1116 | aw_root->awar(cbs->awar_sort)->write_int(AWT_QUERY_SORT_BY_HIT_DESCRIPTION); |
|---|
| 1117 | } |
|---|
| 1118 | |
|---|
| 1119 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, aw_root, range); |
|---|
| 1120 | gb_item_container && !error; |
|---|
| 1121 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 1122 | { |
|---|
| 1123 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 1124 | gb_item && !error; |
|---|
| 1125 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 1126 | { |
|---|
| 1127 | string hit_reason; |
|---|
| 1128 | |
|---|
| 1129 | switch (mode) { |
|---|
| 1130 | case AWT_QUERY_GENERATE: CLEAR_QUERIED(gb_item,cbs); break; |
|---|
| 1131 | case AWT_QUERY_ENLARGE: if (IS_QUERIED(gb_item,cbs)) continue; break; |
|---|
| 1132 | case AWT_QUERY_REDUCE: if (!IS_QUERIED(gb_item,cbs)) continue; break; |
|---|
| 1133 | } |
|---|
| 1134 | |
|---|
| 1135 | bool hit = false; |
|---|
| 1136 | |
|---|
| 1137 | switch(type) { |
|---|
| 1138 | case AWT_QUERY_MARKED: { |
|---|
| 1139 | hit = GB_read_flag(gb_item); |
|---|
| 1140 | hit_reason = "<marked>"; |
|---|
| 1141 | break; |
|---|
| 1142 | } |
|---|
| 1143 | case AWT_QUERY_MATCH: { |
|---|
| 1144 | for (awt_query *this_query = &query; this_query; this_query = this_query ? this_query->getNext() : 0) { // iterate over all single queries |
|---|
| 1145 | awt_query_operator this_op = this_query->getOperator(); |
|---|
| 1146 | |
|---|
| 1147 | if ((this_op == OR) == hit) { |
|---|
| 1148 | continue; // skip query Q for '1 OR Q' and for '0 AND Q' (result can't change) |
|---|
| 1149 | } |
|---|
| 1150 | |
|---|
| 1151 | string this_hit_reason; |
|---|
| 1152 | |
|---|
| 1153 | GBDATA *gb_key = this_query->get_first_key(gb_item); |
|---|
| 1154 | awt_query_field_type match_field = this_query->get_match_field(); |
|---|
| 1155 | bool this_hit = (match_field == AQFT_ALL_FIELDS); |
|---|
| 1156 | |
|---|
| 1157 | char *data = gb_key ? GB_read_as_string(gb_key) : strdup(""); // assume "" for explicit fields that don't exist |
|---|
| 1158 | if (!data) error = GB_await_error(); |
|---|
| 1159 | |
|---|
| 1160 | while (data) { |
|---|
| 1161 | awt_assert(ext_query == AWT_EXT_QUERY_NONE); |
|---|
| 1162 | bool matched = this_query->matches(data, gb_item); // includes not-op |
|---|
| 1163 | const char *reason_key = 0; |
|---|
| 1164 | |
|---|
| 1165 | switch (match_field) { |
|---|
| 1166 | case AQFT_EXPLICIT: |
|---|
| 1167 | this_hit = matched; |
|---|
| 1168 | reason_key = this_query->getKey(); |
|---|
| 1169 | break; |
|---|
| 1170 | |
|---|
| 1171 | case AQFT_ANY_FIELD: |
|---|
| 1172 | if (matched) { |
|---|
| 1173 | this_hit = true; |
|---|
| 1174 | reason_key = GB_read_key_pntr(gb_key); |
|---|
| 1175 | } |
|---|
| 1176 | break; |
|---|
| 1177 | |
|---|
| 1178 | case AQFT_ALL_FIELDS: |
|---|
| 1179 | if (!matched) { |
|---|
| 1180 | this_hit = false; |
|---|
| 1181 | reason_key = GB_read_key_pntr(gb_key); |
|---|
| 1182 | } |
|---|
| 1183 | break; |
|---|
| 1184 | } |
|---|
| 1185 | |
|---|
| 1186 | if (reason_key) { |
|---|
| 1187 | if (strlen(data)>AWT_MAX_SHOWN_DATA_SIZE) { |
|---|
| 1188 | size_t shortened_len = GBS_shorten_repeated_data(data); |
|---|
| 1189 | if (shortened_len>AWT_MAX_SHOWN_DATA_SIZE) { |
|---|
| 1190 | strcpy(data+AWT_MAX_SHOWN_DATA_SIZE-5, "[...]"); |
|---|
| 1191 | } |
|---|
| 1192 | } |
|---|
| 1193 | this_hit_reason = string(reason_key)+"="+data; |
|---|
| 1194 | const char *ACIresult = this_query->get_last_ACI_result(); |
|---|
| 1195 | if (ACIresult) { |
|---|
| 1196 | this_hit_reason = string("[ACI=")+ACIresult+"] "+this_hit_reason; |
|---|
| 1197 | } |
|---|
| 1198 | gb_key = NULL; // stop! |
|---|
| 1199 | } |
|---|
| 1200 | |
|---|
| 1201 | freeset(data, NULL); |
|---|
| 1202 | if (gb_key) { |
|---|
| 1203 | do { gb_key = GB_nextChild(gb_key); } |
|---|
| 1204 | while (gb_key && GB_read_type(gb_key) == GB_DB); |
|---|
| 1205 | |
|---|
| 1206 | if (gb_key) { |
|---|
| 1207 | data = GB_read_as_string(gb_key); |
|---|
| 1208 | awt_assert(data); |
|---|
| 1209 | } |
|---|
| 1210 | } |
|---|
| 1211 | } |
|---|
| 1212 | |
|---|
| 1213 | if (this_hit && match_field == AQFT_ALL_FIELDS) { |
|---|
| 1214 | awt_assert(this_hit_reason.empty()); |
|---|
| 1215 | this_hit_reason = this_query->shallMatch() ? "<matched all fields>" : "<matched no field>"; |
|---|
| 1216 | } |
|---|
| 1217 | |
|---|
| 1218 | |
|---|
| 1219 | if (this_hit) { |
|---|
| 1220 | awt_assert(!this_hit_reason.empty()); // if we got a hit, we also need a reason |
|---|
| 1221 | const char *prefix = GBS_global_string("%c%c", '1'+this_query->getIndex(), this_query->shallMatch() ? ' ' : '!'); |
|---|
| 1222 | this_hit_reason = string(prefix)+this_hit_reason; |
|---|
| 1223 | } |
|---|
| 1224 | |
|---|
| 1225 | // calculate result |
|---|
| 1226 | // (Note: the operator of the 1st query is always OR) |
|---|
| 1227 | switch (this_op) { |
|---|
| 1228 | case AND: { |
|---|
| 1229 | awt_assert(hit); // otherwise there was no need to run this sub-query |
|---|
| 1230 | hit = this_hit; |
|---|
| 1231 | hit_reason = hit_reason.empty() ? this_hit_reason : hit_reason+" & "+this_hit_reason; |
|---|
| 1232 | break; |
|---|
| 1233 | } |
|---|
| 1234 | case OR: { |
|---|
| 1235 | awt_assert(!hit); // otherwise there was no need to run this sub-query |
|---|
| 1236 | hit = this_hit; |
|---|
| 1237 | hit_reason = this_hit_reason; |
|---|
| 1238 | break; |
|---|
| 1239 | } |
|---|
| 1240 | default : |
|---|
| 1241 | awt_assert(0); |
|---|
| 1242 | break; |
|---|
| 1243 | } |
|---|
| 1244 | awt_assert(!hit || !hit_reason.empty()); // if we got a hit, we also need a reason |
|---|
| 1245 | } |
|---|
| 1246 | break; |
|---|
| 1247 | } |
|---|
| 1248 | default : awt_assert(0); break; |
|---|
| 1249 | } |
|---|
| 1250 | |
|---|
| 1251 | if (hit) { |
|---|
| 1252 | awt_assert(!hit_reason.empty()); |
|---|
| 1253 | |
|---|
| 1254 | if (mode == AWT_QUERY_REDUCE) { |
|---|
| 1255 | string prev_info = getHitInfo(gb_item, cbs); |
|---|
| 1256 | hit_reason = prev_info+" (kept cause "+hit_reason+")"; |
|---|
| 1257 | } |
|---|
| 1258 | |
|---|
| 1259 | SET_QUERIED(gb_item, cbs, hit_reason.c_str(), hit_reason.length()); |
|---|
| 1260 | } |
|---|
| 1261 | else CLEAR_QUERIED(gb_item, cbs); |
|---|
| 1262 | |
|---|
| 1263 | if (error) { |
|---|
| 1264 | error = GB_failedTo_error("query", GBT_get_name(gb_item), error); |
|---|
| 1265 | } |
|---|
| 1266 | else { |
|---|
| 1267 | if (aw_status(searched_count++/double(item_count))) error = "aborted"; |
|---|
| 1268 | } |
|---|
| 1269 | } |
|---|
| 1270 | } |
|---|
| 1271 | } |
|---|
| 1272 | |
|---|
| 1273 | aw_closestatus(); |
|---|
| 1274 | } |
|---|
| 1275 | |
|---|
| 1276 | if (!error) error = query.getError(); // check for query error |
|---|
| 1277 | |
|---|
| 1278 | if (error) aw_message(error); |
|---|
| 1279 | else awt_query_update_list(0,cbs); |
|---|
| 1280 | |
|---|
| 1281 | GB_pop_transaction(cbs->gb_main); |
|---|
| 1282 | } |
|---|
| 1283 | |
|---|
| 1284 | void awt_copy_selection_list_2_queried_species(struct adaqbsstruct *cbs, AW_selection_list *id, const char *hit_description) { |
|---|
| 1285 | GB_transaction ta(cbs->gb_main); |
|---|
| 1286 | |
|---|
| 1287 | awt_assert(strstr(hit_description, "%s")); // hit_description needs '%s' (which is replaced by visible content of 'id') |
|---|
| 1288 | |
|---|
| 1289 | GB_ERROR error = 0; |
|---|
| 1290 | AW_window *aww = cbs->aws; |
|---|
| 1291 | AW_root *aw_root = aww->get_root(); |
|---|
| 1292 | GB_HASH *list_hash = aww->selection_list_to_hash(id, false); |
|---|
| 1293 | AWT_QUERY_MODES mode = (AWT_QUERY_MODES)aw_root->awar(cbs->awar_ere)->read_int(); |
|---|
| 1294 | AWT_QUERY_TYPES type = (AWT_QUERY_TYPES)aw_root->awar(cbs->awar_by)->read_int(); |
|---|
| 1295 | |
|---|
| 1296 | if (type == AWT_QUERY_MARKED) { |
|---|
| 1297 | error = "Query mode 'that are marked' does not apply here.\nEither select 'that match the query' or 'that don't match the q.'"; |
|---|
| 1298 | } |
|---|
| 1299 | |
|---|
| 1300 | if (type != AWT_QUERY_MATCH || mode != AWT_QUERY_GENERATE) { // different behavior as in the past -> advice |
|---|
| 1301 | AWT_advice("'Move to hitlist' now depends on the values selected for\n" |
|---|
| 1302 | " * 'Search/Add/Keep species' and\n" |
|---|
| 1303 | " * 'that match/don't match the query'\n" |
|---|
| 1304 | "in the search tool.", |
|---|
| 1305 | AWT_ADVICE_TOGGLE|AWT_ADVICE_HELP, |
|---|
| 1306 | "Behavior changed", |
|---|
| 1307 | "next_neighbours.hlp"); |
|---|
| 1308 | } |
|---|
| 1309 | |
|---|
| 1310 | long inHitlist = GBS_hash_count_elems(list_hash); |
|---|
| 1311 | long seenInDB = 0; |
|---|
| 1312 | |
|---|
| 1313 | for (GBDATA *gb_species = GBT_first_species(cbs->gb_main); |
|---|
| 1314 | gb_species && !error; |
|---|
| 1315 | gb_species = GBT_next_species(gb_species)) |
|---|
| 1316 | { |
|---|
| 1317 | switch (mode) { |
|---|
| 1318 | case AWT_QUERY_GENERATE: CLEAR_QUERIED(gb_species, cbs); break; |
|---|
| 1319 | case AWT_QUERY_ENLARGE: if (IS_QUERIED(gb_species, cbs)) continue; break; |
|---|
| 1320 | case AWT_QUERY_REDUCE: if (!IS_QUERIED(gb_species, cbs)) continue; break; |
|---|
| 1321 | } |
|---|
| 1322 | |
|---|
| 1323 | const char *name = GBT_get_name(gb_species); |
|---|
| 1324 | const char *displayed = reinterpret_cast<const char*>(GBS_read_hash(list_hash, name)); |
|---|
| 1325 | |
|---|
| 1326 | if (displayed) seenInDB++; |
|---|
| 1327 | |
|---|
| 1328 | if ((displayed == 0) == (type == AWT_QUERY_DONT_MATCH)) { |
|---|
| 1329 | string hit_reason = GBS_global_string(hit_description, displayed ? displayed : "<no near neighbour>"); |
|---|
| 1330 | |
|---|
| 1331 | if (mode == AWT_QUERY_REDUCE) { |
|---|
| 1332 | string prev_info = getHitInfo(gb_species, cbs); |
|---|
| 1333 | hit_reason = prev_info+" (kept cause "+hit_reason+")"; |
|---|
| 1334 | } |
|---|
| 1335 | SET_QUERIED(gb_species, cbs, hit_reason.c_str(), hit_reason.length()); |
|---|
| 1336 | } |
|---|
| 1337 | else { |
|---|
| 1338 | CLEAR_QUERIED(gb_species, cbs); |
|---|
| 1339 | } |
|---|
| 1340 | } |
|---|
| 1341 | |
|---|
| 1342 | if (seenInDB < inHitlist) { |
|---|
| 1343 | aw_message(GBS_global_string("%li of %li hits were found in database", seenInDB, inHitlist)); |
|---|
| 1344 | } |
|---|
| 1345 | |
|---|
| 1346 | GBS_free_hash(list_hash); |
|---|
| 1347 | if (error) aw_message(error); |
|---|
| 1348 | awt_query_update_list(0,cbs); |
|---|
| 1349 | } |
|---|
| 1350 | |
|---|
| 1351 | |
|---|
| 1352 | void awt_search_equal_entries(AW_window *,struct adaqbsstruct *cbs, bool tokenize){ |
|---|
| 1353 | char *key = cbs->aws->get_root()->awar(cbs->awar_keys[0])->read_string(); |
|---|
| 1354 | GB_ERROR error = 0; |
|---|
| 1355 | |
|---|
| 1356 | if (strlen(key) == 0) { |
|---|
| 1357 | error = "Please select a key (in the first query expression)"; |
|---|
| 1358 | } |
|---|
| 1359 | else { |
|---|
| 1360 | GB_transaction dumy(cbs->gb_main); |
|---|
| 1361 | |
|---|
| 1362 | GBDATA *gb_species_data = GB_search(cbs->gb_main, "species_data", GB_CREATE_CONTAINER); |
|---|
| 1363 | AW_root *aw_root = cbs->aws->get_root(); |
|---|
| 1364 | long hashsize; |
|---|
| 1365 | AWT_QUERY_RANGE range = AWT_QUERY_ALL_SPECIES; |
|---|
| 1366 | AWT_QUERY_TYPES type = (AWT_QUERY_TYPES)aw_root->awar(cbs->awar_by)->read_int();; |
|---|
| 1367 | |
|---|
| 1368 | switch (cbs->selector->type) { |
|---|
| 1369 | case AWT_QUERY_ITEM_SPECIES: { |
|---|
| 1370 | hashsize = GB_number_of_subentries(gb_species_data); |
|---|
| 1371 | break; |
|---|
| 1372 | } |
|---|
| 1373 | case AWT_QUERY_ITEM_EXPERIMENTS: |
|---|
| 1374 | case AWT_QUERY_ITEM_GENES: { |
|---|
| 1375 | // handle species sub-items |
|---|
| 1376 | hashsize = 0; |
|---|
| 1377 | |
|---|
| 1378 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, cbs->aws->get_root(), range); |
|---|
| 1379 | gb_item_container; |
|---|
| 1380 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 1381 | { |
|---|
| 1382 | hashsize += GB_number_of_subentries(gb_item_container); |
|---|
| 1383 | } |
|---|
| 1384 | |
|---|
| 1385 | break; |
|---|
| 1386 | } |
|---|
| 1387 | default: { |
|---|
| 1388 | awt_assert(0); |
|---|
| 1389 | hashsize = 0; |
|---|
| 1390 | break; |
|---|
| 1391 | } |
|---|
| 1392 | } |
|---|
| 1393 | |
|---|
| 1394 | if (!hashsize) { |
|---|
| 1395 | error = "No items exist"; |
|---|
| 1396 | } |
|---|
| 1397 | else if (type == AWT_QUERY_MARKED) { |
|---|
| 1398 | error = "'that are marked' is not applicable here"; |
|---|
| 1399 | } |
|---|
| 1400 | |
|---|
| 1401 | if (!error) { |
|---|
| 1402 | GB_HASH *hash = GBS_create_hash(hashsize, GB_IGNORE_CASE); |
|---|
| 1403 | |
|---|
| 1404 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, aw_root, range); |
|---|
| 1405 | gb_item_container; |
|---|
| 1406 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 1407 | { |
|---|
| 1408 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 1409 | gb_item; |
|---|
| 1410 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 1411 | { |
|---|
| 1412 | CLEAR_QUERIED(gb_item,cbs); |
|---|
| 1413 | GB_write_flag(gb_item,0); |
|---|
| 1414 | |
|---|
| 1415 | GBDATA *gb_key = GB_search(gb_item,key,GB_FIND); if (!gb_key) continue; |
|---|
| 1416 | char *data = GB_read_as_string(gb_key); if (!data) continue; |
|---|
| 1417 | |
|---|
| 1418 | if (tokenize){ |
|---|
| 1419 | char *s; |
|---|
| 1420 | for (s=strtok(data,",; \t."); s ; s = strtok(0,",; \t.")){ |
|---|
| 1421 | GBDATA *gb_old = (GBDATA *)GBS_read_hash(hash,s); |
|---|
| 1422 | if (gb_old) { |
|---|
| 1423 | const char *oldInfo = 0; |
|---|
| 1424 | char *firstInfo = GBS_global_string_copy("1st=%s", s); |
|---|
| 1425 | |
|---|
| 1426 | if (IS_QUERIED(gb_old, cbs)) { |
|---|
| 1427 | const char *prevInfo = getHitInfo(gb_old, cbs); |
|---|
| 1428 | |
|---|
| 1429 | if (strstr(prevInfo, firstInfo) == 0) { // not already have 1st-entry here |
|---|
| 1430 | oldInfo = GBS_global_string("%s %s", prevInfo, firstInfo); |
|---|
| 1431 | } |
|---|
| 1432 | } |
|---|
| 1433 | else { |
|---|
| 1434 | oldInfo = firstInfo; |
|---|
| 1435 | } |
|---|
| 1436 | |
|---|
| 1437 | if (oldInfo) SET_QUERIED(gb_old, cbs, oldInfo); |
|---|
| 1438 | SET_QUERIED(gb_item, cbs, GBS_global_string("dup=%s", s)); |
|---|
| 1439 | GB_write_flag(gb_item, 1); |
|---|
| 1440 | |
|---|
| 1441 | free(firstInfo); |
|---|
| 1442 | } |
|---|
| 1443 | else { |
|---|
| 1444 | GBS_write_hash(hash,s,(long)gb_item); |
|---|
| 1445 | } |
|---|
| 1446 | } |
|---|
| 1447 | } |
|---|
| 1448 | else { |
|---|
| 1449 | GBDATA *gb_old = (GBDATA *)GBS_read_hash(hash,data); |
|---|
| 1450 | if (gb_old) { |
|---|
| 1451 | if (!IS_QUERIED(gb_old, cbs)) { |
|---|
| 1452 | SET_QUERIED(gb_old, cbs, GBS_global_string("%s (1st)", data)); |
|---|
| 1453 | } |
|---|
| 1454 | SET_QUERIED(gb_item, cbs, GBS_global_string("%s (duplicate)", data)); |
|---|
| 1455 | GB_write_flag(gb_item, 1); |
|---|
| 1456 | } |
|---|
| 1457 | else { |
|---|
| 1458 | GBS_write_hash(hash,data,(long)gb_item); |
|---|
| 1459 | } |
|---|
| 1460 | } |
|---|
| 1461 | |
|---|
| 1462 | free(data); |
|---|
| 1463 | } |
|---|
| 1464 | |
|---|
| 1465 | if (type == AWT_QUERY_DONT_MATCH) { |
|---|
| 1466 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 1467 | gb_item; |
|---|
| 1468 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 1469 | { |
|---|
| 1470 | if (IS_QUERIED(gb_item, cbs)) { |
|---|
| 1471 | CLEAR_QUERIED(gb_item, cbs); |
|---|
| 1472 | GB_write_flag(gb_item, 0); // unmark |
|---|
| 1473 | } |
|---|
| 1474 | else { |
|---|
| 1475 | SET_QUERIED(gb_item, cbs, tokenize ? "<entry with unique words>" : "<unique entry>"); |
|---|
| 1476 | } |
|---|
| 1477 | } |
|---|
| 1478 | } |
|---|
| 1479 | } |
|---|
| 1480 | |
|---|
| 1481 | GBS_free_hash(hash); |
|---|
| 1482 | } |
|---|
| 1483 | |
|---|
| 1484 | if (type != AWT_QUERY_MATCH) { |
|---|
| 1485 | AWT_advice("'Find equal entries' now depends on the values selected for\n" |
|---|
| 1486 | " * 'that match/don't match the query'\n" |
|---|
| 1487 | "in the search tool.", |
|---|
| 1488 | AWT_ADVICE_TOGGLE|AWT_ADVICE_HELP, |
|---|
| 1489 | "Behavior changed", |
|---|
| 1490 | "search_duplicates.hlp"); |
|---|
| 1491 | } |
|---|
| 1492 | } |
|---|
| 1493 | |
|---|
| 1494 | free(key); |
|---|
| 1495 | |
|---|
| 1496 | if (error) aw_message(error); |
|---|
| 1497 | awt_query_update_list(0,cbs); |
|---|
| 1498 | } |
|---|
| 1499 | |
|---|
| 1500 | /***************** Pars fields *************************/ |
|---|
| 1501 | |
|---|
| 1502 | void awt_do_pars_list(void *dummy, struct adaqbsstruct *cbs) |
|---|
| 1503 | { |
|---|
| 1504 | AWUSE(dummy); |
|---|
| 1505 | GB_ERROR error = 0; |
|---|
| 1506 | char *key = cbs->aws->get_root()->awar(cbs->awar_parskey)->read_string(); |
|---|
| 1507 | |
|---|
| 1508 | if (!strcmp(key,"name")){ |
|---|
| 1509 | switch (cbs->selector->type) { |
|---|
| 1510 | case AWT_QUERY_ITEM_SPECIES: { |
|---|
| 1511 | if (aw_question("WARNING WARNING WARNING!!! You now try to rename the species\n" |
|---|
| 1512 | " The name is used to link database entries and trees\n" |
|---|
| 1513 | " -> ALL TREES WILL BE LOST\n" |
|---|
| 1514 | " -> The new name MUST be UNIQUE" |
|---|
| 1515 | " if not you will corrupt the database!" , |
|---|
| 1516 | "Let's Go,Cancel")) return; |
|---|
| 1517 | break; |
|---|
| 1518 | } |
|---|
| 1519 | case AWT_QUERY_ITEM_GENES: { |
|---|
| 1520 | if (aw_question("WARNING! You now try to rename the gene\n" |
|---|
| 1521 | " -> Pseudo-species will loose their link to the gene" |
|---|
| 1522 | " -> The new name MUST be UNIQUE" |
|---|
| 1523 | " if not you will corrupt the database!" , |
|---|
| 1524 | "Let's Go,Cancel")) return; |
|---|
| 1525 | break; |
|---|
| 1526 | } |
|---|
| 1527 | case AWT_QUERY_ITEM_EXPERIMENTS: { |
|---|
| 1528 | if (aw_question("WARNING! You now try to rename the experiment\n" |
|---|
| 1529 | " -> The new name MUST be UNIQUE" |
|---|
| 1530 | " if not you will corrupt the database!" , |
|---|
| 1531 | "Let's Go,Cancel")) return; |
|---|
| 1532 | break; |
|---|
| 1533 | } |
|---|
| 1534 | default: { |
|---|
| 1535 | awt_assert(0); |
|---|
| 1536 | return; |
|---|
| 1537 | } |
|---|
| 1538 | } |
|---|
| 1539 | } |
|---|
| 1540 | |
|---|
| 1541 | |
|---|
| 1542 | if (!strlen(key)) error = "Please select a valid key"; |
|---|
| 1543 | |
|---|
| 1544 | char *command = cbs->aws->get_root()->awar(cbs->awar_parsvalue)->read_string(); |
|---|
| 1545 | if (!error && !strlen(command)) { |
|---|
| 1546 | error = "Please enter your command"; |
|---|
| 1547 | } |
|---|
| 1548 | if (!error) { |
|---|
| 1549 | GB_begin_transaction(cbs->gb_main); |
|---|
| 1550 | |
|---|
| 1551 | GBDATA *gb_key_name; |
|---|
| 1552 | { |
|---|
| 1553 | GBDATA *gb_key_data = GB_search(cbs->gb_main, cbs->selector->change_key_path, GB_CREATE_CONTAINER); |
|---|
| 1554 | while (!error && !(gb_key_name = GB_find_string(gb_key_data,CHANGEKEY_NAME,key,GB_IGNORE_CASE,down_2_level))) { |
|---|
| 1555 | const char *question = GBS_global_string("The destination field '%s' does not exists", key); |
|---|
| 1556 | if (aw_question(question, "Create Field (Type STRING),Cancel")) { |
|---|
| 1557 | error = "Aborted by user"; |
|---|
| 1558 | } |
|---|
| 1559 | else { |
|---|
| 1560 | error = GBT_add_new_changekey_to_keypath(cbs->gb_main,key,GB_STRING, cbs->selector->change_key_path); |
|---|
| 1561 | } |
|---|
| 1562 | } |
|---|
| 1563 | } |
|---|
| 1564 | |
|---|
| 1565 | GBDATA *gb_key_type; |
|---|
| 1566 | if (!error) { |
|---|
| 1567 | gb_key_type = GB_brother(gb_key_name,CHANGEKEY_TYPE); |
|---|
| 1568 | |
|---|
| 1569 | if (!gb_key_type) error = GB_await_error(); |
|---|
| 1570 | else { |
|---|
| 1571 | if (GB_read_int(gb_key_type)!=GB_STRING && |
|---|
| 1572 | aw_question("Writing to a non-STRING database field may lead to conversion problems.", "Abort,Continue")==0) |
|---|
| 1573 | { |
|---|
| 1574 | error = "Aborted by user"; |
|---|
| 1575 | } |
|---|
| 1576 | } |
|---|
| 1577 | } |
|---|
| 1578 | |
|---|
| 1579 | if (!error) { |
|---|
| 1580 | long count = 0; |
|---|
| 1581 | long ncount = cbs->aws->get_root()->awar(cbs->awar_count)->read_int(); |
|---|
| 1582 | char *deftag = cbs->aws->get_root()->awar(cbs->awar_deftag)->read_string(); |
|---|
| 1583 | char *tag = cbs->aws->get_root()->awar(cbs->awar_tag)->read_string(); |
|---|
| 1584 | |
|---|
| 1585 | { |
|---|
| 1586 | long use_tag = cbs->aws->get_root()->awar(cbs->awar_use_tag)->read_int(); |
|---|
| 1587 | if (!use_tag || !strlen(tag)) { |
|---|
| 1588 | freeset(tag, 0); |
|---|
| 1589 | } |
|---|
| 1590 | } |
|---|
| 1591 | int double_pars = cbs->aws->get_root()->awar(cbs->awar_double_pars)->read_int(); |
|---|
| 1592 | |
|---|
| 1593 | aw_openstatus("Pars Fields"); |
|---|
| 1594 | |
|---|
| 1595 | AW_root *aw_root = cbs->aws->get_root(); |
|---|
| 1596 | AWT_QUERY_RANGE range = (AWT_QUERY_RANGE)aw_root->awar(cbs->awar_where)->read_int(); |
|---|
| 1597 | |
|---|
| 1598 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, aw_root, range); |
|---|
| 1599 | !error && gb_item_container; |
|---|
| 1600 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 1601 | { |
|---|
| 1602 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 1603 | !error && gb_item; |
|---|
| 1604 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 1605 | { |
|---|
| 1606 | if (IS_QUERIED(gb_item,cbs)) { |
|---|
| 1607 | if (aw_status((count++)/(double)ncount)) { |
|---|
| 1608 | error = "Aborted by user"; |
|---|
| 1609 | break; |
|---|
| 1610 | } |
|---|
| 1611 | GBDATA *gb_new = GB_search(gb_item, key,GB_FIND); |
|---|
| 1612 | char *str = gb_new ? GB_read_as_string(gb_new) : strdup(""); |
|---|
| 1613 | char *parsed = 0; |
|---|
| 1614 | |
|---|
| 1615 | if (double_pars) { |
|---|
| 1616 | char *com2 = GB_command_interpreter(cbs->gb_main, str,command,gb_item, cbs->tree_name); |
|---|
| 1617 | if (com2) { |
|---|
| 1618 | if (tag) parsed = GBS_string_eval_tagged_string(cbs->gb_main, "", deftag, tag, 0, com2, gb_item); |
|---|
| 1619 | else parsed = GB_command_interpreter (cbs->gb_main, "", com2, gb_item, cbs->tree_name); |
|---|
| 1620 | } |
|---|
| 1621 | free(com2); |
|---|
| 1622 | } |
|---|
| 1623 | else { |
|---|
| 1624 | if (tag) parsed = GBS_string_eval_tagged_string(cbs->gb_main, str, deftag, tag, 0, command,gb_item); |
|---|
| 1625 | else parsed = GB_command_interpreter (cbs->gb_main, str, command, gb_item, cbs->tree_name); |
|---|
| 1626 | } |
|---|
| 1627 | |
|---|
| 1628 | if (!parsed) error = GB_await_error(); |
|---|
| 1629 | else { |
|---|
| 1630 | if (strcmp(parsed, str) != 0) { // any change? |
|---|
| 1631 | if (gb_new && parsed[0] == 0) { // empty result -> delete field |
|---|
| 1632 | error = GB_delete(gb_new); |
|---|
| 1633 | } |
|---|
| 1634 | else { |
|---|
| 1635 | if (!gb_new) { |
|---|
| 1636 | gb_new = GB_search(gb_item, key, GB_read_int(gb_key_type)); |
|---|
| 1637 | if (!gb_new) error = GB_await_error(); |
|---|
| 1638 | } |
|---|
| 1639 | if (!error) error = GB_write_as_string(gb_new, parsed); |
|---|
| 1640 | } |
|---|
| 1641 | } |
|---|
| 1642 | free(parsed); |
|---|
| 1643 | } |
|---|
| 1644 | free(str); |
|---|
| 1645 | } |
|---|
| 1646 | } |
|---|
| 1647 | } |
|---|
| 1648 | |
|---|
| 1649 | |
|---|
| 1650 | aw_closestatus(); |
|---|
| 1651 | delete tag; |
|---|
| 1652 | free(deftag); |
|---|
| 1653 | } |
|---|
| 1654 | |
|---|
| 1655 | error = GB_end_transaction(cbs->gb_main, error); |
|---|
| 1656 | } |
|---|
| 1657 | |
|---|
| 1658 | if (error) aw_message(error); |
|---|
| 1659 | |
|---|
| 1660 | free(key); |
|---|
| 1661 | free(command); |
|---|
| 1662 | } |
|---|
| 1663 | |
|---|
| 1664 | void awt_predef_prg(AW_root *aw_root, struct adaqbsstruct *cbs){ |
|---|
| 1665 | char *str = aw_root->awar(cbs->awar_parspredefined)->read_string(); |
|---|
| 1666 | char *brk = strchr(str,'#'); |
|---|
| 1667 | if (brk) { |
|---|
| 1668 | *(brk++) = 0; |
|---|
| 1669 | char *kv = str; |
|---|
| 1670 | if (!strcmp(str,"ali_*/data")){ |
|---|
| 1671 | GB_transaction valid_transaction(cbs->gb_main); |
|---|
| 1672 | char *use = GBT_get_default_alignment(cbs->gb_main); |
|---|
| 1673 | kv = GBS_global_string_copy("%s/data",use); |
|---|
| 1674 | free(use); |
|---|
| 1675 | } |
|---|
| 1676 | aw_root->awar(cbs->awar_parskey)->write_string( kv); |
|---|
| 1677 | if (kv != str) free(kv); |
|---|
| 1678 | aw_root->awar(cbs->awar_parsvalue)->write_string( brk); |
|---|
| 1679 | }else{ |
|---|
| 1680 | aw_root->awar(cbs->awar_parsvalue)->write_string( str); |
|---|
| 1681 | } |
|---|
| 1682 | free(str); |
|---|
| 1683 | } |
|---|
| 1684 | |
|---|
| 1685 | char *AWT_get_item_id(GBDATA *gb_main, const ad_item_selector *sel, GBDATA *gb_item) { |
|---|
| 1686 | return sel->generate_item_id(gb_main, gb_item); |
|---|
| 1687 | } |
|---|
| 1688 | |
|---|
| 1689 | GBDATA *AWT_get_item_with_id(GBDATA *gb_main, const ad_item_selector *sel, const char *id) { |
|---|
| 1690 | return sel->find_item_by_id(gb_main, id); |
|---|
| 1691 | } |
|---|
| 1692 | |
|---|
| 1693 | static void awt_colorize_listed(AW_window */*dummy*/, AW_CL cl_cbs) { |
|---|
| 1694 | struct adaqbsstruct *cbs = (struct adaqbsstruct *)cl_cbs; |
|---|
| 1695 | GB_transaction trans_dummy(cbs->gb_main); |
|---|
| 1696 | GB_ERROR error = 0; |
|---|
| 1697 | AW_root *aw_root = cbs->aws->get_root(); |
|---|
| 1698 | int color_group = aw_root->awar(AWAR_COLORIZE)->read_int(); |
|---|
| 1699 | AWT_QUERY_RANGE range = (AWT_QUERY_RANGE)aw_root->awar(cbs->awar_where)->read_int(); |
|---|
| 1700 | |
|---|
| 1701 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, aw_root, range); |
|---|
| 1702 | !error && gb_item_container; |
|---|
| 1703 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 1704 | { |
|---|
| 1705 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 1706 | !error && gb_item; |
|---|
| 1707 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 1708 | { |
|---|
| 1709 | if (IS_QUERIED(gb_item,cbs)) { |
|---|
| 1710 | error = AW_set_color_group(gb_item, color_group); |
|---|
| 1711 | } |
|---|
| 1712 | } |
|---|
| 1713 | } |
|---|
| 1714 | |
|---|
| 1715 | if (error) GB_export_error(error); |
|---|
| 1716 | } |
|---|
| 1717 | |
|---|
| 1718 | struct color_mark_data { |
|---|
| 1719 | const ad_item_selector *sel; |
|---|
| 1720 | GBDATA *gb_main; |
|---|
| 1721 | }; |
|---|
| 1722 | |
|---|
| 1723 | static void awt_colorize_marked(AW_window *aww, AW_CL cl_cmd) { |
|---|
| 1724 | const color_mark_data *cmd = (struct color_mark_data *)cl_cmd; |
|---|
| 1725 | const ad_item_selector *sel = cmd->sel; |
|---|
| 1726 | GB_transaction trans_dummy(cmd->gb_main); |
|---|
| 1727 | GB_ERROR error = 0; |
|---|
| 1728 | AW_root *aw_root = aww->get_root(); |
|---|
| 1729 | int color_group = aw_root->awar(AWAR_COLORIZE)->read_int(); |
|---|
| 1730 | AWT_QUERY_RANGE range = AWT_QUERY_ALL_SPECIES; // @@@ FIXME: make customizable |
|---|
| 1731 | |
|---|
| 1732 | for (GBDATA *gb_item_container = sel->get_first_item_container(cmd->gb_main, aw_root, range); |
|---|
| 1733 | !error && gb_item_container; |
|---|
| 1734 | gb_item_container = sel->get_next_item_container(gb_item_container, range)) |
|---|
| 1735 | { |
|---|
| 1736 | for (GBDATA *gb_item = sel->get_first_item(gb_item_container); |
|---|
| 1737 | !error && gb_item; |
|---|
| 1738 | gb_item = sel->get_next_item(gb_item)) |
|---|
| 1739 | { |
|---|
| 1740 | if (GB_read_flag(gb_item)) { |
|---|
| 1741 | error = AW_set_color_group(gb_item, color_group); |
|---|
| 1742 | } |
|---|
| 1743 | } |
|---|
| 1744 | } |
|---|
| 1745 | |
|---|
| 1746 | if (error) GB_export_error(error); |
|---|
| 1747 | } |
|---|
| 1748 | |
|---|
| 1749 | // @@@ awt_mark_colored is obsolete! (will be replaced by dynamic coloring in the future) |
|---|
| 1750 | static void awt_mark_colored(AW_window *aww, AW_CL cl_cmd, AW_CL cl_mode) |
|---|
| 1751 | { |
|---|
| 1752 | const color_mark_data *cmd = (struct color_mark_data *)cl_cmd; |
|---|
| 1753 | const ad_item_selector *sel = cmd->sel; |
|---|
| 1754 | int mode = int(cl_mode); // 0 = unmark 1 = mark 2 = invert |
|---|
| 1755 | GB_ERROR error = 0; |
|---|
| 1756 | AW_root *aw_root = aww->get_root(); |
|---|
| 1757 | int color_group = aw_root->awar(AWAR_COLORIZE)->read_int(); |
|---|
| 1758 | AWT_QUERY_RANGE range = AWT_QUERY_ALL_SPECIES; // @@@ FIXME: make customizable |
|---|
| 1759 | |
|---|
| 1760 | GB_transaction trans_dummy(cmd->gb_main); |
|---|
| 1761 | |
|---|
| 1762 | for (GBDATA *gb_item_container = sel->get_first_item_container(cmd->gb_main, aw_root, range); |
|---|
| 1763 | !error && gb_item_container; |
|---|
| 1764 | gb_item_container = sel->get_next_item_container(gb_item_container, range)) |
|---|
| 1765 | { |
|---|
| 1766 | for (GBDATA *gb_item = sel->get_first_item(gb_item_container); |
|---|
| 1767 | !error && gb_item; |
|---|
| 1768 | gb_item = sel->get_next_item(gb_item)) |
|---|
| 1769 | { |
|---|
| 1770 | long my_color = AW_find_color_group(gb_item, true); |
|---|
| 1771 | if (my_color == color_group) { |
|---|
| 1772 | bool marked = GB_read_flag(gb_item); |
|---|
| 1773 | |
|---|
| 1774 | switch (mode) { |
|---|
| 1775 | case 0: marked = 0; break; |
|---|
| 1776 | case 1: marked = 1; break; |
|---|
| 1777 | case 2: marked = !marked; break; |
|---|
| 1778 | default : awt_assert(0); break; |
|---|
| 1779 | } |
|---|
| 1780 | |
|---|
| 1781 | error = GB_write_flag(gb_item, marked); |
|---|
| 1782 | } |
|---|
| 1783 | } |
|---|
| 1784 | } |
|---|
| 1785 | |
|---|
| 1786 | if (error) GB_export_error(error); |
|---|
| 1787 | } |
|---|
| 1788 | |
|---|
| 1789 | // -------------------------------------------------------------------------------- |
|---|
| 1790 | // color sets |
|---|
| 1791 | |
|---|
| 1792 | struct color_save_data { |
|---|
| 1793 | color_mark_data *cmd; |
|---|
| 1794 | const char *items_name; |
|---|
| 1795 | AW_window *aww; // window of selection list |
|---|
| 1796 | AW_selection_list *sel_id; |
|---|
| 1797 | }; |
|---|
| 1798 | |
|---|
| 1799 | #define AWT_COLOR_LOADSAVE_NAME "tmp/colorset/name" |
|---|
| 1800 | |
|---|
| 1801 | static GBDATA *get_colorset_root(const color_save_data *csd) { |
|---|
| 1802 | GBDATA *gb_main = csd->cmd->gb_main; |
|---|
| 1803 | GBDATA *gb_colorsets = GB_search(gb_main, "colorsets", GB_CREATE_CONTAINER); |
|---|
| 1804 | GBDATA *gb_item_root = GB_search(gb_colorsets, csd->items_name, GB_CREATE_CONTAINER); |
|---|
| 1805 | |
|---|
| 1806 | awt_assert(gb_item_root); |
|---|
| 1807 | return gb_item_root; |
|---|
| 1808 | } |
|---|
| 1809 | |
|---|
| 1810 | static void update_colorset_selection_list(const color_save_data *csd) { |
|---|
| 1811 | GB_transaction ta(csd->cmd->gb_main); |
|---|
| 1812 | AW_window *aww = csd->aww; |
|---|
| 1813 | |
|---|
| 1814 | aww->clear_selection_list(csd->sel_id); |
|---|
| 1815 | GBDATA *gb_item_root = get_colorset_root(csd); |
|---|
| 1816 | |
|---|
| 1817 | for (GBDATA *gb_colorset = GB_entry(gb_item_root, "colorset"); |
|---|
| 1818 | gb_colorset; |
|---|
| 1819 | gb_colorset = GB_nextEntry(gb_colorset)) |
|---|
| 1820 | { |
|---|
| 1821 | const char *name = GBT_read_name(gb_colorset); |
|---|
| 1822 | aww->insert_selection(csd->sel_id, name, name); |
|---|
| 1823 | } |
|---|
| 1824 | aww->insert_default_selection(csd->sel_id, "<new colorset>", ""); |
|---|
| 1825 | |
|---|
| 1826 | aww->update_selection_list(csd->sel_id); |
|---|
| 1827 | } |
|---|
| 1828 | |
|---|
| 1829 | static void colorset_changed_cb(GBDATA*, int *cl_csd, GB_CB_TYPE cbt) { |
|---|
| 1830 | if (cbt&GB_CB_CHANGED) { |
|---|
| 1831 | const color_save_data *csd = (const color_save_data*)cl_csd; |
|---|
| 1832 | update_colorset_selection_list(csd); |
|---|
| 1833 | } |
|---|
| 1834 | } |
|---|
| 1835 | |
|---|
| 1836 | static char *create_colorset_representation(const color_save_data *csd, GB_ERROR& error) { |
|---|
| 1837 | const color_mark_data *cmd = csd->cmd; |
|---|
| 1838 | const ad_item_selector *sel = cmd->sel; |
|---|
| 1839 | AWT_QUERY_RANGE range = AWT_QUERY_ALL_SPECIES; |
|---|
| 1840 | AW_root *aw_root = csd->aww->get_root(); |
|---|
| 1841 | GBDATA *gb_main = cmd->gb_main; |
|---|
| 1842 | |
|---|
| 1843 | typedef list<string> ColorList; |
|---|
| 1844 | ColorList cl; |
|---|
| 1845 | |
|---|
| 1846 | for (GBDATA *gb_item_container = sel->get_first_item_container(cmd->gb_main, aw_root, range); |
|---|
| 1847 | !error && gb_item_container; |
|---|
| 1848 | gb_item_container = sel->get_next_item_container(gb_item_container, range)) |
|---|
| 1849 | { |
|---|
| 1850 | for (GBDATA *gb_item = sel->get_first_item(gb_item_container); |
|---|
| 1851 | !error && gb_item; |
|---|
| 1852 | gb_item = sel->get_next_item(gb_item)) |
|---|
| 1853 | { |
|---|
| 1854 | long color = AW_find_color_group(gb_item, true); |
|---|
| 1855 | char *id = sel->generate_item_id(gb_main, gb_item); |
|---|
| 1856 | const char *color_def = GBS_global_string("%s=%li", id, color); |
|---|
| 1857 | cl.push_front(color_def); |
|---|
| 1858 | free(id); |
|---|
| 1859 | } |
|---|
| 1860 | } |
|---|
| 1861 | |
|---|
| 1862 | char *result = 0; |
|---|
| 1863 | if (cl.empty()) { |
|---|
| 1864 | error = GBS_global_string("Could not find any %s", sel->items_name); |
|---|
| 1865 | } |
|---|
| 1866 | else { |
|---|
| 1867 | string res; |
|---|
| 1868 | for (ColorList::iterator ci = cl.begin(); ci != cl.end(); ++ci) { |
|---|
| 1869 | res += (*ci) + ';'; |
|---|
| 1870 | } |
|---|
| 1871 | |
|---|
| 1872 | result = (char*)malloc(res.length()); |
|---|
| 1873 | memcpy(result, res.c_str(), res.length()-1); // skip trailing ';' |
|---|
| 1874 | result[res.length()] = 0; |
|---|
| 1875 | } |
|---|
| 1876 | return result; |
|---|
| 1877 | } |
|---|
| 1878 | |
|---|
| 1879 | static GB_ERROR clear_all_colors(const color_save_data *csd) { |
|---|
| 1880 | const color_mark_data *cmd = csd->cmd; |
|---|
| 1881 | const ad_item_selector *sel = cmd->sel; |
|---|
| 1882 | AWT_QUERY_RANGE range = AWT_QUERY_ALL_SPECIES; |
|---|
| 1883 | AW_root *aw_root = csd->aww->get_root(); |
|---|
| 1884 | GB_ERROR error = 0; |
|---|
| 1885 | |
|---|
| 1886 | for (GBDATA *gb_item_container = sel->get_first_item_container(cmd->gb_main, aw_root, range); |
|---|
| 1887 | !error && gb_item_container; |
|---|
| 1888 | gb_item_container = sel->get_next_item_container(gb_item_container, range)) |
|---|
| 1889 | { |
|---|
| 1890 | for (GBDATA *gb_item = sel->get_first_item(gb_item_container); |
|---|
| 1891 | !error && gb_item; |
|---|
| 1892 | gb_item = sel->get_next_item(gb_item)) |
|---|
| 1893 | { |
|---|
| 1894 | error = AW_set_color_group(gb_item, 0); // clear colors |
|---|
| 1895 | } |
|---|
| 1896 | } |
|---|
| 1897 | |
|---|
| 1898 | return error; |
|---|
| 1899 | } |
|---|
| 1900 | |
|---|
| 1901 | static void awt_clear_all_colors(AW_window *, AW_CL cl_csd) { |
|---|
| 1902 | const color_save_data *csd = (const color_save_data*)cl_csd; |
|---|
| 1903 | GB_transaction ta(csd->cmd->gb_main); |
|---|
| 1904 | GB_ERROR error = clear_all_colors(csd); |
|---|
| 1905 | |
|---|
| 1906 | if (error) { |
|---|
| 1907 | error = ta.close(error); |
|---|
| 1908 | aw_message(error); |
|---|
| 1909 | } |
|---|
| 1910 | } |
|---|
| 1911 | |
|---|
| 1912 | static GB_ERROR restore_colorset_representation(const color_save_data *csd, const char *colorset) { |
|---|
| 1913 | const color_mark_data *cmd = csd->cmd; |
|---|
| 1914 | const ad_item_selector *sel = cmd->sel; |
|---|
| 1915 | GBDATA *gb_main = cmd->gb_main; |
|---|
| 1916 | |
|---|
| 1917 | int buffersize = 200; |
|---|
| 1918 | char *buffer = (char*)malloc(buffersize); |
|---|
| 1919 | |
|---|
| 1920 | while (colorset) { |
|---|
| 1921 | const char *equal = strchr(colorset, '='); |
|---|
| 1922 | awt_assert(equal); |
|---|
| 1923 | const char *semi = strchr(equal, ';'); |
|---|
| 1924 | |
|---|
| 1925 | int size = equal-colorset; |
|---|
| 1926 | if (size >= buffersize) { |
|---|
| 1927 | buffersize = int(size*1.5); |
|---|
| 1928 | freeset(buffer, (char*)malloc(buffersize)); |
|---|
| 1929 | } |
|---|
| 1930 | |
|---|
| 1931 | awt_assert(buffer && buffersize>size); |
|---|
| 1932 | memcpy(buffer, colorset, size); |
|---|
| 1933 | buffer[size] = 0; // now buffer contains the item id |
|---|
| 1934 | |
|---|
| 1935 | GBDATA *gb_item = AWT_get_item_with_id(gb_main, sel, buffer); |
|---|
| 1936 | if (!gb_item) { |
|---|
| 1937 | aw_message(GBS_global_string("No such %s: '%s'", sel->item_name, buffer)); |
|---|
| 1938 | } |
|---|
| 1939 | else { |
|---|
| 1940 | int color_group = atoi(equal+1); |
|---|
| 1941 | AW_set_color_group(gb_item, color_group); |
|---|
| 1942 | } |
|---|
| 1943 | colorset = semi ? semi+1 : 0; |
|---|
| 1944 | } |
|---|
| 1945 | |
|---|
| 1946 | free(buffer); |
|---|
| 1947 | return 0; |
|---|
| 1948 | } |
|---|
| 1949 | |
|---|
| 1950 | static void awt_loadsave_colorset(AW_window *aws, AW_CL cl_csd, AW_CL cl_mode) { |
|---|
| 1951 | const color_save_data *csd = (const color_save_data*)cl_csd; |
|---|
| 1952 | int mode = (int)cl_mode; // 0 = save; 1 = load; 2 = overlay; 3 = delete; |
|---|
| 1953 | AW_root *aw_root = aws->get_root(); |
|---|
| 1954 | char *name = aw_root->awar(AWT_COLOR_LOADSAVE_NAME)->read_string(); |
|---|
| 1955 | GB_ERROR error = 0; |
|---|
| 1956 | |
|---|
| 1957 | if (name[0] == 0) { |
|---|
| 1958 | error = "Please enter a name for the colorset."; |
|---|
| 1959 | } |
|---|
| 1960 | else { |
|---|
| 1961 | GB_transaction ta(csd->cmd->gb_main); |
|---|
| 1962 | GBDATA *gb_colorset_root = get_colorset_root(csd); |
|---|
| 1963 | awt_assert(gb_colorset_root); |
|---|
| 1964 | |
|---|
| 1965 | GBDATA *gb_colorset_name = GB_find_string(gb_colorset_root, "name", name, GB_IGNORE_CASE, down_2_level); |
|---|
| 1966 | GBDATA *gb_colorset = gb_colorset_name ? GB_get_father(gb_colorset_name) : 0; |
|---|
| 1967 | if (mode == 0) { // save-mode |
|---|
| 1968 | if (!gb_colorset) { // create new (otherwise overwrite w/o comment) |
|---|
| 1969 | gb_colorset = GB_create_container(gb_colorset_root, "colorset"); |
|---|
| 1970 | if (!gb_colorset) error = GB_await_error(); |
|---|
| 1971 | else error = GBT_write_string(gb_colorset, "name", name); |
|---|
| 1972 | } |
|---|
| 1973 | if (!error) { |
|---|
| 1974 | char *colorset = create_colorset_representation(csd, error); |
|---|
| 1975 | if (colorset) { |
|---|
| 1976 | error = GBT_write_string(gb_colorset, "color_set", colorset); |
|---|
| 1977 | free(colorset); |
|---|
| 1978 | } |
|---|
| 1979 | } |
|---|
| 1980 | } |
|---|
| 1981 | else { // load/delete |
|---|
| 1982 | if (!gb_colorset) { |
|---|
| 1983 | error = GBS_global_string("Colorset '%s' not found", name); |
|---|
| 1984 | } |
|---|
| 1985 | else { |
|---|
| 1986 | if (mode == 1 || mode == 2) { // load- and overlay-mode |
|---|
| 1987 | GBDATA *gb_set = GB_entry(gb_colorset, "color_set"); |
|---|
| 1988 | if (!gb_set) { |
|---|
| 1989 | error = "colorset is empty (oops)"; |
|---|
| 1990 | } |
|---|
| 1991 | else { |
|---|
| 1992 | const char *colorset = GB_read_char_pntr(gb_set); |
|---|
| 1993 | if (!colorset) error = GB_await_error(); |
|---|
| 1994 | else { |
|---|
| 1995 | if (mode == 1) { // load => clear all colors |
|---|
| 1996 | error = clear_all_colors(csd); |
|---|
| 1997 | } |
|---|
| 1998 | if (!error) { |
|---|
| 1999 | error = restore_colorset_representation(csd, colorset); |
|---|
| 2000 | } |
|---|
| 2001 | } |
|---|
| 2002 | } |
|---|
| 2003 | } |
|---|
| 2004 | else { |
|---|
| 2005 | awt_assert(mode == 3); // delete-mode |
|---|
| 2006 | error = GB_delete(gb_colorset); |
|---|
| 2007 | } |
|---|
| 2008 | } |
|---|
| 2009 | } |
|---|
| 2010 | |
|---|
| 2011 | error = ta.close(error); |
|---|
| 2012 | } |
|---|
| 2013 | free(name); |
|---|
| 2014 | |
|---|
| 2015 | if (error) aw_message(error); |
|---|
| 2016 | } |
|---|
| 2017 | |
|---|
| 2018 | static AW_window *awt_create_loadsave_colored_window(AW_root *aw_root, AW_CL cl_csd) { |
|---|
| 2019 | static AW_window **aw_loadsave = 0; |
|---|
| 2020 | if (!aw_loadsave) { |
|---|
| 2021 | // init data |
|---|
| 2022 | aw_root->awar_string(AWT_COLOR_LOADSAVE_NAME, "", AW_ROOT_DEFAULT); |
|---|
| 2023 | aw_loadsave = (AW_window**)GB_calloc(AWT_QUERY_ITEM_TYPES, sizeof(*aw_loadsave)); // contains loadsave windows for each item type |
|---|
| 2024 | } |
|---|
| 2025 | |
|---|
| 2026 | color_save_data *csd = (color_save_data*)cl_csd; |
|---|
| 2027 | AWT_QUERY_ITEM_TYPE type = csd->cmd->sel->type; |
|---|
| 2028 | |
|---|
| 2029 | awt_assert(type<AWT_QUERY_ITEM_TYPES); |
|---|
| 2030 | |
|---|
| 2031 | if (!aw_loadsave[type]) { |
|---|
| 2032 | // init window |
|---|
| 2033 | AW_window_simple *aws = new AW_window_simple; |
|---|
| 2034 | { |
|---|
| 2035 | char *window_id = GBS_global_string_copy("colorset_loadsave_%s", csd->items_name); |
|---|
| 2036 | aws->init(aw_root, window_id, GBS_global_string("Load/Save %s colorset", csd->items_name)); |
|---|
| 2037 | free(window_id); |
|---|
| 2038 | } |
|---|
| 2039 | |
|---|
| 2040 | aws->load_xfig("color_loadsave.fig"); |
|---|
| 2041 | |
|---|
| 2042 | aws->at("close"); |
|---|
| 2043 | aws->callback((AW_CB0) AW_POPDOWN); |
|---|
| 2044 | aws->create_button("CLOSE","CLOSE", "C"); |
|---|
| 2045 | |
|---|
| 2046 | aws->at("help"); |
|---|
| 2047 | aws->callback(AW_POPUP_HELP,(AW_CL)"color_loadsave.hlp"); |
|---|
| 2048 | aws->create_button("HELP","HELP","H"); |
|---|
| 2049 | |
|---|
| 2050 | aws->at("name"); |
|---|
| 2051 | aws->create_input_field(AWT_COLOR_LOADSAVE_NAME, 60); |
|---|
| 2052 | |
|---|
| 2053 | awt_assert(csd->sel_id == 0); |
|---|
| 2054 | aws->at("list"); |
|---|
| 2055 | csd->sel_id = aws->create_selection_list(AWT_COLOR_LOADSAVE_NAME, 0, 0, 0, 0); |
|---|
| 2056 | csd->aww = aws; |
|---|
| 2057 | |
|---|
| 2058 | update_colorset_selection_list(csd); |
|---|
| 2059 | |
|---|
| 2060 | aws->at("save"); |
|---|
| 2061 | aws->callback(awt_loadsave_colorset, (AW_CL)csd, (AW_CL)0); // 0 = save |
|---|
| 2062 | aws->create_button("save", "Save", "S"); |
|---|
| 2063 | |
|---|
| 2064 | aws->at("load"); |
|---|
| 2065 | aws->callback(awt_loadsave_colorset, (AW_CL)csd, (AW_CL)1); // 1 = load |
|---|
| 2066 | aws->create_button("load", "Load", "L"); |
|---|
| 2067 | |
|---|
| 2068 | aws->at("overlay"); |
|---|
| 2069 | aws->callback(awt_loadsave_colorset, (AW_CL)csd, (AW_CL)2); // 2 = overlay |
|---|
| 2070 | aws->create_button("overlay", "Overlay", "O"); |
|---|
| 2071 | |
|---|
| 2072 | aws->at("delete"); |
|---|
| 2073 | aws->callback(awt_loadsave_colorset, (AW_CL)csd, (AW_CL)3); // 3 = delete |
|---|
| 2074 | aws->create_button("delete", "Delete", "D"); |
|---|
| 2075 | |
|---|
| 2076 | aws->at("reset"); |
|---|
| 2077 | aws->callback(awt_clear_all_colors, (AW_CL)csd); |
|---|
| 2078 | aws->create_button("reset", "Reset", "R"); |
|---|
| 2079 | |
|---|
| 2080 | // callbacks |
|---|
| 2081 | { |
|---|
| 2082 | GB_transaction ta(csd->cmd->gb_main); |
|---|
| 2083 | GBDATA *gb_colorset = get_colorset_root(csd); |
|---|
| 2084 | GB_add_callback(gb_colorset, GB_CB_CHANGED, colorset_changed_cb, (int*)csd); |
|---|
| 2085 | } |
|---|
| 2086 | |
|---|
| 2087 | aw_loadsave[type] = aws; |
|---|
| 2088 | } |
|---|
| 2089 | |
|---|
| 2090 | return aw_loadsave[type]; |
|---|
| 2091 | } |
|---|
| 2092 | |
|---|
| 2093 | static const char *color_group_name(int color_group) { |
|---|
| 2094 | static char buf[30]; |
|---|
| 2095 | |
|---|
| 2096 | if (color_group) { |
|---|
| 2097 | sprintf(buf, "color group %i", color_group); |
|---|
| 2098 | } |
|---|
| 2099 | else { |
|---|
| 2100 | strcpy(buf, "no color group"); |
|---|
| 2101 | } |
|---|
| 2102 | |
|---|
| 2103 | return buf; |
|---|
| 2104 | } |
|---|
| 2105 | |
|---|
| 2106 | static AW_window *create_awt_colorizer_window(AW_root *aw_root, GBDATA *gb_main, struct adaqbsstruct *cbs, const ad_item_selector *sel) { |
|---|
| 2107 | // invoked by 'colorize listed' (sel != 0) |
|---|
| 2108 | // and 'colorize marked/mark colored' (cbs != 0) |
|---|
| 2109 | |
|---|
| 2110 | enum { AWT_COL_INVALID, AWT_COL_COLORIZE_LISTED, AWT_COL_COLORIZE_MARKED } mode = AWT_COL_INVALID; |
|---|
| 2111 | |
|---|
| 2112 | awt_query_create_global_awars(aw_root, AW_ROOT_DEFAULT); |
|---|
| 2113 | |
|---|
| 2114 | AW_window_simple *aws = new AW_window_simple; |
|---|
| 2115 | |
|---|
| 2116 | if (cbs) { |
|---|
| 2117 | awt_assert(mode == AWT_COL_INVALID); |
|---|
| 2118 | mode = AWT_COL_COLORIZE_LISTED; |
|---|
| 2119 | } |
|---|
| 2120 | if (sel) { |
|---|
| 2121 | awt_assert(mode == AWT_COL_INVALID); |
|---|
| 2122 | mode = AWT_COL_COLORIZE_MARKED; |
|---|
| 2123 | } |
|---|
| 2124 | awt_assert(!(mode == AWT_COL_INVALID)); |
|---|
| 2125 | |
|---|
| 2126 | const ad_item_selector *Sel = mode == AWT_COL_COLORIZE_LISTED ? cbs->selector : sel; |
|---|
| 2127 | const char *what = mode == AWT_COL_COLORIZE_LISTED ? "listed" : "marked"; |
|---|
| 2128 | |
|---|
| 2129 | { |
|---|
| 2130 | char *macro_name = GBS_global_string_copy("COLORIZE_%s_%s", what, Sel->items_name); |
|---|
| 2131 | char *window_name = GBS_global_string_copy("Colorize %s %s", what, Sel->items_name); |
|---|
| 2132 | |
|---|
| 2133 | aws->init( aw_root, macro_name, window_name); |
|---|
| 2134 | |
|---|
| 2135 | free(window_name); |
|---|
| 2136 | free(macro_name); |
|---|
| 2137 | } |
|---|
| 2138 | |
|---|
| 2139 | aws->load_xfig("colorize.fig"); |
|---|
| 2140 | |
|---|
| 2141 | aws->auto_space(10, 10); |
|---|
| 2142 | |
|---|
| 2143 | aws->at("close"); |
|---|
| 2144 | aws->callback((AW_CB0) AW_POPDOWN); |
|---|
| 2145 | aws->create_button("CLOSE","CLOSE", "C"); |
|---|
| 2146 | |
|---|
| 2147 | aws->at("help"); |
|---|
| 2148 | aws->callback(AW_POPUP_HELP,(AW_CL)(mode == AWT_COL_COLORIZE_LISTED ? "set_color_of_listed.hlp" : "colorize.hlp")); |
|---|
| 2149 | aws->create_button("HELP","HELP","H"); |
|---|
| 2150 | |
|---|
| 2151 | aws->at("colorize"); |
|---|
| 2152 | |
|---|
| 2153 | color_mark_data *cmd = new color_mark_data; // do not free! |
|---|
| 2154 | cmd->sel = (mode == AWT_COL_COLORIZE_MARKED) ? sel : cbs->selector; |
|---|
| 2155 | cmd->gb_main = gb_main; |
|---|
| 2156 | |
|---|
| 2157 | if (mode == AWT_COL_COLORIZE_LISTED) aws->callback(awt_colorize_listed, (AW_CL)cbs); |
|---|
| 2158 | else aws->callback(awt_colorize_marked, (AW_CL)cmd); |
|---|
| 2159 | |
|---|
| 2160 | aws->create_autosize_button("COLORIZE", GBS_global_string_copy("Set color of %s %s to ...", what, Sel->items_name), "S", 2); |
|---|
| 2161 | |
|---|
| 2162 | { |
|---|
| 2163 | int color_group; |
|---|
| 2164 | |
|---|
| 2165 | aws->create_option_menu(AWAR_COLORIZE); |
|---|
| 2166 | aws->insert_default_option(color_group_name(0), "none", 0); |
|---|
| 2167 | for (color_group = 1; color_group <= AW_COLOR_GROUPS; ++color_group) { |
|---|
| 2168 | aws->insert_option(color_group_name(color_group), "", color_group); |
|---|
| 2169 | } |
|---|
| 2170 | aws->update_option_menu(); |
|---|
| 2171 | } |
|---|
| 2172 | |
|---|
| 2173 | color_save_data *csd = new color_save_data; // do not free! |
|---|
| 2174 | csd->cmd = cmd; |
|---|
| 2175 | csd->items_name = Sel->items_name; |
|---|
| 2176 | csd->aww = 0; |
|---|
| 2177 | csd->sel_id = 0; |
|---|
| 2178 | |
|---|
| 2179 | aws->at("loadsave"); |
|---|
| 2180 | aws->callback(AW_POPUP, (AW_CL)awt_create_loadsave_colored_window, (AW_CL)csd); |
|---|
| 2181 | aws->create_autosize_button("LOADSAVE_COLORED", "Load/Save", "L"); |
|---|
| 2182 | |
|---|
| 2183 | if (mode == AWT_COL_COLORIZE_MARKED) { |
|---|
| 2184 | aws->at("mark"); |
|---|
| 2185 | aws->callback(awt_mark_colored, (AW_CL)cmd, (AW_CL)1); |
|---|
| 2186 | aws->create_autosize_button("MARK_COLORED", GBS_global_string_copy("Mark all %s of ...", Sel->items_name), "M", 2); |
|---|
| 2187 | |
|---|
| 2188 | aws->at("unmark"); |
|---|
| 2189 | aws->callback(awt_mark_colored, (AW_CL)cmd, (AW_CL)0); |
|---|
| 2190 | aws->create_autosize_button("UNMARK_COLORED", GBS_global_string_copy("Unmark all %s of ...", Sel->items_name), "U", 2); |
|---|
| 2191 | |
|---|
| 2192 | aws->at("invert"); |
|---|
| 2193 | aws->callback(awt_mark_colored, (AW_CL)cmd, (AW_CL)2); |
|---|
| 2194 | aws->create_autosize_button("INVERT_COLORED", GBS_global_string_copy("Invert all %s of ...", Sel->items_name), "I", 2); |
|---|
| 2195 | } |
|---|
| 2196 | |
|---|
| 2197 | aws->at_newline(); |
|---|
| 2198 | aws->window_fit(); |
|---|
| 2199 | |
|---|
| 2200 | return aws; |
|---|
| 2201 | } |
|---|
| 2202 | |
|---|
| 2203 | AW_window *create_awt_listed_items_colorizer(AW_root *aw_root, struct adaqbsstruct *cbs) { |
|---|
| 2204 | return create_awt_colorizer_window(aw_root, cbs->gb_main, cbs, 0); |
|---|
| 2205 | } |
|---|
| 2206 | |
|---|
| 2207 | AW_window *awt_create_item_colorizer(AW_root *aw_root, GBDATA *gb_main, const ad_item_selector *sel) { |
|---|
| 2208 | return create_awt_colorizer_window(aw_root, gb_main, 0, sel); |
|---|
| 2209 | } |
|---|
| 2210 | |
|---|
| 2211 | AW_window *create_awt_open_parser(AW_root *aw_root, struct adaqbsstruct *cbs) |
|---|
| 2212 | { |
|---|
| 2213 | AW_window_simple *aws = 0; |
|---|
| 2214 | aws = new AW_window_simple; |
|---|
| 2215 | |
|---|
| 2216 | { |
|---|
| 2217 | char *macro_name = GBS_global_string_copy("MODIFY_DATABASE_FIELD_%s", cbs->selector->items_name); |
|---|
| 2218 | char *window_name = GBS_global_string_copy("MODIFY DATABASE FIELD of listed %s", cbs->selector->items_name); |
|---|
| 2219 | |
|---|
| 2220 | aws->init( aw_root, macro_name, window_name); |
|---|
| 2221 | |
|---|
| 2222 | free(window_name); |
|---|
| 2223 | free(macro_name); |
|---|
| 2224 | } |
|---|
| 2225 | |
|---|
| 2226 | aws->load_xfig("awt/parser.fig"); |
|---|
| 2227 | |
|---|
| 2228 | aws->at("close"); |
|---|
| 2229 | aws->callback( (AW_CB0)AW_POPDOWN); |
|---|
| 2230 | aws->create_button("CLOSE","CLOSE","C"); |
|---|
| 2231 | |
|---|
| 2232 | aws->at("help"); |
|---|
| 2233 | aws->callback(AW_POPUP_HELP,(AW_CL)"mod_field_list.hlp"); |
|---|
| 2234 | aws->create_button("HELP","HELP","H"); |
|---|
| 2235 | |
|---|
| 2236 | aws->at("helptags"); |
|---|
| 2237 | aws->callback(AW_POPUP_HELP,(AW_CL)"tags.hlp"); |
|---|
| 2238 | aws->create_button("HELP_TAGS", "HELP TAGS","H"); |
|---|
| 2239 | |
|---|
| 2240 | aws->at("usetag"); aws->create_toggle(cbs->awar_use_tag); |
|---|
| 2241 | aws->at("deftag"); aws->create_input_field(cbs->awar_deftag); |
|---|
| 2242 | aws->at("tag"); aws->create_input_field(cbs->awar_tag); |
|---|
| 2243 | |
|---|
| 2244 | aws->at("double"); aws->create_toggle(cbs->awar_double_pars); |
|---|
| 2245 | |
|---|
| 2246 | awt_create_selection_list_on_scandb(cbs->gb_main,aws,cbs->awar_parskey,AWT_PARS_FILTER, "field",0, cbs->selector, 20, 10); |
|---|
| 2247 | |
|---|
| 2248 | aws->at("go"); |
|---|
| 2249 | aws->callback((AW_CB1)awt_do_pars_list,(AW_CL)cbs); |
|---|
| 2250 | aws->create_button("GO", "GO","G"); |
|---|
| 2251 | |
|---|
| 2252 | aws->at("parser"); |
|---|
| 2253 | aws->create_text_field(cbs->awar_parsvalue); |
|---|
| 2254 | |
|---|
| 2255 | aws->at("pre"); |
|---|
| 2256 | AW_selection_list *id = aws->create_selection_list(cbs->awar_parspredefined); |
|---|
| 2257 | |
|---|
| 2258 | char *filename = 0; |
|---|
| 2259 | switch (cbs->selector->type) { |
|---|
| 2260 | case AWT_QUERY_ITEM_SPECIES: |
|---|
| 2261 | filename = AWT_unfold_path("lib/sellists/mod_fields*.sellst","ARBHOME"); |
|---|
| 2262 | break; |
|---|
| 2263 | case AWT_QUERY_ITEM_GENES: |
|---|
| 2264 | filename = AWT_unfold_path("lib/sellists/mod_gene_fields*.sellst","ARBHOME"); |
|---|
| 2265 | break; |
|---|
| 2266 | case AWT_QUERY_ITEM_EXPERIMENTS: |
|---|
| 2267 | filename = AWT_unfold_path("lib/sellists/mod_experiment_fields*.sellst","ARBHOME"); |
|---|
| 2268 | break; |
|---|
| 2269 | default: |
|---|
| 2270 | gb_assert(0); |
|---|
| 2271 | break; |
|---|
| 2272 | } |
|---|
| 2273 | |
|---|
| 2274 | GB_ERROR error = filename ? aws->load_selection_list(id,filename) : "No default selection list for query-type"; |
|---|
| 2275 | free(filename); |
|---|
| 2276 | if (error) { |
|---|
| 2277 | aw_message(error); |
|---|
| 2278 | } |
|---|
| 2279 | else{ |
|---|
| 2280 | aws->get_root()->awar(cbs->awar_parspredefined)->add_callback((AW_RCB1)awt_predef_prg,(AW_CL)cbs); |
|---|
| 2281 | } |
|---|
| 2282 | return (AW_window *)aws; |
|---|
| 2283 | } |
|---|
| 2284 | |
|---|
| 2285 | |
|---|
| 2286 | /***************** Multi set fields *************************/ |
|---|
| 2287 | |
|---|
| 2288 | void awt_do_set_list(void *, struct adaqbsstruct *cbs, long append) { |
|---|
| 2289 | GB_ERROR error = 0; |
|---|
| 2290 | char *key = cbs->aws->get_root()->awar(cbs->awar_setkey)->read_string(); |
|---|
| 2291 | if (strcmp(key,"name") == 0) { |
|---|
| 2292 | error = "You cannot set the name field"; |
|---|
| 2293 | } |
|---|
| 2294 | |
|---|
| 2295 | char *value = cbs->aws->get_root()->awar(cbs->awar_setvalue)->read_string(); |
|---|
| 2296 | if (value[0] == 0) freeset(value, 0); |
|---|
| 2297 | |
|---|
| 2298 | GB_begin_transaction(cbs->gb_main); |
|---|
| 2299 | |
|---|
| 2300 | GBDATA *gb_key_type = 0; |
|---|
| 2301 | { |
|---|
| 2302 | GBDATA *gb_key_data = GB_search(cbs->gb_main, cbs->selector->change_key_path, GB_CREATE_CONTAINER); |
|---|
| 2303 | if (!gb_key_data) error = GB_await_error(); |
|---|
| 2304 | else { |
|---|
| 2305 | GBDATA *gb_key_name = GB_find_string(gb_key_data,CHANGEKEY_NAME,key,GB_IGNORE_CASE,down_2_level); |
|---|
| 2306 | if (!gb_key_name) { |
|---|
| 2307 | error = GBS_global_string("The destination field '%s' does not exists", key); |
|---|
| 2308 | } |
|---|
| 2309 | else { |
|---|
| 2310 | gb_key_type = GB_brother(gb_key_name,CHANGEKEY_TYPE); |
|---|
| 2311 | if (!gb_key_type) error = GB_await_error(); |
|---|
| 2312 | } |
|---|
| 2313 | } |
|---|
| 2314 | } |
|---|
| 2315 | |
|---|
| 2316 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, cbs->aws->get_root(), AWT_QUERY_ALL_SPECIES); |
|---|
| 2317 | !error && gb_item_container; |
|---|
| 2318 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, AWT_QUERY_ALL_SPECIES)) |
|---|
| 2319 | { |
|---|
| 2320 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 2321 | !error && gb_item; |
|---|
| 2322 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 2323 | { |
|---|
| 2324 | if (IS_QUERIED(gb_item,cbs)) { |
|---|
| 2325 | GBDATA *gb_new = GB_search(gb_item, key,GB_FIND); |
|---|
| 2326 | if (gb_new) { |
|---|
| 2327 | if (value){ |
|---|
| 2328 | if (append){ |
|---|
| 2329 | char *old = GB_read_as_string(gb_new); |
|---|
| 2330 | if (old) { |
|---|
| 2331 | GBS_strstruct *strstr = GBS_stropen(strlen(old)+strlen(value)+2); |
|---|
| 2332 | GBS_strcat(strstr,old); |
|---|
| 2333 | GBS_strcat(strstr,value); |
|---|
| 2334 | char *v = GBS_strclose(strstr); |
|---|
| 2335 | error = GB_write_as_string(gb_new,v); |
|---|
| 2336 | free(v); |
|---|
| 2337 | } |
|---|
| 2338 | else { |
|---|
| 2339 | char *name = GBT_read_string(gb_item,"name"); |
|---|
| 2340 | error = GB_export_errorf("Field '%s' of %s '%s' has incompatible type", key, cbs->selector->item_name, name); |
|---|
| 2341 | free(name); |
|---|
| 2342 | } |
|---|
| 2343 | } |
|---|
| 2344 | else { |
|---|
| 2345 | error = GB_write_as_string(gb_new,value); |
|---|
| 2346 | } |
|---|
| 2347 | } |
|---|
| 2348 | else { |
|---|
| 2349 | if (!append) error = GB_delete(gb_new); |
|---|
| 2350 | } |
|---|
| 2351 | } |
|---|
| 2352 | else { |
|---|
| 2353 | gb_new = GB_search(gb_item, key, GB_read_int(gb_key_type)); |
|---|
| 2354 | |
|---|
| 2355 | if (!gb_new) error = GB_await_error(); |
|---|
| 2356 | else error = GB_write_as_string(gb_new,value); |
|---|
| 2357 | } |
|---|
| 2358 | } |
|---|
| 2359 | } |
|---|
| 2360 | } |
|---|
| 2361 | |
|---|
| 2362 | GB_end_transaction_show_error(cbs->gb_main, error, aw_message); |
|---|
| 2363 | |
|---|
| 2364 | free(key); |
|---|
| 2365 | free(value); |
|---|
| 2366 | } |
|---|
| 2367 | |
|---|
| 2368 | AW_window *create_awt_do_set_list(AW_root *aw_root, struct adaqbsstruct *cbs) |
|---|
| 2369 | { |
|---|
| 2370 | AW_window_simple *aws = 0; |
|---|
| 2371 | aws = new AW_window_simple; |
|---|
| 2372 | aws->init( aw_root, "SET_DATABASE_FIELD_OF_LISTED","SET MANY FIELDS"); |
|---|
| 2373 | aws->load_xfig("ad_mset.fig"); |
|---|
| 2374 | |
|---|
| 2375 | aws->at("close"); |
|---|
| 2376 | aws->callback( (AW_CB0)AW_POPDOWN); |
|---|
| 2377 | aws->create_button("CLOSE", "CLOSE","C"); |
|---|
| 2378 | |
|---|
| 2379 | aws->at("help"); |
|---|
| 2380 | aws->callback( AW_POPUP_HELP,(AW_CL)"write_field_list.hlp"); |
|---|
| 2381 | aws->create_button("HELP", "HELP","H"); |
|---|
| 2382 | |
|---|
| 2383 | awt_create_selection_list_on_scandb(cbs->gb_main,aws,cbs->awar_setkey, AWT_NDS_FILTER, "box",0, cbs->selector, 20, 10); |
|---|
| 2384 | aws->at("create"); |
|---|
| 2385 | aws->callback((AW_CB)awt_do_set_list,(AW_CL)cbs,0); |
|---|
| 2386 | aws->create_button("SET_SINGLE_FIELD_OF_LISTED","WRITE"); |
|---|
| 2387 | aws->at("do"); |
|---|
| 2388 | aws->callback((AW_CB)awt_do_set_list,(AW_CL)cbs,1); |
|---|
| 2389 | aws->create_button("APPEND_SINGLE_FIELD_OF_LISTED","APPEND"); |
|---|
| 2390 | |
|---|
| 2391 | aws->at("val"); |
|---|
| 2392 | aws->create_text_field(cbs->awar_setvalue,2,2); |
|---|
| 2393 | return (AW_window *)aws; |
|---|
| 2394 | |
|---|
| 2395 | } |
|---|
| 2396 | |
|---|
| 2397 | /***************** Multi set fields *************************/ |
|---|
| 2398 | |
|---|
| 2399 | void awt_do_set_protection(void *, struct adaqbsstruct *cbs) { |
|---|
| 2400 | GB_ERROR error = 0; |
|---|
| 2401 | char *key = cbs->aws->get_root()->awar(cbs->awar_setkey)->read_string(); |
|---|
| 2402 | |
|---|
| 2403 | GB_begin_transaction(cbs->gb_main); |
|---|
| 2404 | GBDATA *gb_key_data = GB_search(cbs->gb_main, cbs->selector->change_key_path, GB_CREATE_CONTAINER); |
|---|
| 2405 | GBDATA *gb_key_name = GB_find_string(gb_key_data,CHANGEKEY_NAME,key,GB_IGNORE_CASE,down_2_level); |
|---|
| 2406 | if (!gb_key_name) { |
|---|
| 2407 | error = GBS_global_string("The destination field '%s' does not exists", key); |
|---|
| 2408 | } |
|---|
| 2409 | else { |
|---|
| 2410 | int level = cbs->aws->get_root()->awar(cbs->awar_setprotection)->read_int(); |
|---|
| 2411 | AW_root *aw_root = cbs->aws->get_root(); |
|---|
| 2412 | AWT_QUERY_RANGE range = (AWT_QUERY_RANGE)aw_root->awar(cbs->awar_where)->read_int(); |
|---|
| 2413 | |
|---|
| 2414 | for (GBDATA *gb_item_container = cbs->selector->get_first_item_container(cbs->gb_main, aw_root, range); |
|---|
| 2415 | !error && gb_item_container; |
|---|
| 2416 | gb_item_container = cbs->selector->get_next_item_container(gb_item_container, range)) |
|---|
| 2417 | { |
|---|
| 2418 | for (GBDATA *gb_item = cbs->selector->get_first_item(gb_item_container); |
|---|
| 2419 | !error && gb_item; |
|---|
| 2420 | gb_item = cbs->selector->get_next_item(gb_item)) |
|---|
| 2421 | { |
|---|
| 2422 | if (IS_QUERIED(gb_item,cbs)) { |
|---|
| 2423 | GBDATA *gb_new = GB_search(gb_item, key,GB_FIND); |
|---|
| 2424 | if (!gb_new) continue; |
|---|
| 2425 | error = GB_write_security_delete(gb_new,level); |
|---|
| 2426 | error = GB_write_security_write(gb_new,level); |
|---|
| 2427 | } |
|---|
| 2428 | } |
|---|
| 2429 | } |
|---|
| 2430 | } |
|---|
| 2431 | GB_end_transaction_show_error(cbs->gb_main, error, aw_message); |
|---|
| 2432 | |
|---|
| 2433 | free(key); |
|---|
| 2434 | } |
|---|
| 2435 | |
|---|
| 2436 | AW_window *create_awt_set_protection(AW_root *aw_root, struct adaqbsstruct *cbs) |
|---|
| 2437 | { |
|---|
| 2438 | AW_window_simple *aws = 0; |
|---|
| 2439 | aws = new AW_window_simple; |
|---|
| 2440 | aws->init( aw_root, "SET_PROTECTION_OF_FIELD_OF_LISTED", "SET PROTECTIONS OF FIELDS"); |
|---|
| 2441 | aws->load_xfig("awt/set_protection.fig"); |
|---|
| 2442 | |
|---|
| 2443 | aws->at("close"); |
|---|
| 2444 | aws->callback( (AW_CB0)AW_POPDOWN); |
|---|
| 2445 | aws->create_button("CLOSE","CLOSE","C"); |
|---|
| 2446 | |
|---|
| 2447 | aws->at("help"); |
|---|
| 2448 | aws->callback( AW_POPUP_HELP,(AW_CL)"set_protection.hlp"); |
|---|
| 2449 | aws->create_button("HELP", "HELP","H"); |
|---|
| 2450 | |
|---|
| 2451 | |
|---|
| 2452 | aws->at("prot"); |
|---|
| 2453 | aws->create_toggle_field(cbs->awar_setprotection,0); |
|---|
| 2454 | aws->insert_toggle("0 Temporary","0",0); |
|---|
| 2455 | aws->insert_toggle("1 Checked","1",1); |
|---|
| 2456 | aws->insert_toggle("2","2",2); |
|---|
| 2457 | aws->insert_toggle("3","3",3); |
|---|
| 2458 | aws->insert_toggle("4 normal","4",4); |
|---|
| 2459 | aws->insert_toggle("5 ","5",5); |
|---|
| 2460 | aws->insert_toggle("6 the truth","5",6); |
|---|
| 2461 | |
|---|
| 2462 | awt_create_selection_list_on_scandb(cbs->gb_main,aws,cbs->awar_setkey, AWT_NDS_FILTER, "list",0, cbs->selector, 20, 10); |
|---|
| 2463 | |
|---|
| 2464 | aws->at("go"); |
|---|
| 2465 | aws->callback((AW_CB1)awt_do_set_protection,(AW_CL)cbs); |
|---|
| 2466 | aws->create_button("SET_PROTECTION_OF_FIELD_OF_LISTED", "SET PROTECTION"); |
|---|
| 2467 | |
|---|
| 2468 | return (AW_window *)aws; |
|---|
| 2469 | } |
|---|
| 2470 | |
|---|
| 2471 | void awt_toggle_flag(AW_window *aww, struct adaqbsstruct *cbs) { |
|---|
| 2472 | GB_transaction dummy(cbs->gb_main); |
|---|
| 2473 | GBDATA *gb_item = cbs->selector->get_selected_item(cbs->gb_main, aww->get_root()); |
|---|
| 2474 | if (gb_item) { |
|---|
| 2475 | long flag = GB_read_flag(gb_item); |
|---|
| 2476 | GB_write_flag(gb_item, 1-flag); |
|---|
| 2477 | } |
|---|
| 2478 | awt_query_update_list(aww,cbs); |
|---|
| 2479 | |
|---|
| 2480 | // GB_transaction dummy(cbs->gb_main); |
|---|
| 2481 | // char *sname = aww->get_root()->awar(cbs->species_name)->read_string(); |
|---|
| 2482 | // if (sname[0]){ |
|---|
| 2483 | // GBDATA *gb_species = GBT_find_species(cbs->gb_main,sname); |
|---|
| 2484 | // if (gb_species) { |
|---|
| 2485 | // long flag = GB_read_flag(gb_species); |
|---|
| 2486 | // GB_write_flag(gb_species,1-flag); |
|---|
| 2487 | // } |
|---|
| 2488 | // } |
|---|
| 2489 | |
|---|
| 2490 | // delete sname; |
|---|
| 2491 | // awt_query_update_list(aww,cbs); |
|---|
| 2492 | } |
|---|
| 2493 | |
|---|
| 2494 | // ----------------------------------------------------- |
|---|
| 2495 | // struct ad_item_selector AWT_species_selector |
|---|
| 2496 | // ----------------------------------------------------- |
|---|
| 2497 | |
|---|
| 2498 | static GBDATA *awt_get_first_species_data(GBDATA *gb_main, AW_root *, AWT_QUERY_RANGE) { |
|---|
| 2499 | return GBT_get_species_data(gb_main); |
|---|
| 2500 | } |
|---|
| 2501 | static GBDATA *awt_get_next_species_data(GBDATA *, AWT_QUERY_RANGE) { |
|---|
| 2502 | return 0; // there is only ONE species_data |
|---|
| 2503 | } |
|---|
| 2504 | |
|---|
| 2505 | static void awt_select_species(GBDATA* , AW_root *aw_root, const char *item_name) { |
|---|
| 2506 | aw_root->awar(AWAR_SPECIES_NAME)->write_string(item_name); |
|---|
| 2507 | } |
|---|
| 2508 | |
|---|
| 2509 | static GBDATA* awt_get_selected_species(GBDATA *gb_main, AW_root *aw_root) { |
|---|
| 2510 | char *species_name = aw_root->awar(AWAR_SPECIES_NAME)->read_string(); |
|---|
| 2511 | GBDATA *gb_species = 0; |
|---|
| 2512 | if (species_name[0]) { |
|---|
| 2513 | gb_species = GBT_find_species(gb_main, species_name); |
|---|
| 2514 | } |
|---|
| 2515 | free(species_name); |
|---|
| 2516 | return gb_species; |
|---|
| 2517 | } |
|---|
| 2518 | |
|---|
| 2519 | static char* awt_get_species_id(GBDATA *, GBDATA *gb_species) { |
|---|
| 2520 | // awt_get_species_id creates the label that occurs in the search and query result list |
|---|
| 2521 | GBDATA *gb_name = GB_entry(gb_species, "name"); |
|---|
| 2522 | if (!gb_name) return 0; // species w/o name -> skip |
|---|
| 2523 | return GB_read_as_string(gb_name); |
|---|
| 2524 | } |
|---|
| 2525 | |
|---|
| 2526 | static GBDATA *awt_find_species_by_id(GBDATA *gb_main, const char *id) { |
|---|
| 2527 | return GBT_find_species(gb_main, id); // id is 'name' field |
|---|
| 2528 | } |
|---|
| 2529 | |
|---|
| 2530 | struct ad_item_selector AWT_species_selector = { |
|---|
| 2531 | AWT_QUERY_ITEM_SPECIES, |
|---|
| 2532 | awt_select_species, |
|---|
| 2533 | awt_get_species_id, |
|---|
| 2534 | awt_find_species_by_id, |
|---|
| 2535 | (AW_CB)awt_selection_list_update_cb, |
|---|
| 2536 | 12, |
|---|
| 2537 | CHANGE_KEY_PATH, |
|---|
| 2538 | "species", |
|---|
| 2539 | "species", |
|---|
| 2540 | "name", |
|---|
| 2541 | awt_get_first_species_data, |
|---|
| 2542 | awt_get_next_species_data, |
|---|
| 2543 | GBT_first_species_rel_species_data, |
|---|
| 2544 | GBT_next_species, |
|---|
| 2545 | awt_get_selected_species, |
|---|
| 2546 | 0, 0, |
|---|
| 2547 | }; |
|---|
| 2548 | |
|---|
| 2549 | struct ad_item_selector AWT_organism_selector = { |
|---|
| 2550 | AWT_QUERY_ITEM_SPECIES, |
|---|
| 2551 | awt_select_species, |
|---|
| 2552 | awt_get_species_id, |
|---|
| 2553 | awt_find_species_by_id, |
|---|
| 2554 | (AW_CB)awt_selection_list_update_cb, |
|---|
| 2555 | 12, |
|---|
| 2556 | CHANGE_KEY_PATH, |
|---|
| 2557 | "organism", |
|---|
| 2558 | "organism", |
|---|
| 2559 | "name", |
|---|
| 2560 | awt_get_first_species_data, |
|---|
| 2561 | awt_get_next_species_data, |
|---|
| 2562 | GBT_first_species_rel_species_data, |
|---|
| 2563 | GBT_next_species, |
|---|
| 2564 | awt_get_selected_species, |
|---|
| 2565 | 0, 0, |
|---|
| 2566 | }; |
|---|
| 2567 | |
|---|
| 2568 | static void awt_new_selection_made(AW_root *aw_root, AW_CL cl_awar_selection, AW_CL cl_cbs) { |
|---|
| 2569 | const char *awar_selection = (const char *)cl_awar_selection; |
|---|
| 2570 | struct adaqbsstruct *cbs = (struct adaqbsstruct *)cl_cbs; |
|---|
| 2571 | |
|---|
| 2572 | char *item_name = aw_root->awar(awar_selection)->read_as_string(); |
|---|
| 2573 | cbs->selector->update_item_awars(cbs->gb_main, aw_root, item_name); |
|---|
| 2574 | free(item_name); |
|---|
| 2575 | } |
|---|
| 2576 | |
|---|
| 2577 | static void query_box_init_config(AWT_config_definition& cdef, struct adaqbsstruct *cbs) { // this defines what is saved/restored to/from configs |
|---|
| 2578 | // don't save these |
|---|
| 2579 | // cdef.add(cbs->awar_ere, "action"); |
|---|
| 2580 | // cdef.add(cbs->awar_where, "range"); |
|---|
| 2581 | // cdef.add(cbs->awar_by, "by"); |
|---|
| 2582 | |
|---|
| 2583 | for (int key_id = 0; key_id<AWT_QUERY_SEARCHES; ++key_id) { |
|---|
| 2584 | cdef.add(cbs->awar_keys[key_id], "key", key_id); |
|---|
| 2585 | cdef.add(cbs->awar_queries[key_id], "query", key_id); |
|---|
| 2586 | cdef.add(cbs->awar_not[key_id], "not", key_id); |
|---|
| 2587 | cdef.add(cbs->awar_operator[key_id], "operator", key_id); |
|---|
| 2588 | } |
|---|
| 2589 | } |
|---|
| 2590 | static char *query_box_store_config(AW_window *aww, AW_CL cl_cbs, AW_CL) { |
|---|
| 2591 | AWT_config_definition cdef(aww->get_root()); |
|---|
| 2592 | query_box_init_config(cdef, (struct adaqbsstruct *)cl_cbs); |
|---|
| 2593 | return cdef.read(); |
|---|
| 2594 | } |
|---|
| 2595 | static void query_box_restore_config(AW_window *aww, const char *stored, AW_CL cl_cbs, AW_CL ) { |
|---|
| 2596 | AWT_config_definition cdef(aww->get_root()); |
|---|
| 2597 | query_box_init_config(cdef, (struct adaqbsstruct *)cl_cbs); |
|---|
| 2598 | cdef.write(stored); |
|---|
| 2599 | } |
|---|
| 2600 | |
|---|
| 2601 | |
|---|
| 2602 | typedef AW_window *(*window_generator)(AW_root *); |
|---|
| 2603 | |
|---|
| 2604 | static void query_box_popup_view_window(AW_window *aww, AW_CL cl_create_window, AW_CL) { |
|---|
| 2605 | window_generator create_window = (window_generator)cl_create_window; |
|---|
| 2606 | AW_window *aw_viewer = create_window(aww->get_root()); |
|---|
| 2607 | aw_viewer->show(); |
|---|
| 2608 | } |
|---|
| 2609 | |
|---|
| 2610 | /***************** Create the database query box and functions *************************/ |
|---|
| 2611 | |
|---|
| 2612 | static void query_rel_menu_entry(AW_window *aws, const char *id, const char *query_id, AW_label label, const char *mnemonic, const char *helpText, AW_active Mask, void (*f)(AW_window*,AW_CL,AW_CL), AW_CL cd1, AW_CL cd2) { |
|---|
| 2613 | char *rel_id = GBS_global_string_copy("%s_%s", query_id, id); |
|---|
| 2614 | aws->insert_menu_topic(rel_id, label, mnemonic, helpText, Mask, f, cd1, cd2); |
|---|
| 2615 | free(rel_id); |
|---|
| 2616 | } |
|---|
| 2617 | |
|---|
| 2618 | struct adaqbsstruct *awt_create_query_box(AW_window *aws, awt_query_struct *awtqs, const char *query_id) // create the query box |
|---|
| 2619 | { |
|---|
| 2620 | char buffer[256]; |
|---|
| 2621 | AW_root *aw_root = aws->get_root(); |
|---|
| 2622 | GBDATA *gb_main = awtqs->gb_main; |
|---|
| 2623 | struct adaqbsstruct *cbs = (struct adaqbsstruct *)calloc(1, sizeof(struct adaqbsstruct)); |
|---|
| 2624 | |
|---|
| 2625 | cbs->gb_main = awtqs->gb_main; |
|---|
| 2626 | cbs->aws = aws; |
|---|
| 2627 | cbs->gb_ref = awtqs->gb_ref; |
|---|
| 2628 | cbs->expect_hit_in_ref_list = awtqs->expect_hit_in_ref_list; |
|---|
| 2629 | cbs->select_bit = awtqs->select_bit; |
|---|
| 2630 | cbs->species_name = strdup(awtqs->species_name); |
|---|
| 2631 | cbs->tree_name = awtqs->tree_name ? aw_root->awar(awtqs->tree_name)->read_string() : 0; |
|---|
| 2632 | cbs->selector = awtqs->selector; |
|---|
| 2633 | cbs->hit_description = GBS_create_hash(2*awt_count_items(cbs, AWT_QUERY_ALL_SPECIES), GB_IGNORE_CASE); |
|---|
| 2634 | |
|---|
| 2635 | GB_push_transaction(gb_main); |
|---|
| 2636 | /*************** Create local AWARS *******************/ |
|---|
| 2637 | |
|---|
| 2638 | awt_query_create_global_awars(aw_root, AW_ROOT_DEFAULT); |
|---|
| 2639 | |
|---|
| 2640 | { |
|---|
| 2641 | const char *default_key[AWT_QUERY_SEARCHES+1] = { "name", "name", "name", 0}; |
|---|
| 2642 | |
|---|
| 2643 | for (int key_id = 0; key_id<AWT_QUERY_SEARCHES; ++key_id) { |
|---|
| 2644 | sprintf(buffer,"tmp/dbquery_%s/key_%i",query_id, key_id); |
|---|
| 2645 | cbs->awar_keys[key_id] = strdup(buffer); |
|---|
| 2646 | awt_assert(default_key[key_id] != 0); |
|---|
| 2647 | aw_root->awar_string( cbs->awar_keys[key_id], default_key[key_id], AW_ROOT_DEFAULT); |
|---|
| 2648 | |
|---|
| 2649 | sprintf(buffer,"tmp/dbquery_%s/query_%i",query_id, key_id); |
|---|
| 2650 | cbs->awar_queries[key_id] = strdup(buffer); |
|---|
| 2651 | aw_root->awar_string( cbs->awar_queries[key_id], "*", AW_ROOT_DEFAULT); |
|---|
| 2652 | |
|---|
| 2653 | sprintf(buffer,"tmp/dbquery_%s/not_%i",query_id, key_id); |
|---|
| 2654 | cbs->awar_not[key_id] = strdup(buffer); |
|---|
| 2655 | aw_root->awar_int( cbs->awar_not[key_id], 0, AW_ROOT_DEFAULT); |
|---|
| 2656 | |
|---|
| 2657 | sprintf(buffer,"tmp/dbquery_%s/operator_%i",query_id, key_id); |
|---|
| 2658 | cbs->awar_operator[key_id] = strdup(buffer); |
|---|
| 2659 | aw_root->awar_string( cbs->awar_operator[key_id], "ign", AW_ROOT_DEFAULT); |
|---|
| 2660 | } |
|---|
| 2661 | aw_root->awar(cbs->awar_keys[0])->add_callback(awt_first_searchkey_changed_cb, (AW_CL)cbs); |
|---|
| 2662 | } |
|---|
| 2663 | |
|---|
| 2664 | sprintf(buffer,"tmp/dbquery_%s/ere",query_id); |
|---|
| 2665 | cbs->awar_ere = strdup(buffer); |
|---|
| 2666 | aw_root->awar_int( cbs->awar_ere, AWT_QUERY_GENERATE); |
|---|
| 2667 | |
|---|
| 2668 | sprintf(buffer,"tmp/dbquery_%s/where",query_id); |
|---|
| 2669 | cbs->awar_where = strdup(buffer); |
|---|
| 2670 | aw_root->awar_int( cbs->awar_where, AWT_QUERY_ALL_SPECIES); |
|---|
| 2671 | |
|---|
| 2672 | sprintf(buffer,"tmp/dbquery_%s/count",query_id); |
|---|
| 2673 | cbs->awar_count = strdup(buffer); |
|---|
| 2674 | aw_root->awar_int( cbs->awar_count, 0); |
|---|
| 2675 | |
|---|
| 2676 | sprintf(buffer,"tmp/dbquery_%s/sort",query_id); |
|---|
| 2677 | cbs->awar_sort = strdup(buffer); |
|---|
| 2678 | aw_root->awar_int( cbs->awar_sort, AWT_QUERY_SORT_NONE)->add_callback(awt_sort_order_changed_cb, (AW_CL)cbs); |
|---|
| 2679 | cbs->sort_mask = AWT_QUERY_SORT_NONE; // default to unsorted |
|---|
| 2680 | |
|---|
| 2681 | sprintf(buffer,"tmp/dbquery_%s/by",query_id); |
|---|
| 2682 | cbs->awar_by = strdup(buffer); |
|---|
| 2683 | aw_root->awar_int( cbs->awar_by, AWT_QUERY_MATCH); |
|---|
| 2684 | |
|---|
| 2685 | if (awtqs->ere_pos_fig){ |
|---|
| 2686 | aws->at(awtqs->ere_pos_fig); |
|---|
| 2687 | aws->create_toggle_field(cbs->awar_ere,"",""); |
|---|
| 2688 | |
|---|
| 2689 | aws->insert_toggle(GBS_global_string("Search %s", cbs->selector->items_name),"G",(int)AWT_QUERY_GENERATE); |
|---|
| 2690 | aws->insert_toggle(GBS_global_string("Add %s", cbs->selector->items_name),"E",(int)AWT_QUERY_ENLARGE); |
|---|
| 2691 | aws->insert_toggle(GBS_global_string("Keep %s", cbs->selector->items_name),"R",(int)AWT_QUERY_REDUCE); |
|---|
| 2692 | |
|---|
| 2693 | aws->update_toggle_field(); |
|---|
| 2694 | } |
|---|
| 2695 | if (awtqs->where_pos_fig) { |
|---|
| 2696 | aws->at(awtqs->where_pos_fig); |
|---|
| 2697 | aws->create_toggle_field(cbs->awar_where,"",""); |
|---|
| 2698 | aws->insert_toggle("of current organism","C",(int)AWT_QUERY_CURRENT_SPECIES); |
|---|
| 2699 | aws->insert_toggle("of marked organisms","M",(int)AWT_QUERY_MARKED_SPECIES); |
|---|
| 2700 | aws->insert_toggle("of all organisms","A",(int)AWT_QUERY_ALL_SPECIES); |
|---|
| 2701 | aws->update_toggle_field(); |
|---|
| 2702 | |
|---|
| 2703 | } |
|---|
| 2704 | if (awtqs->by_pos_fig){ |
|---|
| 2705 | aws->at(awtqs->by_pos_fig); |
|---|
| 2706 | aws->create_toggle_field(cbs->awar_by,"",""); |
|---|
| 2707 | aws->insert_toggle("that match the query","M",(int)AWT_QUERY_MATCH); |
|---|
| 2708 | aws->insert_toggle("that don't match the q.","D",(int)AWT_QUERY_DONT_MATCH); |
|---|
| 2709 | aws->insert_toggle("that are marked","A",(int)AWT_QUERY_MARKED); |
|---|
| 2710 | aws->update_toggle_field(); |
|---|
| 2711 | } |
|---|
| 2712 | |
|---|
| 2713 | // distances for multiple queries : |
|---|
| 2714 | |
|---|
| 2715 | #define KEY_Y_OFFSET 32 |
|---|
| 2716 | |
|---|
| 2717 | int xpos_calc[3] = { -1, -1, -1 }; // X-positions for elements in search expressions |
|---|
| 2718 | |
|---|
| 2719 | if (awtqs->qbox_pos_fig){ |
|---|
| 2720 | AW_at_size at_size; |
|---|
| 2721 | int xpos, ypos; |
|---|
| 2722 | |
|---|
| 2723 | aws->auto_space(1, 1); |
|---|
| 2724 | |
|---|
| 2725 | aws->at(awtqs->qbox_pos_fig); |
|---|
| 2726 | aws->store_at_size_and_attach(&at_size); |
|---|
| 2727 | aws->get_at_position(&xpos, &ypos); |
|---|
| 2728 | |
|---|
| 2729 | int ypos_dummy; |
|---|
| 2730 | |
|---|
| 2731 | for (int key = AWT_QUERY_SEARCHES-1; key >= 0; --key) { |
|---|
| 2732 | if (key) { |
|---|
| 2733 | aws->at(xpos, ypos+key*KEY_Y_OFFSET); |
|---|
| 2734 | aws->create_option_menu(cbs->awar_operator[key], 0, ""); |
|---|
| 2735 | aws->insert_option("and", "", "and"); |
|---|
| 2736 | aws->insert_option("or", "", "or"); |
|---|
| 2737 | aws->insert_option("ign", "", "ign"); |
|---|
| 2738 | aws->update_option_menu(); |
|---|
| 2739 | |
|---|
| 2740 | if (xpos_calc[0] == -1) aws->get_at_position(&xpos_calc[0], &ypos_dummy); |
|---|
| 2741 | } |
|---|
| 2742 | |
|---|
| 2743 | aws->at(xpos_calc[0], ypos+key*KEY_Y_OFFSET); |
|---|
| 2744 | aws->restore_at_size_and_attach(&at_size); |
|---|
| 2745 | |
|---|
| 2746 | { |
|---|
| 2747 | char *button_id = GBS_global_string_copy("field_sel_%s_%i", query_id, key); |
|---|
| 2748 | awt_create_selection_list_on_scandb(gb_main,aws,cbs->awar_keys[key], AWT_NDS_FILTER, |
|---|
| 2749 | 0, awtqs->rescan_pos_fig, |
|---|
| 2750 | awtqs->selector, 22, 20, AWT_SF_PSEUDO, button_id); |
|---|
| 2751 | free(button_id); |
|---|
| 2752 | } |
|---|
| 2753 | |
|---|
| 2754 | if (xpos_calc[1] == -1) aws->get_at_position(&xpos_calc[1], &ypos_dummy); |
|---|
| 2755 | |
|---|
| 2756 | aws->at(xpos_calc[1], ypos+key*KEY_Y_OFFSET); |
|---|
| 2757 | aws->create_toggle(cbs->awar_not[key], "#equal.xpm", "#notEqual.xpm"); |
|---|
| 2758 | |
|---|
| 2759 | if (xpos_calc[2] == -1) aws->get_at_position(&xpos_calc[2], &ypos_dummy); |
|---|
| 2760 | } |
|---|
| 2761 | } |
|---|
| 2762 | if (awtqs->key_pos_fig){ |
|---|
| 2763 | aws->at(awtqs->key_pos_fig); |
|---|
| 2764 | aws->create_input_field(cbs->awar_keys[0],12); |
|---|
| 2765 | } |
|---|
| 2766 | |
|---|
| 2767 | if (awtqs->query_pos_fig){ |
|---|
| 2768 | aws->at(awtqs->query_pos_fig); |
|---|
| 2769 | |
|---|
| 2770 | AW_at_size at_size; |
|---|
| 2771 | int xpos, ypos; |
|---|
| 2772 | aws->store_at_size_and_attach(&at_size); |
|---|
| 2773 | aws->get_at_position(&xpos, &ypos); |
|---|
| 2774 | |
|---|
| 2775 | for (int key = 0; key<AWT_QUERY_SEARCHES; ++key) { |
|---|
| 2776 | aws->at(xpos_calc[2], ypos+key*KEY_Y_OFFSET); |
|---|
| 2777 | aws->restore_at_size_and_attach(&at_size); |
|---|
| 2778 | aws->d_callback((AW_CB)awt_do_query,(AW_CL)cbs,AWT_EXT_QUERY_NONE); // enable ENTER in searchfield to start search |
|---|
| 2779 | aws->create_input_field(cbs->awar_queries[key],12); |
|---|
| 2780 | } |
|---|
| 2781 | } |
|---|
| 2782 | |
|---|
| 2783 | if (awtqs->result_pos_fig){ |
|---|
| 2784 | aws->at(awtqs->result_pos_fig); |
|---|
| 2785 | if(awtqs->create_view_window) { |
|---|
| 2786 | aws->callback(query_box_popup_view_window,(AW_CL)awtqs->create_view_window, 0); |
|---|
| 2787 | } |
|---|
| 2788 | aws->d_callback((AW_CB1)awt_toggle_flag,(AW_CL)cbs); |
|---|
| 2789 | |
|---|
| 2790 | { |
|---|
| 2791 | char *this_awar_name = GBS_global_string_copy("tmp/dbquery_%s/select", query_id); |
|---|
| 2792 | AW_awar *awar = aw_root->awar_string( this_awar_name, "", AW_ROOT_DEFAULT); |
|---|
| 2793 | |
|---|
| 2794 | cbs->result_id = aws->create_selection_list(this_awar_name,"","",5,5); |
|---|
| 2795 | awar->add_callback(awt_new_selection_made, (AW_CL)this_awar_name, (AW_CL)cbs); |
|---|
| 2796 | |
|---|
| 2797 | //free(this_awar_name); do not free this, cause it's passed to awt_new_selection_made |
|---|
| 2798 | } |
|---|
| 2799 | aws->insert_default_selection( cbs->result_id, "end of list", "" ); |
|---|
| 2800 | aws->update_selection_list( cbs->result_id ); |
|---|
| 2801 | } |
|---|
| 2802 | if (awtqs->count_pos_fig){ |
|---|
| 2803 | aws->at(awtqs->count_pos_fig); |
|---|
| 2804 | aws->label("Hits:"); |
|---|
| 2805 | aws->create_button(0,cbs->awar_count,0,"+"); |
|---|
| 2806 | } |
|---|
| 2807 | |
|---|
| 2808 | if (awtqs->config_pos_fig){ |
|---|
| 2809 | aws->button_length(0); |
|---|
| 2810 | aws->at(awtqs->config_pos_fig); |
|---|
| 2811 | char *macro_id = GBS_global_string_copy("SAVELOAD_CONFIG_%s", query_id); |
|---|
| 2812 | AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "query_box", |
|---|
| 2813 | query_box_store_config, query_box_restore_config, (AW_CL)cbs, 0, |
|---|
| 2814 | macro_id); |
|---|
| 2815 | free(macro_id); |
|---|
| 2816 | } |
|---|
| 2817 | |
|---|
| 2818 | aws->button_length(18); |
|---|
| 2819 | if (awtqs->do_query_pos_fig){ |
|---|
| 2820 | aws->at(awtqs->do_query_pos_fig); |
|---|
| 2821 | aws->callback((AW_CB)awt_do_query,(AW_CL)cbs,AWT_EXT_QUERY_NONE); |
|---|
| 2822 | char *macro_id = GBS_global_string_copy("SEARCH_%s", query_id); |
|---|
| 2823 | aws->create_button(macro_id, "Search"); |
|---|
| 2824 | free(macro_id); |
|---|
| 2825 | } |
|---|
| 2826 | if (awtqs->do_refresh_pos_fig){ |
|---|
| 2827 | aws->at(awtqs->do_refresh_pos_fig); |
|---|
| 2828 | aws->create_option_menu(cbs->awar_sort); |
|---|
| 2829 | aws->insert_default_option("unsorted", "u", AWT_QUERY_SORT_NONE); |
|---|
| 2830 | aws->insert_option ("by value", "v", AWT_QUERY_SORT_BY_1STFIELD_CONTENT); |
|---|
| 2831 | aws->insert_option ("by id", "n", AWT_QUERY_SORT_BY_ID); |
|---|
| 2832 | if (cbs->selector->parent_selector) { |
|---|
| 2833 | aws->insert_option ("by parent", "p", AWT_QUERY_SORT_BY_NESTED_PID); |
|---|
| 2834 | } |
|---|
| 2835 | aws->insert_option ("by marked", "m", AWT_QUERY_SORT_BY_MARKED); |
|---|
| 2836 | aws->insert_option ("by hit", "h", AWT_QUERY_SORT_BY_HIT_DESCRIPTION); |
|---|
| 2837 | aws->insert_option ("reverse", "r", AWT_QUERY_SORT_REVERSE); |
|---|
| 2838 | aws->update_option_menu(); |
|---|
| 2839 | } |
|---|
| 2840 | else { |
|---|
| 2841 | awt_assert(0); // hmm - no sort button here. -> tell ralf where this happens |
|---|
| 2842 | } |
|---|
| 2843 | |
|---|
| 2844 | if (awtqs->do_mark_pos_fig){ |
|---|
| 2845 | aws->at(awtqs->do_mark_pos_fig); |
|---|
| 2846 | aws->help_text("mark_list.hlp"); |
|---|
| 2847 | aws->callback((AW_CB)awt_do_mark_list,(AW_CL)cbs,1); |
|---|
| 2848 | aws->create_button("MARK_LISTED_UNMARK_REST", "Mark Listed\nUnmark Rest","M"); |
|---|
| 2849 | } |
|---|
| 2850 | if (awtqs->do_unmark_pos_fig){ |
|---|
| 2851 | aws->at(awtqs->do_unmark_pos_fig); |
|---|
| 2852 | aws->help_text("unmark_list.hlp"); |
|---|
| 2853 | aws->callback((AW_CB)awt_do_mark_list,(AW_CL)cbs,0); |
|---|
| 2854 | aws->create_button("UNMARK_LISTED_MARK_REST","Unmark Listed\nMark Rest","U"); |
|---|
| 2855 | } |
|---|
| 2856 | if (awtqs->do_delete_pos_fig){ |
|---|
| 2857 | aws->at(awtqs->do_delete_pos_fig); |
|---|
| 2858 | aws->help_text("del_list.hlp"); |
|---|
| 2859 | aws->callback((AW_CB)awt_delete_species_in_list,(AW_CL)cbs,0); |
|---|
| 2860 | char *macro_id = GBS_global_string_copy("DELETE_LISTED_%s", query_id); |
|---|
| 2861 | aws->create_button(macro_id, "Delete Listed", "D"); |
|---|
| 2862 | free(macro_id); |
|---|
| 2863 | } |
|---|
| 2864 | if (awtqs->do_set_pos_fig){ |
|---|
| 2865 | sprintf(buffer,"tmp/dbquery_%s/set_key",query_id); |
|---|
| 2866 | cbs->awar_setkey = strdup(buffer); |
|---|
| 2867 | aw_root->awar_string( cbs->awar_setkey); |
|---|
| 2868 | |
|---|
| 2869 | sprintf(buffer,"tmp/dbquery_%s/set_protection",query_id); |
|---|
| 2870 | cbs->awar_setprotection = strdup(buffer); |
|---|
| 2871 | aw_root->awar_int( cbs->awar_setprotection, 4); |
|---|
| 2872 | |
|---|
| 2873 | sprintf(buffer,"tmp/dbquery_%s/set_value",query_id); |
|---|
| 2874 | cbs->awar_setvalue = strdup(buffer); |
|---|
| 2875 | aw_root->awar_string( cbs->awar_setvalue); |
|---|
| 2876 | |
|---|
| 2877 | aws->at(awtqs->do_set_pos_fig); |
|---|
| 2878 | aws->help_text("mod_field_list.hlp"); |
|---|
| 2879 | aws->callback(AW_POPUP,(AW_CL)create_awt_do_set_list,(AW_CL)cbs); |
|---|
| 2880 | char *macro_id = GBS_global_string_copy("WRITE_TO_FIELDS_OF_LISTED_%s", query_id); |
|---|
| 2881 | aws->create_button(macro_id, "Write to Fields\nof Listed","S"); |
|---|
| 2882 | free(macro_id); |
|---|
| 2883 | } |
|---|
| 2884 | |
|---|
| 2885 | char *Items = strdup(cbs->selector->items_name); |
|---|
| 2886 | Items[0] = toupper(Items[0]); |
|---|
| 2887 | |
|---|
| 2888 | if ( ( awtqs->use_menu || awtqs->open_parser_pos_fig)){ |
|---|
| 2889 | sprintf(buffer, "tmp/dbquery_%s/tag", query_id); cbs->awar_tag = strdup(buffer); aw_root->awar_string(cbs->awar_tag); |
|---|
| 2890 | sprintf(buffer, "tmp/dbquery_%s/use_tag", query_id); cbs->awar_use_tag = strdup(buffer); aw_root->awar_int (cbs->awar_use_tag); |
|---|
| 2891 | sprintf(buffer, "tmp/dbquery_%s/deftag", query_id); cbs->awar_deftag = strdup(buffer); aw_root->awar_string(cbs->awar_deftag); |
|---|
| 2892 | sprintf(buffer, "tmp/dbquery_%s/double_pars", query_id); cbs->awar_double_pars = strdup(buffer); aw_root->awar_int (cbs->awar_double_pars); |
|---|
| 2893 | sprintf(buffer, "tmp/dbquery_%s/parskey", query_id); cbs->awar_parskey = strdup(buffer); aw_root->awar_string(cbs->awar_parskey); |
|---|
| 2894 | sprintf(buffer, "tmp/dbquery_%s/parsvalue", query_id); cbs->awar_parsvalue = strdup(buffer); aw_root->awar_string(cbs->awar_parsvalue); |
|---|
| 2895 | sprintf(buffer, "tmp/dbquery_%s/awar_parspredefined", query_id); cbs->awar_parspredefined = strdup(buffer); aw_root->awar_string(cbs->awar_parspredefined); |
|---|
| 2896 | |
|---|
| 2897 | if (awtqs->use_menu){ |
|---|
| 2898 | 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, AW_POPUP,(AW_CL)create_awt_open_parser,(AW_CL)cbs); |
|---|
| 2899 | }else{ |
|---|
| 2900 | aws->at(awtqs->open_parser_pos_fig); |
|---|
| 2901 | aws->callback(AW_POPUP,(AW_CL)create_awt_open_parser,(AW_CL)cbs); |
|---|
| 2902 | aws->create_button("MODIFY_FIELDS_OF_LISTED", "MODIFY FIELDS\nOF LISTED","F"); |
|---|
| 2903 | } |
|---|
| 2904 | } |
|---|
| 2905 | if (awtqs->use_menu) { |
|---|
| 2906 | 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, AW_POPUP, (AW_CL)create_awt_set_protection, (AW_CL)cbs); |
|---|
| 2907 | aws->insert_separator(); |
|---|
| 2908 | 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, (AW_CB)awt_do_mark_list, (AW_CL)cbs, (AW_CL)1 | 8); |
|---|
| 2909 | 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, (AW_CB)awt_do_mark_list, (AW_CL)cbs, (AW_CL)1); |
|---|
| 2910 | 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, (AW_CB)awt_do_mark_list, (AW_CL)cbs, (AW_CL)0 | 8); |
|---|
| 2911 | 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, (AW_CB)awt_do_mark_list, (AW_CL)cbs, (AW_CL)0); |
|---|
| 2912 | aws->insert_separator(); |
|---|
| 2913 | |
|---|
| 2914 | |
|---|
| 2915 | 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, AW_POPUP, (AW_CL)create_awt_listed_items_colorizer, (AW_CL)cbs); |
|---|
| 2916 | |
|---|
| 2917 | if (cbs->gb_ref){ |
|---|
| 2918 | awt_assert(cbs->selector->type == AWT_QUERY_ITEM_SPECIES); // stuff below works only for species |
|---|
| 2919 | aws->insert_separator(); |
|---|
| 2920 | if (cbs->expect_hit_in_ref_list) { |
|---|
| 2921 | aws->insert_menu_topic("search_equal_fields_and_listed_in_I", "Search entries existing in both DBs and listed in the DB I hitlist","S", |
|---|
| 2922 | "search_equal_fields.hlp", AWM_ALL, (AW_CB)awt_do_query,(AW_CL)cbs,AWT_EXT_QUERY_COMPARE_LINES); |
|---|
| 2923 | aws->insert_menu_topic("search_equal_words_and_listed_in_I", "Search words existing in entries of both DBs and listed in the DB I hitlist","W", |
|---|
| 2924 | "search_equal_fields.hlp", AWM_ALL, (AW_CB)awt_do_query,(AW_CL)cbs,AWT_EXT_QUERY_COMPARE_WORDS); |
|---|
| 2925 | }else{ |
|---|
| 2926 | aws->insert_menu_topic("search_equal_field_in_both_db", "Search entries existing in both DBs","S", |
|---|
| 2927 | "search_equal_fields.hlp", AWM_ALL, (AW_CB)awt_do_query,(AW_CL)cbs,AWT_EXT_QUERY_COMPARE_LINES); |
|---|
| 2928 | aws->insert_menu_topic("search_equal_word_in_both_db","Search words existing in entries of both DBs","W", |
|---|
| 2929 | "search_equal_fields.hlp", AWM_ALL, (AW_CB)awt_do_query,(AW_CL)cbs,AWT_EXT_QUERY_COMPARE_WORDS); |
|---|
| 2930 | } |
|---|
| 2931 | } |
|---|
| 2932 | } |
|---|
| 2933 | |
|---|
| 2934 | free(Items); |
|---|
| 2935 | |
|---|
| 2936 | GB_pop_transaction(gb_main); |
|---|
| 2937 | return cbs; |
|---|
| 2938 | } |
|---|