source: tags/arb-7.0/NTREE/NT_extern.cxx

Last change on this file was 18665, checked in by westram, 3 years ago
  • change many WARN_TODO triggered warnings into todo markers.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 78.1 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : NT_extern.cxx                                     //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "map_viewer.h"
12#include "NT_local.h"
13#include "ad_trees.h"
14#include "NT_group_search.h"
15
16#include <seq_quality.h>
17#include <multi_probe.hxx>
18#include <st_window.hxx>
19#include <GEN.hxx>
20#include <EXP.hxx>
21
22#include <TreeCallbacks.hxx>
23#include <AW_rename.hxx>
24#include <probe_gui.hxx>
25#include <primer_design.hxx>
26#include <gde.hxx>
27#include <awtc_submission.hxx>
28
29#include <macros.hxx>
30#include <nds.h>
31#include <db_query.h>
32#include <dbui.h>
33#include <refentries.h>
34#include <insdel.h>
35
36#include <awti_export.hxx>
37#include <awti_import.hxx>
38
39#include <awt.hxx>
40#include <awt_input_mask.hxx>
41#include <awt_sel_boxes.hxx>
42#include <awt_www.hxx>
43#include <awt_TreeAwars.hxx>
44#include <awt_misc.hxx>
45
46#include <aw_color_groups.hxx>
47#include <aw_advice.hxx>
48#include <aw_preset.hxx>
49#include <aw_awars.hxx>
50#include <aw_global_awars.hxx>
51#include <aw_file.hxx>
52#include <aw_msg.hxx>
53#include <arb_progress.h>
54#include <aw_root.hxx>
55#include <aw_question.hxx>
56#include <aw_select.hxx>
57#include <rootAsWin.h>
58
59#include <ad_cb.h>
60
61#include <arb_strbuf.h>
62#include <arb_file.h>
63#include <arb_version.h>
64
65#include <saicalc.h>
66#if defined(DEVEL_RALF)
67# define TRACE_GROUP_SELECTION
68#endif
69
70#define AWAR_EXPORT_NDS              "tmp/export_nds"
71#define AWAR_EXPORT_NDS_SEPARATOR    AWAR_EXPORT_NDS "/delimiter"
72#define AWAR_MARKED_SPECIES_COUNTER  "tmp/disp_marked_species"
73#define AWAR_NTREE_TITLE_MODE        "tmp/title_mode"
74
75void create_probe_design_variables(AW_root *aw_root, AW_default def, AW_default global);
76
77void       create_insertDeleteColumn_variables(AW_root *root, AW_default db1);
78AW_window *create_insertDeleteColumn_window(AW_root *root);
79AW_window *create_insertDeleteBySAI_window(AW_root *root, GBDATA *gb_main);
80
81AW_window *create_tree_window(AW_root *aw_root, AWT_graphic *awd);
82
83static void nt_changesecurity(AW_root *aw_root) {
84    int level = aw_root->awar(AWAR_SECURITY_LEVEL)->read_int();
85    GB_push_transaction(GLOBAL.gb_main);
86    GB_change_my_security(GLOBAL.gb_main, level); // changes user security
87    GB_pop_transaction(GLOBAL.gb_main);
88}
89
90static void export_nds_cb(AW_window *aww, bool do_print) {
91    AW_root *aw_root = aww->get_root();
92    char    *name    = aw_root->awar(AWAR_EXPORT_NDS"/file_name")->read_string();
93    FILE    *out     = fopen(name, "w");
94
95    if (!out) {
96        aw_message("Error: Cannot open and write to file");
97    }
98    else {
99        GB_transaction ta(GLOBAL.gb_main);
100
101        make_node_text_init(GLOBAL.gb_main);
102        NDS_Type  nds_type  = (NDS_Type)aw_root->awar(AWAR_EXPORT_NDS_SEPARATOR)->read_int();
103        char     *tree_name = aw_root->awar(AWAR_TREE)->read_string();
104
105        for (GBDATA *gb_species = GBT_first_marked_species(GLOBAL.gb_main);
106             gb_species;
107             gb_species = GBT_next_marked_species(gb_species))
108        {
109            const char *buf = make_node_text_nds(GLOBAL.gb_main, gb_species, nds_type, NULp, tree_name);
110            fprintf(out, "%s\n", buf);
111        }
112        AW_refresh_fileselection(aw_root, AWAR_EXPORT_NDS);
113        fclose(out);
114        if (do_print) {
115            GB_ERROR error = GB_textprint(name);
116            if (error) aw_message(error);
117        }
118        free(tree_name);
119    }
120    free(name);
121}
122
123static AW_window *create_nds_export_window(AW_root *root) {
124    AW_window_simple *aws = new AW_window_simple;
125    aws->init(root, "EXPORT_NDS_OF_MARKED", "EXPORT NDS OF MARKED SPECIES");
126    aws->load_xfig("sel_box_nds.fig");
127
128    aws->callback(AW_POPDOWN);
129    aws->at("close");
130    aws->create_button("CLOSE", "CLOSE", "C");
131
132    aws->callback(makeHelpCallback("arb_export_nds.hlp"));
133    aws->at("help");
134    aws->create_button("HELP", "HELP", "H");
135
136    aws->at("save");
137    aws->callback(makeWindowCallback(export_nds_cb, false));
138    aws->create_button("SAVE", "SAVE", "S");
139
140    aws->at("print");
141    aws->callback(makeWindowCallback(export_nds_cb, true));
142    aws->create_button("PRINT", "PRINT", "P");
143
144    aws->at("toggle1");
145    aws->label("Column output");
146    aws->create_option_menu(AWAR_EXPORT_NDS_SEPARATOR, true);
147    aws->insert_option        ("Space padded",    "S", NDS_OUTPUT_SPACE_PADDED);
148    aws->insert_default_option("TAB separated",   "T", NDS_OUTPUT_TAB_SEPARATED);
149    aws->insert_option        ("Comma separated", "C", NDS_OUTPUT_COMMA_SEPARATED);
150    aws->update_option_menu();
151
152    AW_create_standard_fileselection(aws, AWAR_EXPORT_NDS);
153
154    return aws;
155}
156
157static void create_export_nds_awars(AW_root *awr, AW_default def) {
158    AW_create_fileselection_awars(awr, AWAR_EXPORT_NDS, "", ".nds", "export.nds");
159    awr->awar_int(AWAR_EXPORT_NDS_SEPARATOR, NDS_OUTPUT_TAB_SEPARATED, def);
160}
161
162static void selectedSpeciesChanged_cb(AW_root *awr) {
163    const char *value = awr->awar(AWAR_SPECIES_NAME)->read_char_pntr();
164    awr->awar(AWAR_INFO_BUTTON_TEXT)->write_string(value[0] ? value : "Species Info");
165    if (value[0]) {
166        awr->awar(AWAR_GROUP)->write_pointer(NULp); // deselect group when species gets selected
167#if defined(TRACE_GROUP_SELECTION)
168        fputs("clear AWAR_GROUP (because species selected)\n", stderr);
169#endif
170    }
171}
172
173static void expert_mode_changed_cb(AW_root *aw_root) {
174    aw_root->awar(AWAR_AWM_MASK)->write_int(aw_root->awar(AWAR_EXPERT)->read_int() ? AWM_ALL : AWM_BASIC); // publish expert-mode globally
175}
176
177static void NT_toggle_expert_mode(AW_window *aww) { aww->get_root()->awar(AWAR_EXPERT)->toggle_toggle(); }
178static void NT_toggle_focus_policy(AW_window *aww) { aww->get_root()->awar(AWAR_AW_FOCUS_FOLLOWS_MOUSE)->toggle_toggle(); }
179
180static void nt_create_all_awars(AW_root *awr) {
181    // creates awars for all modules reachable from ARB_NT main window
182
183    awr->awar_string(AWAR_FOOTER, "", AW_ROOT_DEFAULT);
184    if (GB_read_clients(GLOBAL.gb_main)>=0) {
185        awr->awar_string(AWAR_TREE, "", GLOBAL.gb_main);
186    }
187    else {
188        awr->awar_string(AWAR_TREE, "", AW_ROOT_DEFAULT);
189    }
190
191    awr->awar_string(AWAR_TOPAREA_SAIS, "ECOLI;HELIX;HELIX_NR", AW_ROOT_DEFAULT);
192
193    awr->awar_string(AWAR_SPECIES_NAME, "",     GLOBAL.gb_main);
194    awr->awar_string(AWAR_SAI_NAME, "",     GLOBAL.gb_main);
195    awr->awar_string(AWAR_SAI_GLOBAL, "",     GLOBAL.gb_main);
196    awr->awar_string(AWAR_MARKED_SPECIES_COUNTER, "unknown",    GLOBAL.gb_main);
197    awr->awar_string(AWAR_INFO_BUTTON_TEXT, "Species Info",    GLOBAL.gb_main);
198    awr->awar(AWAR_SPECIES_NAME)->add_callback(selectedSpeciesChanged_cb);
199    awr->awar_int(AWAR_NTREE_TITLE_MODE, 1);
200
201    awr->awar_string(AWAR_SAI_COLOR_STR, "", GLOBAL.gb_main); // sai visualization in probe match
202
203    GEN_create_awars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
204    EXP_create_awars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
205#if defined(DEBUG)
206    AWT_create_db_browser_awars(awr, AW_ROOT_DEFAULT);
207#endif // DEBUG
208
209    AW_create_namesadmin_awars(awr, GLOBAL.gb_main);
210
211    awr->awar_int(AWAR_SECURITY_LEVEL, 0, AW_ROOT_DEFAULT);
212    awr->awar(AWAR_SECURITY_LEVEL)->add_callback(nt_changesecurity);
213#if defined(DEBUG) && 0
214    awr->awar(AWAR_SECURITY_LEVEL)->write_int(6); // no security for debugging..
215#endif // DEBUG
216
217    create_insertDeleteColumn_variables(awr, AW_ROOT_DEFAULT);
218    create_probe_design_variables(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
219    create_primer_design_variables(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
220    create_trees_var(awr, AW_ROOT_DEFAULT);
221    DBUI::create_dbui_awars(awr);
222    AP_create_consensus_var(awr, AW_ROOT_DEFAULT);
223    {
224        GB_ERROR gde_err = GDE_init(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main, NULp, ARB_format_alignment, GDE_WINDOWTYPE_DEFAULT);
225        if (gde_err) GBK_terminatef("Fatal: %s", gde_err);
226    }
227    NT_create_transpro_variables(awr, AW_ROOT_DEFAULT);
228    NT_create_resort_awars(awr, AW_ROOT_DEFAULT);
229    NT_create_compare_taxonomy_awars(awr, AW_ROOT_DEFAULT);
230    NT_create_trackAliChanges_Awars(awr, GLOBAL.gb_main);
231
232    NT_create_alignment_vars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
233    NT_create_extendeds_vars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
234    create_nds_vars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main, false);
235    create_export_nds_awars(awr, AW_ROOT_DEFAULT);
236    create_group_search_awars(awr, AW_ROOT_DEFAULT);
237    TREE_create_awars(awr, GLOBAL.gb_main);
238
239    awr->awar_string(AWAR_ERROR_MESSAGES, "", GLOBAL.gb_main);
240    awr->awar_string(AWAR_DB_COMMENT, "<no description>", GLOBAL.gb_main);
241
242    AWTC_create_submission_variables(awr, GLOBAL.gb_main);
243    NT_createConcatenationAwars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
244    NT_createValidNamesAwars(awr, AW_ROOT_DEFAULT); // lothar
245    SQ_create_awars(awr, AW_ROOT_DEFAULT);
246    RefEntries::create_refentries_awars(awr, AW_ROOT_DEFAULT);
247
248    NT_create_multifurcate_tree_awars(awr, AW_ROOT_DEFAULT);
249
250    GB_ERROR error = ARB_bind_global_awars(GLOBAL.gb_main);
251    if (!error) {
252        AW_awar *awar_expert = awr->awar(AWAR_EXPERT);
253        awar_expert->add_callback(expert_mode_changed_cb);
254        awar_expert->touch();
255
256        awt_create_aww_vars(awr, AW_ROOT_DEFAULT);
257    }
258
259    if (error) aw_message(error);
260}
261
262// --------------------------------------------------------------------------------
263
264static bool nt_disconnect_from_db(AW_root *aw_root, GBDATA*& gb_main_ref) {
265    // ask user if DB was not saved
266    // returns true if user allows to quit
267
268    // @@@ code here could as well be applied to both merge DBs
269    // - question about saving only with target DB!
270
271    if (gb_main_ref) {
272        if (GB_read_clients(gb_main_ref)>=0) {
273            if (GB_read_clock(gb_main_ref) > GB_last_saved_clock(gb_main_ref)) {
274                long secs;
275                secs = GB_last_saved_time(gb_main_ref);
276
277#if defined(DEBUG)
278                secs =  GB_time_of_day(); // simulate "just saved"
279#endif // DEBUG
280
281                const char *quit_buttons = "Quit ARB,Do NOT quit";
282                if (secs) {
283                    secs = GB_time_of_day() - secs;
284                    if (secs>10) {
285                        char *question = GBS_global_string_copy("You last saved your data %li:%li minutes ago\nSure to quit ?", secs/60, secs%60);
286                        int   dontQuit = aw_question("quit_arb", question, quit_buttons);
287                        free(question);
288                        if (dontQuit) {
289                            return false;
290                        }
291                    }
292                }
293                else {
294                    if (aw_question("quit_arb", "You never saved any data\nSure to quit ???", quit_buttons)) {
295                        return false;
296                    }
297                }
298            }
299        }
300
301        GBCMS_shutdown(gb_main_ref);
302
303        GBDATA *gb_main = gb_main_ref;
304        gb_main_ref     = NULp;                  // avoid further usage
305
306        nt_assert(aw_root);
307
308        // @@@ instead of directly calling the following functions, try to add them as GB_atclose_callback
309        aw_root->unlink_awars_from_DB(gb_main);
310        AWT_destroy_input_masks();
311#if defined(DEBUG)
312        AWT_browser_forget_db(gb_main);
313#endif // DEBUG
314
315        GB_close(gb_main);
316    }
317    return true;
318}
319
320static void nt_run(const char *command) {
321    GB_ERROR error = GBK_system(command);
322    if (error) {
323        fprintf(stderr, "nt_run: Failed to run '%s' (Reason: %s)\n", command, error);
324#if defined(DEBUG)
325        GBK_dump_backtrace(stderr, "nt_run-error");
326#endif
327    }
328}
329
330void NT_start(const char *arb_ntree_args, bool restart_with_new_ARB_PID) {
331    char *command = GBS_global_string_copy("arb_launcher --async %s %s", restart_with_new_ARB_PID ? "arb" : "arb_ntree", arb_ntree_args);
332    nt_run(command);
333    free(command);
334}
335
336__ATTR__NORETURN static void really_exit(int exitcode, bool kill_my_clients) {
337    if (kill_my_clients) {
338        nt_run("(arb_clean session; echo ARB done) &"); // kills all clients
339    }
340    exit(exitcode);
341}
342
343void NT_exit(AW_window *aws, int exitcode) {
344    AW_root *aw_root = aws->get_root();
345    AWTI_cleanup_importer();
346    shutdown_macro_recording(aw_root);
347    bool is_server_and_has_clients = GLOBAL.gb_main && GB_read_clients(GLOBAL.gb_main)>0;
348    if (nt_disconnect_from_db(aw_root, GLOBAL.gb_main)) {
349        really_exit(exitcode, is_server_and_has_clients);
350    }
351}
352void NT_restart(AW_root *aw_root, const char *arb_ntree_args) {
353    // restarts arb_ntree (with new ARB_PID)
354    bool is_server_and_has_clients = GLOBAL.gb_main && GB_read_clients(GLOBAL.gb_main)>0;
355    if (nt_disconnect_from_db(aw_root, GLOBAL.gb_main))  {
356        NT_start(arb_ntree_args, true);
357        really_exit(EXIT_SUCCESS, is_server_and_has_clients);
358    }
359}
360
361static void nt_start_2nd_arb(AW_window *aww, bool quit) {
362    // start 2nd arb with intro window
363    AW_root *aw_root = aww->get_root();
364    char    *dir4intro;
365    GB_split_full_path(aw_root->awar(AWAR_DB_PATH)->read_char_pntr(), &dir4intro, NULp, NULp, NULp);
366    if (!dir4intro) {
367        dir4intro = ARB_strdup(".");
368    }
369
370    if (quit) {
371        NT_restart(aw_root, dir4intro);
372    }
373    else {
374        NT_start(dir4intro, true);
375    }
376    free(dir4intro);
377}
378
379// --------------------------------------------------------------------------------
380
381static void NT_save_quick_cb(AW_window *aww) {
382    AW_root *awr      = aww->get_root();
383    char    *filename = awr->awar(AWAR_DB_PATH)->read_string();
384
385    awr->dont_save_awars_with_default_value(GLOBAL.gb_main);
386
387    GB_ERROR error = GB_save_quick(GLOBAL.gb_main, filename);
388    free( filename);
389    if (error) aw_message(error);
390    else       AW_refresh_fileselection(awr, AWAR_DBBASE);
391}
392
393
394static void NT_save_quick_as_cb(AW_window *aww) {
395    AW_root  *awr      = aww->get_root();
396    char     *filename = awr->awar(AWAR_DB_PATH)->read_string();
397    GB_ERROR  error    = GB_save_quick_as(GLOBAL.gb_main, filename);
398    if (!error) AW_refresh_fileselection(awr, AWAR_DBBASE);
399    aww->hide_or_notify(error);
400
401    free(filename);
402}
403
404#define AWAR_DB_TYPE          AWAR_DBBASE "/type"      // created by AWT_insert_DBsaveType_selector
405#define AWAR_DB_COMPRESSION   AWAR_DBBASE "/compression" // created by AWT_insert_DBcompression_selector
406#define AWAR_DB_OPTI_TREENAME AWAR_DBBASE "/optimize_tree_name"
407
408static void NT_save_as_cb(AW_window *aww) {
409    AW_root    *awr      = aww->get_root();
410    char       *filename = awr->awar(AWAR_DB_PATH)->read_string();
411    const char *atype    = awr->awar(AWAR_DB_TYPE)->read_char_pntr();
412    const char *ctype    = awr->awar(AWAR_DB_COMPRESSION)->read_char_pntr();
413    char       *savetype = GBS_global_string_copy("%s%s", atype, ctype);
414
415    awr->dont_save_awars_with_default_value(GLOBAL.gb_main);
416    GB_ERROR error = GB_save(GLOBAL.gb_main, filename, savetype);
417    if (!error) AW_refresh_fileselection(awr, AWAR_DBBASE);
418    aww->hide_or_notify(error);
419
420    free(savetype);
421    free(filename);
422}
423
424static AW_window *NT_create_save_quick_as_window(AW_root *aw_root, const char *base_name) {
425    static AW_window_simple *aws = NULp;
426    if (!aws) {
427        aws = new AW_window_simple;
428        aws->init(aw_root, "SAVE_CHANGES_TO", "Quicksave changes as");
429        aws->load_xfig("save_as.fig");
430
431        aws->at("close");
432        aws->callback(AW_POPDOWN);
433        aws->create_button("CLOSE", "CLOSE", "C");
434
435        aws->callback(makeHelpCallback("save.hlp"));
436        aws->at("help");
437        aws->create_button("HELP", "HELP", "H");
438
439        AW_create_standard_fileselection(aws, base_name);
440
441        aws->at("comment");
442        aws->create_text_field(AWAR_DB_COMMENT);
443
444        aws->at("save");
445        aws->callback(NT_save_quick_as_cb);
446        aws->create_button("SAVE", "SAVE", "S");
447    }
448    return aws;
449}
450
451static void NT_database_optimization(AW_window *aww) {
452    arb_progress        progress("Optimizing database compression", 2L);
453    GB_topSecurityLevel unsecured(GLOBAL.gb_main);
454
455    GB_ERROR error = GB_begin_transaction(GLOBAL.gb_main);
456    if (!error) {
457        ConstStrArray ali_names;
458        GBT_get_alignment_names(ali_names, GLOBAL.gb_main);
459
460        arb_progress ali_progress("Optimizing sequence data", ali_names.size());
461        ali_progress.allow_title_reuse();
462
463        error = GBT_check_data(GLOBAL.gb_main, NULp);
464        error = GB_end_transaction(GLOBAL.gb_main, error);
465
466        if (!error) {
467            char *tree_name = aww->get_root()->awar(AWAR_DB_OPTI_TREENAME)->read_string();
468            for (int i = 0; ali_names[i]; ++i) {
469                error = GBT_compress_sequence_tree2(GLOBAL.gb_main, tree_name, ali_names[i]);
470                ali_progress.inc_and_check_user_abort(error);
471            }
472            free(tree_name);
473        }
474    }
475    progress.inc_and_check_user_abort(error);
476
477    if (!error) {
478        error = GB_optimize(GLOBAL.gb_main);
479        progress.inc_and_check_user_abort(error);
480    }
481    aww->hide_or_notify(error);
482}
483
484static AW_window *NT_create_database_optimization_window(AW_root *aw_root) {
485    static AW_window_simple *aws = NULp;
486    if (aws) return aws;
487    GB_transaction ta(GLOBAL.gb_main);
488
489    const char *largest_tree = GBT_name_of_largest_tree(GLOBAL.gb_main);
490    aw_root->awar_string(AWAR_DB_OPTI_TREENAME, largest_tree);
491
492    aws = new AW_window_simple;
493    aws->init(aw_root, "OPTIMIZE_DATABASE", "Optimize database compression");
494    aws->load_xfig("optimize.fig");
495
496    aws->at("trees");
497    awt_create_TREE_selection_list(GLOBAL.gb_main, aws, AWAR_DB_OPTI_TREENAME, true);
498
499    aws->at("close");
500    aws->callback(AW_POPDOWN);
501    aws->create_button("CLOSE", "CLOSE", "C");
502
503    aws->callback(makeHelpCallback("optimize.hlp"));
504    aws->at("help");
505    aws->create_button("HELP", "HELP", "H");
506
507    aws->at("go");
508    aws->callback(NT_database_optimization);
509    aws->create_button("GO", "GO");
510    return aws;
511}
512
513static AW_window *NT_create_save_as(AW_root *aw_root, const char *base_name) {
514    static AW_window_simple *aws = NULp;
515    if (aws) return aws;
516
517    aws = new AW_window_simple;
518    aws->init(aw_root, "SAVE_DB", "SAVE ARB DB");
519    aws->load_xfig("save_as.fig");
520
521    aws->at("close");
522    aws->callback(AW_POPDOWN);
523    aws->create_button("CLOSE", "CLOSE", "C");
524
525    aws->at("help");
526    aws->callback(makeHelpCallback("save.hlp"));
527    aws->create_button("HELP", "HELP", "H");
528
529    AW_create_standard_fileselection(aws, base_name);
530
531    aws->at("type");
532    AWT_insert_DBsaveType_selector(aws, AWAR_DB_TYPE);
533
534    aws->at("compression");
535    AWT_insert_DBcompression_selector(aws, AWAR_DB_COMPRESSION);
536
537    aws->at("optimize");
538    aws->callback(NT_create_database_optimization_window);
539    aws->help_text("optimize.hlp");
540    aws->create_autosize_button("OPTIMIZE", "Optimize database compression");
541
542    aws->at("save");
543    aws->callback(NT_save_as_cb);
544    aws->create_button("SAVE", "SAVE", "S");
545
546    aws->at("comment");
547    aws->create_text_field(AWAR_DB_COMMENT);
548
549    return aws;
550}
551
552static void NT_undo_cb(AW_window*, GB_UNDO_TYPE undo_type, TREE_canvas *ntw) {
553    GB_ERROR error = GB_undo(GLOBAL.gb_main, undo_type);
554    if (error) aw_message(error);
555    else {
556        GB_transaction ta(GLOBAL.gb_main);
557        AWT_auto_refresh allowed_on(ntw);
558        ntw->request_refresh();
559    }
560}
561
562enum streamSource { FROM_PIPE, FROM_FILE };
563static char *stream2str(streamSource source, const char *commandOrFile) {
564    char *output = NULp;
565    FILE *in     = NULp;
566
567    switch (source) {
568        case FROM_PIPE: in = popen(commandOrFile, "r"); break;
569        case FROM_FILE: in = fopen(commandOrFile, "rt"); break;
570    }
571
572    if (in) {
573        GBS_strstruct *out = GBS_stropen(2000);
574        int c;
575
576        while (EOF != (c = fgetc(in))) GBS_chrcat(out, c);
577
578        switch (source) {
579            case FROM_PIPE: pclose(in); break;
580            case FROM_FILE: fclose(in); break;
581        }
582
583        // skip trailing linefeeds
584        long offset = GBS_memoffset(out);
585        while (offset>0 && GBS_mempntr(out)[offset-1] == '\n') {
586            GBS_str_cut_tail(out, 1);
587            offset--;
588        }
589
590        output = GBS_strclose(out);
591    }
592    return output;
593}
594
595inline void removeTrailingNewlines(char *str) {
596    char *eos = strchr(str, 0)-1;
597    while (eos >= str && eos[0] == '\n') *eos-- = 0;
598}
599
600inline void append_named_value(GBS_strstruct *out, const char *prefix, const char *value) {
601    GBS_strcat(out, GBS_global_string("%-*s: %s\n", 12, prefix, value));
602}
603inline void append_command_output(GBS_strstruct *out, const char *prefix, const char *command) {
604    char *output = stream2str(FROM_PIPE, command);
605    if (output) {
606        removeTrailingNewlines(output);
607        if (strcmp(output, "unknown") != 0) append_named_value(out, prefix, output);
608        free(output);
609    }
610}
611
612static void NT_infomode_cb(UNFIXED, TREE_canvas *canvas, AWT_COMMAND_MODE mode) {
613    DBUI::popup_species_info_window(canvas->awr, canvas->gb_main);
614    nt_mode_event(NULp, canvas, mode);
615}
616
617static void NT_mark_duplicates(UNFIXED, TREE_canvas *ntw) {
618    AP_tree *tree_root = AWT_TREE(ntw)->get_root_node();
619    if (tree_root) {
620        AWT_auto_refresh allowed_on(ntw);
621        GB_transaction   ta(ntw->gb_main);
622
623        NT_mark_all_cb(NULp, ntw, 0); // unmark all
624        tree_root->mark_duplicates();
625        ntw->request_structure_update();
626    }
627}
628
629static void NT_justify_branch_lenghs(UNFIXED, TREE_canvas *ntw) {
630    GB_transaction  ta(ntw->gb_main);
631    AP_tree        *tree_root = AWT_TREE(ntw)->get_root_node();
632
633    if (tree_root) {
634        AWT_auto_refresh allowed_on(ntw);
635        tree_root->justify_branch_lenghs(ntw->gb_main);
636        ntw->request_save_and_zoom_reset();
637    }
638}
639
640#if defined(DEBUG)
641static void NT_fix_database(AW_window *) {
642    GB_ERROR err = NULp;
643    err = GB_fix_database(GLOBAL.gb_main);
644    if (err) aw_message(err);
645}
646#endif
647
648static void relink_pseudo_species_to_organisms(GBDATA *&ref_gb_node, char *&ref_name, GB_HASH *organism_hash) {
649    if (ref_gb_node) {
650        if (GEN_is_pseudo_gene_species(ref_gb_node)) {
651            GBDATA *gb_organism = GEN_find_origin_organism(ref_gb_node, organism_hash);
652
653            if (gb_organism) {
654                char *name = GBT_read_string(gb_organism, "name");
655
656                if (name) {
657                    freeset(ref_name, name);
658                    ref_gb_node = gb_organism;
659                }
660            }
661        }
662    }
663}
664
665static void NT_pseudo_species_to_organism(AW_window *, TREE_canvas *ntw) {
666    GB_transaction  ta(ntw->gb_main);
667    AP_tree        *tree_root = AWT_TREE(ntw)->get_root_node();
668
669    if (tree_root) {
670        AWT_auto_refresh allowed_on(ntw);
671
672        GB_HASH *organism_hash = GBT_create_organism_hash(ntw->gb_main);
673        tree_root->relink_tree(ntw->gb_main, relink_pseudo_species_to_organisms, organism_hash);
674        GBS_free_hash(organism_hash);
675        ntw->request_save();
676    }
677}
678
679
680// #########################################
681// #########################################
682// ###                                   ###
683// ##          user mask section          ##
684// ###                                   ###
685// #########################################
686// #########################################
687
688struct nt_item_type_species_selector FINAL_TYPE : public awt_item_type_selector {
689    nt_item_type_species_selector() : awt_item_type_selector(AWT_IT_SPECIES) {}
690    ~nt_item_type_species_selector() OVERRIDE {}
691
692    const char *get_self_awar() const OVERRIDE {
693        return AWAR_SPECIES_NAME;
694    }
695    size_t get_self_awar_content_length() const OVERRIDE {
696        return 12; // should be enough for "nnaammee.999"
697    }
698    GBDATA *current(AW_root *root, GBDATA *gb_main) const OVERRIDE { // give the current item
699        char           *species_name = root->awar(get_self_awar())->read_string();
700        GBDATA         *gb_species   = NULp;
701
702        if (species_name[0]) {
703            GB_transaction ta(gb_main);
704            gb_species = GBT_find_species(gb_main, species_name);
705        }
706
707        free(species_name);
708        return gb_species;
709    }
710    const char *getKeyPath() const OVERRIDE { // give the keypath for items
711        return CHANGE_KEY_PATH;
712    }
713};
714
715static nt_item_type_species_selector item_type_species;
716
717static void NT_open_mask_window(AW_window *aww, int id, GBDATA *gb_main) {
718    const awt_input_mask_descriptor *descriptor = AWT_look_input_mask(id);
719    nt_assert(descriptor);
720    if (descriptor) AWT_initialize_input_mask(aww->get_root(), gb_main, &item_type_species, descriptor->get_internal_maskname(), descriptor->is_local_mask());
721}
722
723static void NT_create_mask_submenu(AW_window_menu_modes *awm) {
724    AWT_create_mask_submenu(awm, AWT_IT_SPECIES, NT_open_mask_window, GLOBAL.gb_main);
725}
726static AW_window *create_colorize_species_window(AW_root *aw_root) {
727    return QUERY::create_colorize_items_window(aw_root, GLOBAL.gb_main, SPECIES_get_selector());
728}
729
730static void NT_update_marked_counter(GBDATA*, AW_window* aww) {
731    /*! Updates marked counter and issues redraw on tree if number of marked species changes.
732     * Called on any change of species_information container.
733     */
734    long        count   = GBT_count_marked_species(GLOBAL.gb_main);
735    const char *buffer  = count ? GBS_global_string("%li marked", count) : "";
736    AW_awar    *counter = aww->get_root()->awar(AWAR_MARKED_SPECIES_COUNTER);
737    char       *oldval  = counter->read_string();
738    if (strcmp(oldval, buffer)) {
739        counter->write_string(buffer);
740        aww->get_root()->awar(AWAR_TREE_REFRESH)->touch();
741    }
742    free(oldval);
743}
744
745// --------------------------------------------------------------------------------------------------
746
747static void NT_alltree_remove_leafs(AW_window *, GBT_TreeRemoveType mode, GBDATA *gb_main) {
748    GB_ERROR       error = NULp;
749    GB_transaction ta(gb_main);
750
751    ConstStrArray tree_names;
752    GBT_get_tree_names(tree_names, gb_main, false);
753
754    if (!tree_names.empty()) {
755        long treeCount = tree_names.size();
756
757        const char *whats_removed = NULp;
758        switch (mode) {
759            case GBT_REMOVE_ZOMBIES: whats_removed = "zombies"; break;
760            case GBT_REMOVE_MARKED:  whats_removed = "marked";  break;
761            default: nt_assert(0); break;
762        }
763
764        const char *task = GBS_global_string("Deleting %s from %li trees", whats_removed, treeCount);
765
766        arb_progress  progress(task, treeCount);
767        GB_HASH      *species_hash = GBT_create_species_hash(gb_main);
768
769        int modified = 0;
770
771        for (int t = 0; t<treeCount && !error; t++) {
772            progress.subtitle(tree_names[t]);
773            TreeNode *tree = GBT_read_tree(gb_main, tree_names[t], new SimpleRoot);
774            if (!tree) {
775                aw_message(GBS_global_string("Can't load tree '%s' - skipped", tree_names[t]));
776            }
777            else {
778                int removed        = 0;
779                int groups_removed = 0;
780
781                tree = GBT_remove_leafs(tree, mode, species_hash, &removed, &groups_removed);
782
783                nt_assert(removed >= groups_removed);
784
785                if (!tree) {
786                    aw_message(GBS_global_string("'%s' would disappear. Please delete tree manually.", tree_names[t]));
787                }
788                else {
789                    if (removed>0) {
790                        error = GBT_write_tree(gb_main, tree_names[t], tree);
791                        if (error) {
792                            aw_message(GBS_global_string("Failed to write '%s' (Reason: %s)", tree_names[t], error));
793                        }
794                        else {
795                            if (groups_removed>0) {
796                                aw_message(GBS_global_string("Removed %i species and %i groups from '%s'", removed, groups_removed, tree_names[t]));
797                            }
798                            else {
799                                aw_message(GBS_global_string("Removed %i species from '%s'", removed, tree_names[t]));
800                            }
801                            modified++;
802                        }
803                    }
804                    UNCOVERED();
805                    destroy(tree);
806                }
807            }
808            progress.inc_and_check_user_abort(error);
809        }
810
811        if (modified) {
812            aw_message(GBS_global_string("Changed %i of %li trees.", modified, treeCount));
813        }
814        else {
815            aw_message("No tree modified");
816        }
817
818        GBS_free_hash(species_hash);
819    }
820
821    aw_message_if(ta.close(error));
822}
823
824TreeNode *NT_get_tree_root_of_canvas(TREE_canvas *ntw) {
825    AWT_graphic_tree *tree = AWT_TREE(ntw);
826    if (tree) {
827        AP_tree *root = tree->get_root_node();
828        if (root) return root;
829    }
830    return NULp;
831}
832
833// --------------------------------------------------------------------------------------------------
834
835static ARB_ERROR mark_referred_species(GBDATA *gb_main, const DBItemSet& referred) {
836    GB_transaction ta(gb_main);
837    GBT_mark_all(gb_main, 0);
838
839    DBItemSetIter end = referred.end();
840    for (DBItemSetIter s = referred.begin(); s != end; ++s) {
841        GB_write_flag(*s, 1);
842    }
843    return ARB_ERROR();
844}
845
846static AW_window *create_mark_by_refentries_window(AW_root *awr, GBDATA *gbmain) {
847    static AW_window *aws = NULp;
848    if (!aws) {
849        static RefEntries::ReferringEntriesHandler reh(gbmain, SPECIES_get_selector());
850        aws = RefEntries::create_refentries_window(awr, &reh, "markbyref", "Mark by reference", "markbyref.hlp", NULp, "Mark referenced", mark_referred_species);
851    }
852    return aws;
853}
854
855// --------------------------------------------------------------------------------------------------
856
857static void merge_from_to(AW_root *awr, const char *db_awar_name, bool merge_to) {
858    const char *db_name  = awr->awar(db_awar_name)->read_char_pntr();
859    char       *quotedDB = GBK_singlequote(db_name);
860
861    AWT_system_cb(
862        GBS_global_string(
863            merge_to
864            ? "arb_ntree : %s &"
865            : "arb_ntree %s : &",
866            quotedDB)
867        );
868
869    free(quotedDB);
870}
871
872static void merge_from_cb(AW_window *aww, AW_CL cl_awarNamePtr) { merge_from_to(aww->get_root(), *(const char**)cl_awarNamePtr, false); }
873static void merge_into_cb(AW_window *aww, AW_CL cl_awarNamePtr) { merge_from_to(aww->get_root(), *(const char**)cl_awarNamePtr, true); }
874
875static AW_window *NT_create_merge_from_window(AW_root *awr) {
876    static char *awar_name = NULp; // do not free, bound to callback
877    AW_window *aw_from     =
878        awt_create_load_box(awr, "Merge data from", "other ARB database",
879                            ".", ".arb", &awar_name,
880                            makeWindowCallback(merge_from_cb, AW_CL(&awar_name)));
881    return aw_from;
882}
883static AW_window *NT_create_merge_to_window(AW_root *awr) {
884    static char *awar_name = NULp; // do not free, bound to callback
885    AW_window *aw_to       =
886        awt_create_load_box(awr, "Merge data to", "other ARB database",
887                            ".", ".arb", &awar_name,
888                            makeWindowCallback(merge_into_cb, AW_CL(&awar_name)),
889                            makeWindowCallback(AW_POPDOWN), NULp);
890    return aw_to;
891}
892
893// --------------------------------------------------------------------------------------------------
894
895static void update_main_window_title(AW_root* awr, AW_window_menu_modes* aww, int clone) {
896    const char* filename = awr->awar(AWAR_DB_NAME)->read_char_pntr();
897    if (clone) {
898        aww->set_window_title(GBS_global_string("%s - ARB (%i)",  filename, clone));
899    }
900    else {
901        aww->set_window_title(GBS_global_string("%s - ARB", filename));
902    }
903}
904
905static void canvas_tree_awar_changed_cb(AW_awar *, bool, TREE_canvas *ntw) {
906    NT_reload_tree_event(AW_root::SINGLETON, ntw, true);
907    AW_root::SINGLETON->awar(AWAR_NTREE_MAIN_WINDOW_COUNT)->touch(); // refresh canvas selection lists
908    TREE_auto_jump_cb(NULp, ntw, AP_JUMP_REASON_TREE);
909}
910
911class TREE_canvas_registry {
912    int          count;
913    TREE_canvas *canvas[MAX_NT_WINDOWS];
914
915    static TREE_canvas_registry *SINGLETON;
916
917    TREE_canvas_registry() : count(0) {
918        AW_root::SINGLETON->awar_int(AWAR_NTREE_MAIN_WINDOW_COUNT, 0, AW_ROOT_DEFAULT);
919    }
920
921public:
922    static TREE_canvas_registry& instance() {
923        if (!SINGLETON) SINGLETON = new TREE_canvas_registry;
924        return *SINGLETON;
925    }
926
927    void register_canvas(TREE_canvas *ntw) {
928        nt_assert(count<MAX_NT_WINDOWS);
929        nt_assert(count == ntw->get_index()); // you have to register TREE_canvas'es in order of creation!
930        canvas[count++] = ntw;
931        ntw->awr->awar(AWAR_NTREE_MAIN_WINDOW_COUNT)->write_int(count); // trigger callbacks
932    }
933
934    int get_count() const  { return count; }
935
936    TREE_canvas *get_canvas(int idx) const {
937        if (idx<0 || idx>=count) return NULp;
938        return canvas[idx];
939    }
940};
941
942TREE_canvas_registry *TREE_canvas_registry::SINGLETON = NULp;
943
944TREE_canvas *NT_get_canvas_by_index(int idx) {
945    /*! return canvas with index 'idx' [0...MAX_NT_WINDOWS-1] */
946    nt_assert(idx>=0 && idx<MAX_NT_WINDOWS);
947    return TREE_canvas_registry::instance().get_canvas(idx);
948}
949
950#if defined(TRACE_GROUP_SELECTION)
951static TREE_canvas *find_canvas_showing(AWT_graphic_tree *agt) {
952    // look for (registered) canvas showing given AWT_graphic_tree
953    // returns NULp if none found
954    const TREE_canvas_registry& reg = TREE_canvas_registry::instance();
955
956    int maxIdx = reg.get_count();
957    for (int32_t i = 0; i<maxIdx; ++i) {
958        TREE_canvas *ntw = reg.get_canvas(i);
959        if (ntw->gfx == agt) return ntw;
960    }
961    return NULp;
962}
963#endif
964
965void NT_fill_canvas_selection_list(class AW_selection_list *sellst, TREE_canvas *to_skip) {
966    /*! insert canvases into selection list (using canvas-indices as values)
967     */
968    const TREE_canvas_registry& reg = TREE_canvas_registry::instance();
969
970    int maxIdx = reg.get_count();
971    for (int32_t i = 0; i<maxIdx; ++i) {
972        TREE_canvas *ntw = reg.get_canvas(i);
973        if (ntw && ntw != to_skip) {
974            nt_assert(ntw->get_awar_tree());
975            const char *treename    = ntw->get_awar_tree()->read_char_pntr();
976            const char *description = i
977                ? GBS_global_string("ARB (%i):  %s", i, treename)
978                : GBS_global_string("ARB main: %s", treename);
979            sellst->insert(description, i);
980        }
981    }
982}
983
984// ----------------------------------
985//      group-selection handlers
986
987void NT_deselect_group(AW_root *awr) {
988    awr->awar(AWAR_GROUP)->write_pointer(NULp);
989}
990
991static bool track_group_selection_by_canvas = true;
992
993static void group_selected_by_canvas_cb(AWT_graphic_tree *gfx) {
994    const Group& group = gfx->get_selected_group();
995
996#if defined(TRACE_GROUP_SELECTION)
997    fprintf(stderr, "[%s] ", track_group_selection_by_canvas ? "track" : "dont track");
998    TREE_canvas *ntw = find_canvas_showing(gfx);
999    if (group.is_valid()) {
1000        fprintf(stderr, "canvas %i selects group '%s'\n", ntw->get_index(), group.get_name());
1001    }
1002    else {
1003        fprintf(stderr, "canvas %i de-selects group\n", ntw->get_index());
1004    }
1005#endif
1006
1007    if (track_group_selection_by_canvas) {
1008        // set group-awar:
1009        gfx->get_root()->awar(AWAR_GROUP)->write_pointer(group.get_group_data()); // writes NULp if !group.is_valid()
1010    }
1011}
1012
1013static void group_awar_changed_cb(AW_root *awr) {
1014    AW_awar *awar_group      = awr->awar(AWAR_GROUP);
1015    GBDATA  *gb_wanted_group = awar_group->read_pointer();
1016
1017    GBDATA *gb_wanted_tree = NULp;
1018    {
1019        if (gb_wanted_group) {
1020            GB_transaction ta(gb_wanted_group);
1021            gb_wanted_tree = GB_get_father(gb_wanted_group);
1022            awr->awar(AWAR_SPECIES_NAME)->write_string(""); // deselect species when group gets selected
1023#if defined(TRACE_GROUP_SELECTION)
1024            fputs("clear AWAR_SPECIES_NAME (because group selected)\n", stderr);
1025#endif
1026        }
1027#if defined(TRACE_GROUP_SELECTION)
1028        const char *group_name = NULp;
1029        if (gb_wanted_group) {
1030            GB_transaction  ta(gb_wanted_group);
1031            GBDATA         *gb_name = GB_entry(gb_wanted_group, "group_name");
1032            if (gb_name) group_name = GB_read_char_pntr(gb_name);
1033        }
1034        fprintf(stderr, "group awar changed to %p", gb_wanted_group);
1035        if (group_name) fprintf(stderr, " (='%s')", group_name);
1036        fputc('\n', stderr);
1037#endif
1038    }
1039
1040    LocallyModify<bool> ignore_group_selection_by_canvas(track_group_selection_by_canvas, false);
1041
1042    {
1043        const TREE_canvas_registry& reg = TREE_canvas_registry::instance();
1044
1045        int maxIdx = reg.get_count();
1046        for (int32_t i = 0; i<maxIdx; ++i) {
1047            TREE_canvas      *ntw        = reg.get_canvas(i);
1048            AWT_graphic_tree *agt        = AWT_TREE(ntw);
1049            const Group&      curr_group = agt->get_selected_group();
1050
1051            GBDATA *gb_curr_tree = agt->get_tree_root()->get_gb_tree();
1052            if (gb_curr_tree == gb_wanted_tree) {
1053                AWT_auto_refresh allowed_on(ntw);
1054                if (!curr_group.is_valid() ||                       // no group selected
1055                    curr_group.get_group_data() != gb_wanted_group) // wrong group selected
1056                {
1057                    agt->select_group(gb_wanted_group);
1058                    ntw->request_refresh();
1059                }
1060                // perform auto-jump (also if group was already selected, otherwise group-traversal keys will not follow the selected group)
1061                TREE_auto_jump_cb(NULp, ntw, AP_JUMP_REASON_GROUP);
1062            }
1063            else {
1064                if (curr_group.is_valid()) {
1065                    AWT_auto_refresh allowed_on(ntw);
1066                    agt->deselect_group();
1067                    ntw->request_refresh();
1068                }
1069            }
1070        }
1071    }
1072}
1073
1074// ----------------------------
1075//      create main window
1076
1077static AW_window *popup_new_main_window(AW_root *awr, int clone, TREE_canvas **result_ntw) {
1078    /*! create ARB_NTREE main window
1079     * @param awr application root
1080     * @param clone == 0 -> first window (full functionality); >0 -> additional tree views (restricted functionality)
1081     * @param result_ntw is set to the created TREE_canvas (passed pointer may be NULp if result is not needed)
1082     */
1083    GB_push_transaction(GLOBAL.gb_main);
1084
1085    char        window_title[256];
1086    const char *awar_tree = NULp;
1087
1088    if (clone) {
1089        awar_tree = ARB_keep_string(GBS_global_string_copy(AWAR_TREE "_%i", clone));
1090        sprintf(window_title, "ARB_NT_%i", clone);
1091    }
1092    else {
1093        awar_tree = AWAR_TREE;
1094        sprintf(window_title, "ARB_NT");
1095    }
1096    AW_window_menu_modes *awm = new AW_window_menu_modes;
1097    awm->init(awr, window_title, window_title, 0, 0);
1098
1099    awr->awar(AWAR_DB_NAME)
1100       ->add_callback(makeRootCallback(update_main_window_title, awm, clone))
1101       ->update();
1102
1103    awm->button_length(5);
1104
1105    if (!clone) AW_init_color_group_defaults("arb_ntree");
1106
1107    AWT_graphic_tree *tree = NT_generate_tree(awr, GLOBAL.gb_main, launch_MapViewer_cb);
1108
1109    if (!clone) { // while creating initial window
1110        AWT_graphic_tree::install_group_changed_callback(makeGraphicTreeCallback(group_selected_by_canvas_cb));
1111        awr->awar(AWAR_GROUP)->add_callback(group_awar_changed_cb);
1112    }
1113
1114    TREE_canvas *ntw;
1115    {
1116        AW_awar *tree_awar = awr->awar_string(awar_tree);
1117        {
1118            AP_tree_display_style prev_style = tree->get_tree_style();
1119            tree->set_tree_style(AP_LIST_SIMPLE, NULp); // avoid NDS warnings during startup
1120
1121            ntw = new TREE_canvas(GLOBAL.gb_main, awm, "ARB_NT", tree, tree_awar);
1122            tree->set_tree_style(prev_style, ntw);
1123            ntw->set_mode(AWT_MODE_SELECT);
1124        }
1125
1126        if (result_ntw) *result_ntw = ntw;
1127
1128        {
1129            const char *tree_name          = tree_awar->read_char_pntr();
1130            const char *existing_tree_name = GBT_existing_tree(GLOBAL.gb_main, tree_name);
1131
1132            if (existing_tree_name) {
1133                tree_awar->write_string(existing_tree_name);
1134                NT_reload_tree_event(awr, ntw, true); // load first tree
1135            }
1136            else {
1137                AW_advice("Your database contains no tree.", AW_ADVICE_TOGGLE_AND_HELP, NULp, "no_tree.hlp");
1138                tree->set_tree_style(AP_LIST_NDS, ntw); // no tree -> show NDS list
1139            }
1140
1141            TREE_canvas_registry::instance().register_canvas(ntw);
1142            AWT_registerTreeAwarCallback(tree_awar, makeTreeAwarCallback(canvas_tree_awar_changed_cb, ntw), false);
1143        }
1144    }
1145
1146    TREE_install_update_callbacks(ntw);
1147
1148    bool is_genome_db = GEN_is_genome_db(GLOBAL.gb_main, 0); //  is this a genome database ? (default = 0 = not a genom db)
1149
1150    WindowCallback popupinfo_wcb = RootAsWindowCallback::simple(DBUI::popup_species_info_window, GLOBAL.gb_main);
1151
1152    // --------------
1153    //      File
1154
1155#if defined(DEBUG)
1156    AWT_create_debug_menu(awm);
1157#endif // DEBUG
1158
1159    bool allow_new_window = (ntw->get_index()+1) < MAX_NT_WINDOWS;
1160
1161    if (clone) {
1162        awm->create_menu("File", "F", AWM_ALL);
1163        if (allow_new_window) {
1164            awm->insert_menu_topic(awm->local_id("new_window"), "New window (same database)", "N", "newwindow.hlp", AWM_ALL, makeCreateWindowCallback(popup_new_main_window, clone+1, (TREE_canvas**)NULp));
1165        }
1166        awm->insert_menu_topic("close", "Close", "C", NULp, AWM_ALL, AW_POPDOWN);
1167    }
1168    else {
1169#if defined(DEBUG)
1170        // add more to debug-menu
1171        awm->sep______________();
1172        awm->insert_menu_topic("fix_db",      "Fix database",            "F", NULp, AWM_ALL, NT_fix_database);
1173        awm->insert_menu_topic("debug_arbdb", "Print debug information", "d", NULp, AWM_ALL, makeWindowCallback(GB_print_debug_information, GLOBAL.gb_main));
1174        awm->insert_menu_topic("test_compr",  "Test compression",        "T", NULp, AWM_ALL, makeWindowCallback(GBT_compression_test,       GLOBAL.gb_main));
1175#endif // DEBUG
1176
1177        awm->create_menu("File", "F", AWM_ALL);
1178        {
1179            // keep the following entries in sync with ../EDIT4/ED4_root.cxx@common_save_menu_entries
1180            awm->insert_menu_topic("save_changes", "Quicksave changes",          "s", "save.hlp",      AWM_ALL, NT_save_quick_cb);
1181            awm->insert_menu_topic("save_all_as",  "Save whole database as ...", "w", "save.hlp",      AWM_ALL, makeCreateWindowCallback(NT_create_save_as, AWAR_DBBASE));
1182            if (allow_new_window) {
1183                awm->sep______________();
1184                awm->insert_menu_topic("new_window", "New window (same database)", "N", "newwindow.hlp", AWM_ALL, makeCreateWindowCallback(popup_new_main_window, clone+1, (TREE_canvas**)NULp));
1185            }
1186            awm->sep______________();
1187            awm->insert_menu_topic("optimize_db",  "Optimize database compression", "O", "optimize.hlp",  AWM_ALL, NT_create_database_optimization_window);
1188            awm->sep______________();
1189
1190            awm->insert_sub_menu("Import",      "I");
1191            {
1192                awm->insert_menu_topic("merge_from", "Merge from other ARB database", "d", "arb_merge_into.hlp", AWM_ALL, NT_create_merge_from_window);
1193                awm->insert_menu_topic("import_seq", "Import from external format",   "I", "arb_import.hlp",     AWM_ALL, makeWindowCallback(NT_import_sequences, ntw));
1194                GDE_load_menu(awm, AWM_EXP, "Import");
1195            }
1196            awm->close_sub_menu();
1197
1198            awm->insert_sub_menu("Export",      "E");
1199            {
1200                awm->insert_menu_topic("export_to_ARB", "Merge to (new) ARB database", "A", "arb_merge_outof.hlp", AWM_ALL, NT_create_merge_to_window);
1201                awm->insert_menu_topic("export_seqs",   "Export to external format",   "f", "arb_export.hlp",      AWM_ALL, makeCreateWindowCallback(create_AWTC_export_window, GLOBAL.gb_main));
1202                GDE_load_menu(awm, AWM_ALL, "Export");
1203                awm->insert_menu_topic("export_nds",    "Export fields (to calc-sheet using NDS)", "N", "arb_export_nds.hlp",  AWM_ALL, create_nds_export_window);
1204            }
1205            awm->close_sub_menu();
1206            awm->sep______________();
1207
1208            insert_macro_menu_entry(awm, false);
1209
1210            awm->insert_sub_menu("VersionInfo/Bugreport/MailingList", "V");
1211            {
1212                awm->insert_menu_topic("version_info", "Version info (" ARB_VERSION_DETAILED ")", "V", "version.hlp", AWM_ALL, makeHelpCallback  ("version.hlp"));
1213                awm->insert_menu_topic("bug_report",   "Report bug",                              "b", NULp,          AWM_ALL, makeWindowCallback(AWT_openURL, "http://bugs.arb-home.de/wiki/BugReport"));
1214                awm->insert_menu_topic("mailing_list", "Mailing list",                            "M", NULp,          AWM_ALL, makeWindowCallback(AWT_openURL, "http://bugs.arb-home.de/wiki/ArbMailingList"));
1215            }
1216            awm->close_sub_menu();
1217            awm->sep______________();
1218
1219            awm->insert_menu_topic("new_arb",     "Start second database",      "d", "quit.hlp", AWM_ALL, makeWindowCallback(nt_start_2nd_arb, false));
1220            awm->insert_menu_topic("restart_arb", "Quit + load other database", "l", "quit.hlp", AWM_ALL, makeWindowCallback(nt_start_2nd_arb, true));
1221            awm->insert_menu_topic("quit",        "Quit",                       "Q", "quit.hlp", AWM_ALL, makeWindowCallback(NT_exit, EXIT_SUCCESS));
1222        }
1223
1224        // -----------------
1225        //      Species
1226
1227        awm->create_menu("Species", "c", AWM_ALL);
1228        {
1229            awm->insert_menu_topic("species_search", "Search and query",    "q", "sp_search.hlp", AWM_ALL, makeCreateWindowCallback(DBUI::create_species_query_window, GLOBAL.gb_main));
1230            awm->insert_menu_topic("species_info",   "Species information", "i", "sp_info.hlp",   AWM_ALL, popupinfo_wcb);
1231
1232            awm->sep______________();
1233
1234            NT_insert_mark_submenus(awm, ntw, 1);
1235            awm->insert_menu_topic("mark_by_ref",     "Mark by reference..", "r", "markbyref.hlp",       AWM_EXP, makeCreateWindowCallback(create_mark_by_refentries_window, GLOBAL.gb_main));
1236            awm->insert_menu_topic("species_colors",  "Colors ...",          "l", "colorize.hlp",        AWM_ALL, create_colorize_species_window);
1237            awm->insert_menu_topic("selection_admin", "Selections ...",      "o", "species_configs.hlp", AWM_ALL, makeWindowCallback(NT_popup_configuration_admin, ntw));
1238
1239            awm->sep______________();
1240
1241            awm->insert_sub_menu("Database fields admin", "f");
1242            DBUI::insert_field_admin_menuitems(awm, GLOBAL.gb_main);
1243            awm->close_sub_menu();
1244            NT_create_mask_submenu(awm);
1245
1246            awm->sep______________();
1247
1248            awm->insert_menu_topic("del_marked",    "Delete Marked Species",    "D", "sp_del_mrkd.hlp", AWM_ALL, makeWindowCallback(NT_delete_mark_all_cb, ntw));
1249
1250            awm->insert_sub_menu("Sort Species",         "s");
1251            {
1252                awm->insert_menu_topic("$sort_by_field", "According to Database Entries", "D", "sp_sort_fld.hlp",  AWM_ALL, NT_create_resort_window);
1253                awm->insert_menu_topic("$sort_by_tree",  "According to Phylogeny",        "P", "sp_sort_phyl.hlp", AWM_ALL, makeWindowCallback(NT_resort_data_by_phylogeny, ntw));
1254            }
1255            awm->close_sub_menu();
1256
1257            awm->insert_sub_menu("Merge Species", "g", AWM_EXP);
1258            {
1259                awm->insert_menu_topic("merge_species", "Create merged species from similar species", "m", "merge_species.hlp", AWM_EXP, NT_createMergeSimilarSpeciesWindow);
1260                awm->insert_menu_topic("join_marked",   "Join Marked Species",                        "J", "species_join.hlp",  AWM_EXP, NT_create_species_join_window);
1261            }
1262            awm->close_sub_menu();
1263
1264            awm->sep______________();
1265
1266            awm->insert_menu_topic("species_submission", "Submit Species", "b", "submission.hlp", AWM_EXP, makeCreateWindowCallback(AWTC_create_submission_window, GLOBAL.gb_main));
1267
1268            awm->sep______________();
1269
1270            awm->insert_menu_topic("new_names", "Synchronize IDs", "e", "rename.hlp", AWM_ALL, makeCreateWindowCallback(AWTC_create_rename_window, GLOBAL.gb_main));
1271
1272            awm->insert_sub_menu("Valid Names ...", "V", AWM_EXP);
1273            {
1274                awm->insert_menu_topic("imp_names",    "Import names from file", "I", "vn_import.hlp",  AWM_EXP, NT_importValidNames);
1275                awm->insert_menu_topic("del_names",    "Delete names from DB",   "D", "vn_delete.hlp",  AWM_EXP, NT_deleteValidNames);
1276                awm->insert_menu_topic("sug_names",    "Suggest valid names",    "v", "vn_suggest.hlp", AWM_EXP, NT_suggestValidNames);
1277                awm->insert_menu_topic("search_names", "Search manually",        "m", "vn_search.hlp",  AWM_EXP, NT_create_searchManuallyNames_window);
1278            }
1279            awm->close_sub_menu();
1280        }
1281
1282        // ----------------------------
1283        //      Genes + Experiment
1284
1285        if (is_genome_db) GEN_create_genes_submenu(awm, GLOBAL.gb_main, true);
1286
1287        // ------------------
1288        //      Sequence
1289
1290        awm->create_menu("Sequence", "S", AWM_ALL);
1291        {
1292            awm->insert_menu_topic("seq_admin",   "Sequence/Alignment Admin", "A", "ad_align.hlp",   AWM_ALL, makeCreateWindowCallback(NT_create_alignment_admin_window, (AW_window*)NULp));
1293            awm->insert_sub_menu("Insert/delete", "I");
1294            {
1295                awm->insert_menu_topic("ins_del_col", ".. column",     "c", "insdel.hlp",     AWM_ALL, create_insertDeleteColumn_window);
1296                awm->insert_menu_topic("ins_del_sai", ".. using SAI",  "S", "insdel_sai.hlp", AWM_ALL, makeCreateWindowCallback(create_insertDeleteBySAI_window,  GLOBAL.gb_main));
1297            }
1298            awm->close_sub_menu();
1299            awm->sep______________();
1300
1301            awm->insert_sub_menu("Edit Sequences", "E");
1302            {
1303                awm->insert_menu_topic("new_arb_edit4",  "Using marked species and tree", "m", "arb_edit4.hlp", AWM_ALL, makeWindowCallback(NT_start_editor_on_tree,  0, ntw));
1304                awm->insert_menu_topic("new2_arb_edit4", "... plus relatives",            "r", "arb_edit4.hlp", AWM_ALL, makeWindowCallback(NT_start_editor_on_tree, -1, ntw));
1305                awm->insert_menu_topic("old_arb_edit4",  "Using earlier configuration",   "c", "arb_edit4.hlp", AWM_ALL, NT_create_startEditorOnOldConfiguration_window);
1306            }
1307            awm->close_sub_menu();
1308
1309            awm->sep______________();
1310
1311            awm->insert_sub_menu("Align Sequences",  "S");
1312            {
1313                awm->insert_menu_topic("realign_dna", "Realign DNA according to aligned protein", "R", "realign_dna.hlp", AWM_ALL, NT_create_realign_dna_window);
1314                GDE_load_menu(awm, AWM_ALL, "Align");
1315            }
1316            awm->close_sub_menu();
1317            awm->insert_menu_topic("seq_concat",    "Concatenate Sequences/Alignments", "C", "concatenate.hlp",       AWM_ALL, NT_createConcatenationWindow);
1318            awm->insert_menu_topic("track_changes", "Track alignment changes",          "k", "track_ali_changes.hlp", AWM_EXP, NT_create_trackAliChanges_window);
1319            awm->sep______________();
1320
1321            awm->insert_menu_topic("dna_2_pro", "Perform translation",      "t", "translate_dna_2_pro.hlp", AWM_ALL, NT_create_dna_2_pro_window);
1322            awm->insert_menu_topic("arb_dist",  "Distance Matrix + ARB NJ", "D", "dist.hlp",                AWM_ALL, makeWindowCallback(AWT_system_cb, "arb_dist &"));
1323            awm->sep______________();
1324
1325            awm->insert_menu_topic("seq_quality",   "Check Sequence Quality", "Q", "seq_quality.hlp",   AWM_EXP, makeCreateWindowCallback(SQ_create_seq_quality_window, GLOBAL.gb_main));
1326            awm->insert_menu_topic("chimera_check", "Chimera Check",          "m", "chimera_check.hlp", AWM_EXP, makeCreateWindowCallback(STAT_create_chimera_check_window, GLOBAL.gb_main));
1327
1328            awm->sep______________();
1329
1330            GDE_load_menu(awm, AWM_ALL, "Print");
1331        }
1332
1333        // -------------
1334        //      SAI
1335
1336        awm->create_menu("SAI", "A", AWM_ALL);
1337        {
1338            awm->insert_menu_topic("sai_admin", "Manage SAIs",  "S", "ad_extended.hlp", AWM_ALL, NT_create_extendeds_window);
1339            awm->insert_menu_topic("sai_calc",  "Combine SAIs", "b", "saicalc.hlp",     AWM_ALL, makeWindowCallback(SAI_popup_calculator_window, GLOBAL.gb_main));
1340            awm->insert_sub_menu("Create SAI using ...", "C");
1341            {
1342                awm->insert_menu_topic("sai_max_freq",  "Max. Frequency",                                               "M", "max_freq.hlp",     AWM_EXP, AP_create_max_freq_window);
1343                awm->insert_menu_topic("sai_consensus", "Consensus",                                                    "C", "consensus.hlp",    AWM_ALL, AP_create_con_expert_window);
1344                awm->insert_menu_topic("pos_var_pars",  "Positional variability + Column statistic (parsimony method)", "a", "pos_var_pars.hlp", AWM_ALL, AP_create_pos_var_pars_window);
1345                awm->insert_menu_topic("arb_phyl",      "Filter by base frequency",                                     "F", "phylo.hlp",        AWM_ALL, makeWindowCallback(AWT_system_cb, "arb_phylo &"));
1346                awm->insert_menu_topic("sai_pfold",     "Protein secondary structure (field \"sec_struct\")",           "P", "pfold.hlp",        AWM_EXP, NT_create_sai_from_pfold);
1347
1348                GDE_load_menu(awm, AWM_EXP, "SAI");
1349            }
1350            awm->close_sub_menu();
1351
1352            awm->insert_sub_menu("Other functions", "O");
1353            {
1354                awm->insert_menu_topic("count_different_chars", "Count different chars/column",             "C", "count_chars.hlp",    AWM_EXP, makeWindowCallback(NT_count_different_chars, GLOBAL.gb_main));
1355                awm->insert_menu_topic("corr_mutat_analysis",   "Compute clusters of correlated positions", "m", "",                   AWM_ALL, makeWindowCallback(AWT_system_in_console_cb, "arb_rnacma", XCMD_ASYNC_WAIT_ON_ERROR));
1356                awm->insert_menu_topic("export_pos_var",        "Export Column Statistic (GNUPLOT format)", "E", "csp_2_gnuplot.hlp",  AWM_ALL, NT_create_colstat_2_gnuplot_window);
1357            }
1358            awm->close_sub_menu();
1359        }
1360
1361        // ----------------
1362        //      Probes
1363
1364        awm->create_menu("Probes", "P", AWM_ALL);
1365        {
1366            awm->insert_menu_topic("probe_design", "Design Probes",          "D", "probedesign.hlp", AWM_ALL, makeCreateWindowCallback(create_probe_design_window, GLOBAL.gb_main));
1367            awm->insert_menu_topic("probe_multi",  "Calculate Multi-Probes", "u", "multiprobe.hlp",  AWM_ALL, makeCreateWindowCallback(create_multiprobe_window, ntw));
1368            awm->insert_menu_topic("probe_match",  "Match Probes",           "M", "probematch.hlp",  AWM_ALL, makeCreateWindowCallback(create_probe_match_window, GLOBAL.gb_main));
1369            awm->sep______________();
1370            awm->insert_menu_topic("probe_match_sp",   "Match Probes with Specificity", "f", "probespec.hlp", AWM_ALL, makeCreateWindowCallback(create_probe_match_with_specificity_window,    ntw));
1371            awm->sep______________();
1372            awm->insert_menu_topic("primer_design_new", "Design Primers",            "P", "primer_new.hlp", AWM_EXP, makeCreateWindowCallback(create_primer_design_window, GLOBAL.gb_main));
1373            awm->insert_menu_topic("primer_design",     "Design Sequencing Primers", "S", "primer.hlp",     AWM_EXP, makeWindowCallback(AWT_system_in_console_cb, "arb_primer", XCMD_ASYNC_WAITKEY));
1374            awm->sep______________();
1375            awm->insert_menu_topic("pt_server_admin",   "PT_SERVER Admin",           "A", "probeadmin.hlp",  AWM_ALL, makeCreateWindowCallback(create_probe_admin_window, GLOBAL.gb_main));
1376        }
1377
1378    }
1379
1380    // --------------
1381    //      Tree
1382
1383    awm->create_menu("Tree", "T", AWM_ALL);
1384    {
1385        if (!clone) {
1386            awm->insert_sub_menu("Add Species to Existing Tree", "A");
1387            {
1388                awm->insert_menu_topic("arb_pars_quick", "ARB Parsimony (Quick add marked)", "Q", "pars.hlp", AWM_ALL, makeWindowCallback(AWT_system_cb, "arb_pars -add_marked -quit &"));
1389                awm->insert_menu_topic("arb_pars",       "ARB Parsimony interactive",        "i", "pars.hlp", AWM_ALL, makeWindowCallback(AWT_system_cb, "arb_pars &"));
1390                GDE_load_menu(awm, AWM_EXP, "Incremental phylogeny");
1391            }
1392            awm->close_sub_menu();
1393        }
1394
1395        awm->insert_sub_menu("Remove Species from Tree",     "R");
1396        {
1397            awm->insert_menu_topic(awm->local_id("tree_remove_deleted"), "Remove zombies", "z", "trm_del.hlp",    AWM_ALL, makeWindowCallback(NT_remove_leafs, ntw, AWT_REMOVE_ZOMBIES));
1398            awm->insert_menu_topic(awm->local_id("tree_remove_marked"),  "Remove marked",  "m", "trm_mrkd.hlp",   AWM_ALL, makeWindowCallback(NT_remove_leafs, ntw, AWT_REMOVE_MARKED));
1399            awm->insert_menu_topic(awm->local_id("tree_keep_marked"),    "Keep marked",    "K", "tkeep_mrkd.hlp", AWM_ALL, makeWindowCallback(NT_remove_leafs, ntw, AWT_KEEP_MARKED));
1400            awm->sep______________();
1401            awm->insert_menu_topic("all_tree_remove_deleted", "Remove zombies from ALL trees", "A", "trm_del.hlp",  AWM_ALL, makeWindowCallback(NT_alltree_remove_leafs, GBT_REMOVE_ZOMBIES, GLOBAL.gb_main));
1402            awm->insert_menu_topic("all_tree_remove_marked",  "Remove marked from ALL trees",  "L", "trm_mrkd.hlp", AWM_ALL, makeWindowCallback(NT_alltree_remove_leafs, GBT_REMOVE_MARKED,  GLOBAL.gb_main));
1403        }
1404        awm->close_sub_menu();
1405
1406        if (!clone) {
1407            awm->insert_sub_menu("Build tree from sequence data",    "B");
1408            {
1409                awm->insert_sub_menu("Distance matrix methods", "D");
1410                awm->insert_menu_topic("arb_dist", "Distance Matrix + ARB NJ", "J", "dist.hlp", AWM_ALL, makeWindowCallback(AWT_system_cb, "arb_dist &"));
1411                GDE_load_menu(awm, AWM_ALL, "Phylogeny Distance Matrix");
1412                awm->close_sub_menu();
1413
1414                awm->insert_sub_menu("Maximum Parsimony methods", "P");
1415                GDE_load_menu(awm, AWM_ALL, "Phylogeny max. parsimony");
1416                awm->close_sub_menu();
1417
1418                awm->insert_sub_menu("Maximum Likelihood methods", "L");
1419                GDE_load_menu(awm, AWM_EXP, "Phylogeny max. Likelihood EXP");
1420                GDE_load_menu(awm, AWM_ALL, "Phylogeny max. Likelihood");
1421                awm->close_sub_menu();
1422
1423                awm->insert_sub_menu("Other methods", "O", AWM_EXP);
1424                GDE_load_menu(awm, AWM_EXP, "Phylogeny (Other)");
1425                awm->close_sub_menu();
1426            }
1427            awm->close_sub_menu();
1428        }
1429
1430        awm->insert_menu_topic(awm->local_id("consense_tree"), "Build consensus tree", "c", "consense_tree.hlp", AWM_ALL, NT_create_consense_window);
1431
1432        awm->sep______________();
1433
1434        awm->insert_sub_menu("Reset zoom",         "z");
1435        {
1436            awm->insert_menu_topic(awm->local_id("reset_logical_zoom"),  "Logical zoom",  "L", "rst_log_zoom.hlp",  AWM_ALL, makeWindowCallback(NT_reset_lzoom_cb, ntw));
1437            awm->insert_menu_topic(awm->local_id("reset_physical_zoom"), "Physical zoom", "P", "rst_phys_zoom.hlp", AWM_ALL, makeWindowCallback(NT_reset_pzoom_cb, ntw));
1438        }
1439        awm->close_sub_menu();
1440
1441        awm->sep______________();
1442
1443        // taxonomic groups
1444        NT_insert_collapse_submenu(awm, ntw);
1445        if (!clone) {
1446            awm->insert_menu_topic("group_search",     "Search groups...",    "g", "group_search.hlp",     AWM_ALL, makeWindowCallback      (popup_group_search_window,         GLOBAL.gb_main));
1447            awm->insert_menu_topic("compare_taxonomy", "Compare taxonomy...", "x", "compare_taxonomy.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_compare_taxonomy_window, ntw));
1448            awm->insert_menu_topic("move_groups",      "Move groups...",      "v", "move_groups.hlp",      AWM_ALL, makeCreateWindowCallback(NT_create_moveGroupInfo_window));
1449        }
1450
1451        awm->sep______________();
1452
1453        if (!clone) {
1454            awm->insert_menu_topic("compare_topology", "Compare topology...", "p", "compare_topo.hlp",     AWM_ALL, makeCreateWindowCallback(NT_create_compareTopologies_window));
1455        }
1456
1457        awm->insert_sub_menu("Modify branches", "M");
1458        {
1459            awm->insert_menu_topic(awm->local_id("tree_remove_remark"), "Remove bootstraps", "b", "trm_boot.hlp", AWM_ALL, makeWindowCallback(NT_remove_bootstrap, ntw));
1460            awm->insert_menu_topic(awm->local_id("tree_edit_remark"),   "Edit bootstraps",   "E", "ted_boot.hlp", AWM_ALL, makeWindowCallback(NT_edit_bootstrap, ntw));
1461            awm->sep______________();
1462            awm->insert_menu_topic(awm->local_id("tree_reset_lengths"),     "Reset branchlengths",   "R", "tbl_reset.hlp",   AWM_ALL, makeWindowCallback(NT_reset_branchlengths,   ntw));
1463            awm->insert_menu_topic(awm->local_id("justify_branch_lengths"), "Justify branchlengths", "J", "tbl_justify.hlp", AWM_ALL, makeWindowCallback(NT_justify_branch_lenghs, ntw));
1464            awm->insert_menu_topic(awm->local_id("tree_scale_lengths"),     "Scale Branchlengths",   "S", "tbl_scale.hlp",   AWM_ALL, makeWindowCallback(NT_scale_tree,            ntw));
1465            awm->sep______________();
1466            awm->insert_menu_topic(awm->local_id("tree_multifurcate"), "Multifurcate...", "M", "multifurcate.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_multifurcate_tree_window, ntw));
1467            awm->sep______________();
1468            awm->insert_menu_topic(awm->local_id("tree_boot2len"), "Bootstraps -> Branchlengths", "l", "tbl_boot2len.hlp", AWM_ALL, makeWindowCallback(NT_move_boot_branch, ntw, 0));
1469            awm->insert_menu_topic(awm->local_id("tree_len2boot"), "Bootstraps <- Branchlengths", "o", "tbl_boot2len.hlp", AWM_ALL, makeWindowCallback(NT_move_boot_branch, ntw, 1));
1470
1471        }
1472        awm->close_sub_menu();
1473        awm->insert_sub_menu("Beautify tree", "e");
1474        {
1475            awm->insert_menu_topic(awm->local_id("beautifyt_tree"),  "#beautifyt.xpm",  "",  "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_TOP));
1476            awm->insert_menu_topic(awm->local_id("beautifyc_tree"),  "#beautifyc.xpm",  "",  "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_EDGE));
1477            awm->insert_menu_topic(awm->local_id("beautifyb_tree"),  "#beautifyb.xpm",  "",  "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_BOTTOM));
1478            awm->insert_menu_topic(awm->local_id("beautifyr_tree"),  "Radial tree (1)", "1", "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_CENTER));
1479            awm->insert_menu_topic(awm->local_id("beautifyr2_tree"), "Radial tree (2)", "2", "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_ALTERNATING));
1480            awm->sep______________();
1481            awm->insert_menu_topic(awm->local_id("sort_by_other"),   "By other tree",   "o", "resortbyother.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_sort_tree_by_other_tree_window, ntw));
1482        }
1483        awm->close_sub_menu();
1484
1485        awm->insert_menu_topic(awm->local_id("branch_analysis"), "Branch analysis", "h", "branch_analysis.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_branch_analysis_window, ntw));
1486        awm->insert_menu_topic(awm->local_id("syncroots"),       "Adjust roots...", "j", "syncroots.hlp",       AWM_ALL, makeCreateWindowCallback(NT_create_syncroot_window,        GLOBAL.gb_main));
1487        awm->insert_menu_topic(awm->local_id("mark_duplicates"), "Mark duplicates", "u", "mark_duplicates.hlp", AWM_ALL, makeWindowCallback      (NT_mark_duplicates,               ntw));
1488
1489        awm->sep______________();
1490
1491        awm->insert_menu_topic(awm->local_id("shade"),            "Tree shading...",       "s", "tree_shading.hlp",     AWM_ALL, makeWindowCallback      (NT_configure_treeShader));
1492        awm->insert_menu_topic(awm->local_id("syncscroll"),       "Sync tree scrolling..", "o", "syncscroll.hlp",       AWM_ALL, makeCreateWindowCallback(NT_create_syncScroll_window, ntw));
1493
1494        awm->sep______________();
1495
1496        awm->insert_menu_topic(awm->local_id("tree_select"),        "Select Tree",      "T", NULp, AWM_ALL, makeCreateWindowCallback(NT_create_select_tree_window, awar_tree));
1497        awm->insert_menu_topic(awm->local_id("tree_select_latest"), "Select Last Tree", "L", NULp, AWM_ALL, makeWindowCallback(NT_select_bottom_tree, awar_tree));
1498
1499        if (!clone) {
1500            awm->sep______________();
1501            awm->insert_menu_topic("tree_admin", "Tree admin",               "i", "treeadm.hlp",   AWM_ALL, popup_tree_admin_window);
1502            awm->insert_menu_topic("nds",        "NDS (Node display setup)", "N", "props_nds.hlp", AWM_ALL, makeCreateWindowCallback(AWT_create_nds_window, GLOBAL.gb_main));
1503        }
1504
1505        awm->sep______________();
1506        awm->insert_menu_topic("transversion",       "Transversion analysis",   "y", "trans_anal.hlp", AWM_EXP, makeHelpCallback("trans_anal.hlp"));
1507
1508        if (!clone) {
1509            awm->sep______________();
1510            awm->insert_menu_topic("print_tree",  "Print tree",          "P", "tree2prt.hlp",  AWM_ALL, makeWindowCallback(AWT_popup_print_window, static_cast<AWT_canvas*>(ntw)));
1511            awm->insert_menu_topic("tree_2_xfig", "Export tree to XFIG", "F", "tree2file.hlp", AWM_ALL, makeWindowCallback(AWT_popup_tree_export_window, static_cast<AWT_canvas*>(ntw)));
1512        }
1513
1514        if (is_genome_db) {
1515            awm->sep______________();
1516            awm->insert_sub_menu("Other..",  "O", AWM_EXP);
1517            {
1518                awm->insert_menu_topic(awm->local_id("tree_pseudo_species_to_organism"), "Relink tree to organisms", "o", "tree_pseudo.hlp", AWM_EXP, makeWindowCallback(NT_pseudo_species_to_organism, ntw));
1519            }
1520            awm->close_sub_menu();
1521        }
1522    }
1523
1524    if (!clone) {
1525        // ---------------
1526        //      Tools
1527
1528        awm->create_menu("Tools", "o", AWM_ALL);
1529        {
1530            awm->insert_menu_topic("names_admin", "Nameserver admin (IDs)", "s", "namesadmin.hlp", AWM_ALL, makeWindowCallback(AW_popup_namesadmin_window, GLOBAL.gb_main));
1531            awm->insert_sub_menu("DB admin", "D", AWM_EXP);
1532            {
1533                awm->insert_menu_topic("db_admin", "Re-repair DB", "R", "rerepair.hlp", AWM_EXP, makeWindowCallback(NT_rerepair_DB, GLOBAL.gb_main));
1534            }
1535            awm->close_sub_menu();
1536            awm->insert_sub_menu("Network", "N", AWM_EXP);
1537            {
1538                GDE_load_menu(awm, AWM_EXP, "Network");
1539            }
1540            awm->close_sub_menu();
1541            awm->sep______________();
1542
1543            awm->insert_sub_menu("GDE specials", "G", AWM_EXP);
1544            {
1545                GDE_load_menu(awm, AWM_EXP, NULp);
1546            }
1547            awm->close_sub_menu();
1548
1549            awm->sep______________();
1550            awm->insert_menu_topic("xterm",    "Start XTERM",     "X", "xterm.hlp",   AWM_ALL, AWT_console);
1551            awm->insert_menu_topic("viewlog",  "View ARB log",    "l", "console.hlp", AWM_ALL, makeWindowCallback(AWT_system_in_console_cb, "arb_show_log.pl run",    XCMD_ASYNC_WAIT_ON_ERROR)); // ../SH/arb_show_log.pl
1552            awm->insert_menu_topic("viewserv", "View server log", "V", "console.hlp", AWM_ALL, makeWindowCallback(AWT_system_in_console_cb, "arb_show_log.pl server", XCMD_ASYNC_WAIT_ON_ERROR));
1553            awm->sep______________();
1554            GDE_load_menu(awm, AWM_EXP, "User");
1555        }
1556        // --------------------
1557        //      Properties
1558
1559        awm->create_menu("Properties", "r", AWM_ALL);
1560        {
1561            awm->insert_menu_topic("props_menu",                 "Frame settings ...",          "F", "props_frame.hlp",      AWM_ALL, AW_preset_window);
1562            awm->insert_menu_topic(awm->local_id("props_tree2"), "Tree options",                "o", "nt_tree_settings.hlp", AWM_ALL, TREE_create_settings_window);
1563            awm->insert_menu_topic("props_tree",                 "Tree colors & fonts",         "c", "color_props.hlp",      AWM_ALL, makeCreateWindowCallback(AW_create_gc_window, ntw->gc_manager));
1564            awm->insert_menu_topic("props_www",                  "Search world wide web (WWW)", "b", "props_www.hlp",        AWM_ALL, makeCreateWindowCallback(AWT_create_www_window, GLOBAL.gb_main));
1565            awm->sep______________();
1566            awm->insert_menu_topic("!toggle_expert", "Toggle expert mode",         "x", NULp, AWM_ALL, NT_toggle_expert_mode);
1567            awm->insert_menu_topic("!toggle_focus",  "Toggle focus follows mouse", "m", NULp, AWM_ALL, NT_toggle_focus_policy);
1568            awm->sep______________();
1569            AW_insert_common_property_menu_entries(awm);
1570            awm->sep______________();
1571            awm->insert_menu_topic("save_props", "Save properties (ntree.arb)", "S", "savedef.hlp", AWM_ALL, AW_save_properties);
1572        }
1573    }
1574
1575    awm->insert_help_topic("ARB_NT help",     "N", "arb_ntree.hlp", AWM_ALL, makeHelpCallback("arb_ntree.hlp"));
1576
1577    // ----------------------
1578    //      mode buttons
1579    //
1580    // keep them synchronized as far as possible with those in ARB_PARSIMONY
1581    // see ../PARSIMONY/PARS_main.cxx@keepModesSynchronized
1582
1583    awm->create_mode("mode_select.xpm", "mode_select.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SELECT));
1584    awm->create_mode("mode_mark.xpm",   "mode_mark.hlp",   AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_MARK));
1585    awm->create_mode("mode_group.xpm",  "mode_group.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_GROUP));
1586    awm->create_mode("mode_zoom.xpm",   "mode_pzoom.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_ZOOM));
1587    awm->create_mode("mode_lzoom.xpm",  "mode_lzoom.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_LZOOM));
1588
1589    awm->create_mode("mode_info.xpm", "mode_info.hlp", AWM_ALL, makeWindowCallback(NT_infomode_cb, ntw, AWT_MODE_INFO));
1590    awm->create_mode("mode_www.xpm",  "mode_www.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event,  ntw, AWT_MODE_WWW));
1591
1592    // topology-modification-modes
1593    awm->create_mode("mode_setroot.xpm",   "mode_setroot.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SETROOT));
1594    awm->create_mode("mode_swap.xpm",      "mode_swap.hlp",    AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SWAP));
1595    awm->create_mode("mode_move.xpm",      "mode_move.hlp",    AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_MOVE));
1596    awm->create_mode("mode_length.xpm",    "mode_length.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_LENGTH));
1597    awm->create_mode("mode_multifurc.xpm", "mode_length.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_MULTIFURC));
1598
1599    // layout-modes
1600    awm->create_mode("mode_line.xpm",   "mode_width.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_LINE));
1601    awm->create_mode("mode_rotate.xpm", "mode_rotate.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_ROTATE));
1602    awm->create_mode("mode_spread.xpm", "mode_spread.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SPREAD));
1603
1604    awm->set_info_area_height(250);
1605    awm->at(5, 2);
1606    awm->auto_space(-2, -2);
1607    awm->shadow_width(1);
1608
1609    // -------------------------
1610    //      create top area
1611
1612    int first_liney;
1613    int leftx;
1614    awm->get_at_position(&leftx, &first_liney);
1615
1616    // ---------------------
1617    //      quit + help
1618
1619    awm->button_length(0);
1620
1621    if (clone) {
1622        awm->callback(AW_POPDOWN);
1623        awm->create_button("CLOSE", "#close.xpm");
1624    }
1625    else {
1626        awm->callback(makeWindowCallback(NT_exit, EXIT_SUCCESS));
1627        awm->help_text("quit.hlp");
1628        awm->create_button("QUIT", "#quit.xpm");
1629    }
1630
1631    int db_pathx = awm->get_at_xposition();
1632
1633    // now fetch the yposition for the 2nd button line
1634    awm->at_newline();
1635    int second_liney = awm->get_at_yposition();
1636
1637    awm->callback(AW_help_entry_pressed);
1638    awm->help_text("arb_ntree.hlp");
1639    awm->create_button("?", "#help.xpm");
1640
1641    // --------------------------
1642    //      save + undo/redo
1643
1644    awm->callback(NT_save_quick_cb);
1645    awm->help_text("save.hlp");
1646    awm->create_button("SAVE", "#save.xpm");
1647
1648    awm->callback(makeCreateWindowCallback(NT_create_save_as, AWAR_DBBASE));
1649    awm->help_text("save.hlp");
1650    awm->create_button("SAVE_AS", "#saveAs.xpm");
1651
1652    // undo/redo:
1653    awm->callback(makeWindowCallback(NT_undo_cb, GB_UNDO_UNDO, ntw));
1654    awm->help_text("undo.hlp");
1655    awm->create_button("UNDO", "#undo.xpm");
1656
1657    awm->callback(makeWindowCallback(NT_undo_cb, GB_UNDO_REDO, ntw));
1658    awm->help_text("undo.hlp");
1659    awm->create_button("REDO", "#redo.xpm");
1660
1661    int db_pathx2 = awm->get_at_xposition();
1662
1663    // fetch position for mode help-line:
1664    awm->at_newline();
1665    int third_liney = awm->get_at_yposition();
1666
1667    awm->at(db_pathx, first_liney);
1668    // size of DB-name button is determined by buttons below:
1669    awm->at_attach_to(false, false, db_pathx2-db_pathx-1, second_liney-first_liney+1);
1670    awm->callback(makeCreateWindowCallback(NT_create_save_quick_as_window, AWAR_DBBASE));
1671    awm->help_text("save.hlp");
1672    awm->create_button("QUICK_SAVE_AS", AWAR_DB_NAME);
1673
1674    // -----------------------------
1675    //      tree + tree display
1676
1677#define TREE_BUTTON_OVERSIZE 6
1678
1679    int db_treex      = awm->get_at_xposition();
1680    int second_uppery = second_liney-TREE_BUTTON_OVERSIZE;
1681
1682    awm->at(db_treex, second_uppery);
1683    awm->button_length(0);
1684
1685    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_TREE_RADIAL));
1686    awm->help_text("tr_type_radial.hlp");
1687    awm->create_button("RADIAL_TREE_TYPE", "#radial.xpm");
1688
1689    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_TREE_NORMAL));
1690    awm->help_text("tr_type_list.hlp");
1691    awm->create_button("LIST_TREE_TYPE", "#dendro.xpm");
1692
1693    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_TREE_IRS));
1694    awm->help_text("tr_type_irs.hlp");
1695    awm->create_button("FOLDED_LIST_TREE_TYPE", "#dendroIrs.xpm");
1696
1697    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_LIST_NDS));
1698    awm->help_text("tr_type_nds.hlp");
1699    awm->create_button("NO_TREE_TYPE", "#listdisp.xpm");
1700
1701    int db_treex2 = awm->get_at_xposition();
1702
1703    awm->at(db_treex, first_liney);
1704    // size of tree-name button is determined by buttons below:
1705    awm->at_attach_to(false, false, db_treex2-db_treex-1, second_uppery-first_liney+1);
1706    awm->callback(makeCreateWindowCallback(NT_create_select_tree_window, awar_tree));
1707    awm->help_text("nt_tree_select.hlp");
1708    awm->create_button("SELECT_A_TREE", awar_tree);
1709
1710    // ---------------------------------------------------------------
1711    //      protection, alignment + editor (and maybe Genome Map)
1712
1713    int db_alignx = awm->get_at_xposition();
1714
1715    // editor and genemap buttons have to be 44x24 sized
1716#define EDIT_XSIZE 50
1717#define EDIT_YSIZE 30 // same as 'save as' buttons
1718
1719    // first draw protection:
1720    int protectx = db_alignx + 2*EDIT_XSIZE;
1721
1722    awm->at(protectx+2, first_liney+1);
1723    awm->button_length(0);
1724    awm->create_button(NULp, "#protect.xpm");
1725
1726    awm->at(protectx, second_liney+2);
1727    awm->create_option_menu(AWAR_SECURITY_LEVEL, true);
1728    awm->insert_option        ("0", NULp, 0);
1729    awm->insert_option        ("1", NULp, 1);
1730    awm->insert_option        ("2", NULp, 2);
1731    awm->insert_option        ("3", NULp, 3);
1732    awm->insert_option        ("4", NULp, 4);
1733    awm->insert_option        ("5", NULp, 5);
1734    awm->insert_default_option("6", NULp, 6);
1735    awm->update_option_menu();
1736
1737    int db_searchx = awm->get_at_xposition() - 7;
1738
1739    // draw ali/editor buttons AFTER protect menu (to get rid of it's label)
1740    awm->at(db_alignx, second_liney);
1741
1742    awm->at_attach_to(false, false, ((2-is_genome_db)*EDIT_XSIZE), EDIT_YSIZE);
1743    awm->callback(makeWindowCallback(NT_start_editor_on_tree, 0, ntw));
1744    awm->help_text("arb_edit4.hlp");
1745    if (is_genome_db) awm->create_button("EDIT_SEQUENCES", "#editor_small.xpm");
1746    else              awm->create_button("EDIT_SEQUENCES", "#editor.xpm");
1747
1748    if (is_genome_db) {
1749        awm->at_attach_to(false, false, EDIT_XSIZE, EDIT_YSIZE);
1750        awm->callback(makeCreateWindowCallback(GEN_create_first_map, GLOBAL.gb_main)); // initial gene map
1751        awm->help_text("gene_map.hlp");
1752        awm->create_button("OPEN_GENE_MAP", "#gen_map.xpm");
1753    }
1754
1755    int db_alignx2 = awm->get_at_xposition();
1756
1757    awm->at(db_alignx, first_liney);
1758    awm->at_attach_to(false, false, db_alignx2-db_alignx-1, second_liney-first_liney+1);
1759    awm->callback(NT_create_select_alignment_window);
1760    awm->help_text("nt_align_select.hlp");
1761    awm->create_button("SELECT_AN_ALIGNMENT", AWAR_DEFAULT_ALIGNMENT);
1762
1763    // -------------------------------
1764    //      create mode-help line
1765
1766    awm->at(leftx, third_liney);
1767    awm->button_length(AWAR_FOOTER_MAX_LEN);
1768    awm->create_button(NULp, AWAR_FOOTER);
1769
1770    awm->at_newline();
1771    int bottomy = awm->get_at_yposition();
1772
1773    // ---------------------------------------
1774    //      Info / marked / Search / Jump
1775
1776    awm->button_length(7);
1777
1778    awm->at(db_searchx, first_liney);
1779    awm->callback(makeCreateWindowCallback(DBUI::create_species_query_window, GLOBAL.gb_main));
1780    awm->help_text("sp_search.hlp");
1781    awm->create_button("SEARCH",  "Search");
1782
1783    awm->at(db_searchx, second_uppery);
1784    awm->callback(makeWindowCallback(NT_jump_cb, ntw, AP_JUMP_BY_BUTTON));
1785    awm->help_text("tr_jump.hlp");
1786    awm->create_button("JUMP", "Jump");
1787
1788    int db_infox = awm->get_at_xposition();
1789
1790    awm->at(db_infox, first_liney);
1791    awm->button_length(13);
1792    awm->callback(popupinfo_wcb);
1793    awm->help_text("sp_search.hlp");
1794    awm->create_button("INFO",  AWAR_INFO_BUTTON_TEXT);
1795
1796    awm->at(db_infox, second_uppery);
1797    awm->button_length(13);
1798    awm->help_text("species_configs.hlp");
1799    awm->callback(makeWindowCallback(NT_popup_configuration_admin, ntw));
1800    awm->create_button("selection_admin2", AWAR_MARKED_SPECIES_COUNTER);
1801    {
1802        GBDATA *gb_species_data = GBT_get_species_data(GLOBAL.gb_main);
1803        GB_add_callback(gb_species_data, GB_CB_CHANGED, makeDatabaseCallback(NT_update_marked_counter, static_cast<AW_window*>(awm)));
1804        NT_update_marked_counter(NULp, awm);
1805    }
1806
1807    // set height of top area:
1808    awm->set_info_area_height(bottomy+2);
1809    awm->set_bottom_area_height(0);
1810
1811    NT_activate_configMarkers_display(ntw);
1812
1813    // ------------------------------------
1814    //      Autostarts for development
1815
1816#if defined(DEVEL_RALF)
1817    // if (is_genome_db) GEN_map_first(awr)->show();
1818#endif // DEVEL_RALF
1819
1820    GB_pop_transaction(GLOBAL.gb_main);
1821
1822#if defined(DEBUG)
1823    AWT_check_action_ids(awr, is_genome_db ? "_genome" : "");
1824#endif
1825
1826    return awm;
1827}
1828
1829TREE_canvas *NT_create_main_window(AW_root *aw_root) {
1830    GB_ERROR error = GB_request_undo_type(GLOBAL.gb_main, GB_UNDO_NONE);
1831    if (error) aw_message(error);
1832
1833    nt_create_all_awars(aw_root);
1834
1835    TREE_canvas *ntw = NULp;
1836    AW_window   *aww = popup_new_main_window(aw_root, 0, &ntw);
1837    NT_install_treeShader(ntw, GLOBAL.gb_main);
1838    aww->show();
1839
1840    error = GB_request_undo_type(GLOBAL.gb_main, GB_UNDO_UNDO);
1841    if (error) aw_message(error);
1842
1843    return ntw;
1844}
Note: See TracBrowser for help on using the repository browser.