source: trunk/EDIT4/ED4_root.cxx

Last change on this file was 19407, checked in by westram, 17 months ago
  • reintegrates 'ali' into 'trunk'
    • use bond settings from EDIT4 in SECEDIT
    • fix refresh logic
    • refactor underlying code
  • adds: log:branches/ali@19393:19406
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 81.8 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ED4_root.cxx                                      //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "ed4_class.hxx"
12#include "ed4_awars.hxx"
13#include "ed4_tools.hxx"
14#include "ed4_block.hxx"
15#include "ed4_dots.hxx"
16#include "ed4_detect_bad_ali.hxx"
17#include "ed4_nds.hxx"
18#include "ed4_list.hxx"
19#include "ed4_plugins.hxx"
20#include "ed4_visualizeSAI.hxx"
21#include "ed4_naligner.hxx"
22#include "ed4_ProteinViewer.hxx"
23#include "ed4_protein_2nd_structure.hxx"
24#include "graph_aligner_gui.hxx"
25#include "ed4_colStat.hxx"
26#include "ed4_seq_colors.hxx"
27#include "ed4_flags.hxx"
28
29#include <ed4_extern.hxx>
30#include <fast_aligner.hxx>
31
32#include <AW_helix.hxx>
33#include <gde.hxx>
34#include <awt.hxx>
35#include <awt_map_key.hxx>
36
37#include <aw_awars.hxx>
38#include <aw_preset.hxx>
39#include <aw_msg.hxx>
40#include <arb_progress.h>
41#include <aw_root.hxx>
42#include <aw_question.hxx>
43#include <aw_advice.hxx>
44#include <rootAsWin.h>
45#include "../WINDOW/aw_status.hxx" // @@@ hack - obsolete when EDIT4 status works like elsewhere
46
47#include <arb_version.h>
48#include <arb_file.h>
49#include <arb_defs.h>
50
51#include <arbdbt.h>
52#include <ad_cb.h>
53#include <macros.hxx>
54#include <st_window.hxx>
55
56#include <cctype>
57#include <map>
58
59ED4_WinContext ED4_WinContext::current_context;
60
61void ED4_folding_line::warn_illegal_dimension() {
62#if defined(DEBUG)
63    if (dimension<0.0) {
64        // e4_assert(0); // crashes gdb when called from scrollbar callback - so instead only dump backtrace
65        const char *msg = GBS_global_string("illegal dimension %f\n", dimension);
66        GBK_dump_backtrace(stderr, msg);
67    }
68#endif
69}
70
71void ED4_WinContext::warn_missing_context() const {
72    e4_assert(0);
73    GBK_dump_backtrace(stderr, "Missing context");
74    aw_message("Missing context - please send information from console to devel@arb-home.de");
75}
76
77static ARB_ERROR request_terminal_refresh(ED4_base *base, ED4_level lev) {
78    if (lev == LEV_NONE || (base->spec.level&lev) != 0) {
79        if (base->is_terminal()) base->request_refresh();
80    }
81    return NULp;
82}
83
84void ED4_root::request_refresh_for_all_terminals() {
85    main_manager->route_down_hierarchy(makeED4_route_cb(request_terminal_refresh, LEV_NONE)).expect_no_error();
86}
87
88void ED4_root::request_refresh_for_specific_terminals(ED4_level lev) {
89    main_manager->route_down_hierarchy(makeED4_route_cb(request_terminal_refresh, lev)).expect_no_error();
90}
91
92
93static ARB_ERROR request_sequence_refresh(ED4_base *base, bool consensi) {
94    ARB_ERROR error;
95    if (base->spec.level & LEV_SPECIES) {
96        if (base->is_consensus_manager() == consensi) {
97            error = base->to_manager()->route_down_hierarchy(makeED4_route_cb(request_terminal_refresh, LEV_SEQUENCE_STRING));
98        }
99    }
100    return error;
101}
102
103// if you want to refresh consensi AND sequences you may use request_refresh_for_specific_terminals(LEV_SEQUENCE_STRING)
104void ED4_root::request_refresh_for_consensus_terminals() {
105    main_manager->route_down_hierarchy(makeED4_route_cb(request_sequence_refresh, true)).expect_no_error();
106}
107void ED4_root::request_refresh_for_sequence_terminals() {
108    if (main_manager) {
109        main_manager->route_down_hierarchy(makeED4_route_cb(request_sequence_refresh, false)).expect_no_error();
110    }
111}
112
113void ED4_root::refresh_window_simple(bool redraw) {
114    // if 'redraw' -> update everything (ignoring refresh flag)
115    bool refresh_all = false;
116    if (redraw) {
117#if defined(TRACE_REFRESH)
118        fprintf(stderr, "- clear display (refresh_window_simple(redraw=true) called)\n"); fflush(stderr);
119#endif
120        main_manager->update_info.set_clear_at_refresh(1);
121        refresh_all = true;
122    }
123
124    main_manager->Show(refresh_all, false);
125    if (redraw) main_manager->update_info.set_clear_at_refresh(0);
126}
127
128void ED4_root::handle_update_requests(bool& redraw) {
129    if (main_manager->update_info.delete_requested) {
130#if defined(TRACE_REFRESH)
131        fprintf(stderr, "- handling requested deletes\n"); fflush(stderr);
132#endif
133        main_manager->delete_requested_children();
134        redraw = true;
135    }
136
137    if (main_manager->update_info.update_requested) {
138#if defined(TRACE_REFRESH)
139        fprintf(stderr, "- handling requested updates\n"); fflush(stderr);
140#endif
141        main_manager->update_requested_children();
142        redraw = true; // @@@ needed ?
143    }
144
145    while (main_manager->update_info.resize) {
146#if defined(TRACE_REFRESH)
147        fprintf(stderr, "- handling requested resizes\n"); fflush(stderr);
148#endif
149        main_manager->resize_requested_children();
150        redraw = true;
151    }
152
153    // make sure all update request have been handled:
154    e4_assert(!main_manager->update_info.delete_requested);
155    e4_assert(!main_manager->update_info.update_requested);
156    e4_assert(!main_manager->update_info.resize);
157}
158
159void ED4_root::special_window_refresh(bool handle_updates) {
160    // this function should only be used for window specific updates (e.g. cursor placement/deletion)
161    e4_assert(ED4_WinContext::have_context());
162
163    bool redraw = true;
164    if (handle_updates) handle_update_requests(redraw);
165    refresh_window_simple(redraw);
166    // do NOT clear_refresh_requests here!! this is no full refresh!
167}
168
169ED4_returncode ED4_root::refresh_all_windows(bool redraw) {
170    // if 'redraw' -> update everything (ignoring refresh flag)
171    GB_transaction ta(gb_main);
172
173    handle_update_requests(redraw);
174
175    ED4_window *window = first_window;
176    while (window) {
177        ED4_LocalWinContext uses(window);
178        refresh_window_simple(redraw);
179        window = window->next;
180    }
181
182    if (main_manager->update_info.refresh) main_manager->clear_refresh();
183
184    if (loadable_SAIs == LSAI_OUTDATED) {
185        GB_touch(GBT_get_SAI_data(gb_main)); // touch SAI data to force update of SAI selection list
186        loadable_SAIs = LSAI_UPTODATE;
187    }
188
189    return ED4_R_OK;
190}
191
192// --------------------------------------------------------------------------------
193
194#ifdef UNIT_TESTS
195#ifndef TEST_UNIT_H
196#include <test_unit.h>
197#endif
198
199static arb_test::match_expectation correct_win2world_calculation(ED4_foldable& foldable, int xwin_org, int ywin_org, int xwrld_expd, int ywrld_expd) {
200    using namespace arb_test;
201    match_expectation precondition(all().of(that(xwrld_expd).is_more_or_equal(xwin_org),
202                                            that(ywrld_expd).is_more_or_equal(ywin_org)));
203
204    AW_pos xwrld_calc = xwin_org;
205    AW_pos ywrld_calc = ywin_org;
206    foldable.win_to_world_coords(&xwrld_calc, &ywrld_calc);
207
208    match_expectation win_2_world_conversion(all().of(that(xwrld_calc).is_equal_to(xwrld_expd),
209                                                      that(ywrld_calc).is_equal_to(ywrld_expd)));
210
211    AW_pos xwin_back = xwrld_calc;
212    AW_pos ywin_back = ywrld_calc;
213    foldable.world_to_win_coords(&xwin_back, &ywin_back);
214
215    match_expectation world_back2_win_conversion(all().of(that(xwin_back).is_equal_to(xwin_org),
216                                                          that(ywin_back).is_equal_to(ywin_org)));
217
218    return all().of(precondition, win_2_world_conversion, world_back2_win_conversion);
219}
220
221static arb_test::match_expectation correct_world2win_calculation(ED4_foldable& foldable, int xwrld_org, int ywrld_org, int xwin_expd, int ywin_expd) {
222    using namespace arb_test;
223    match_expectation precondition(all().of(that(xwrld_org).is_more_or_equal(xwin_expd),
224                                            that(ywrld_org).is_more_or_equal(ywin_expd)));
225
226
227    AW_pos xwin_calc = xwrld_org;
228    AW_pos ywin_calc = ywrld_org;
229    foldable.world_to_win_coords(&xwin_calc, &ywin_calc);
230
231    match_expectation world_2_win_conversion(all().of(that(xwin_calc).is_equal_to(xwin_expd),
232                                                      that(ywin_calc).is_equal_to(ywin_expd)));
233
234    return all().of(precondition, world_2_win_conversion);
235}
236
237#define TEST_EXPECT_WIN_UNFOLDED(xwi,ywi)              TEST_EXPECTATION(correct_win2world_calculation(foldable, xwi, ywi, xwi, ywi))
238#define TEST_EXPECT_WIN_WORLD_FOLDING(xwi,ywi,fx,fy)   TEST_EXPECTATION(correct_win2world_calculation(foldable, xwi, ywi, (xwi)+(fx), (ywi)+(fy)))
239#define TEST_EXPECT_WORLD_WIN_FOLDING(xwo,ywo,xwi,ywi) TEST_EXPECTATION(correct_world2win_calculation(foldable, xwo, ywo, xwi, ywi))
240
241#define TEST_EXPECT_WIN_WORLD_FOLDING__BROKEN(xwi,ywi,fx,fy)        TEST_EXPECTATION__BROKEN(correct_win2world_calculation(foldable, xwi, ywi, (xwi)+(fx), (ywi)+(fy)))
242#define TEST_EXPECT_WIN_WORLD_FOLDING__BROKENIF(when,xwi,ywi,fx,fy) TEST_EXPECTATION__BROKENIF(when, correct_win2world_calculation(foldable, xwi, ywi, (xwi)+(fx), (ywi)+(fy)))
243
244void TEST_win_2_world() {
245    ED4_foldable foldable;
246
247    const int X1 = 200;
248    const int X2 = 300;
249    const int Y1 = 100;
250    const int Y2 = 200;
251
252    ED4_folding_line *hor100 = foldable.insert_folding_line(Y1, 0, PROP_HORIZONTAL);
253    ED4_folding_line *ver200 = foldable.insert_folding_line(X1, 0, PROP_VERTICAL);
254    ED4_folding_line *hor200 = foldable.insert_folding_line(Y2, 0, PROP_HORIZONTAL);
255    ED4_folding_line *ver300 = foldable.insert_folding_line(X2, 0, PROP_VERTICAL);
256
257    // nothing folded yet
258
259    const int x01 = X1/2;
260    const int x12 = (X1+X2)/2;
261    const int x23 = X2+x01;
262
263    const int y01 = Y1/2;
264    const int y12 = (Y1+Y2)/2;
265    const int y23 = Y2+y01;
266
267    TEST_EXPECT_WIN_UNFOLDED(x01, y01);
268    TEST_EXPECT_WIN_UNFOLDED(x12, y01);
269    TEST_EXPECT_WIN_UNFOLDED(x23, y01);
270
271    TEST_EXPECT_WIN_UNFOLDED(x01, y12);
272    TEST_EXPECT_WIN_UNFOLDED(x12, y12);
273    TEST_EXPECT_WIN_UNFOLDED(x23, y12);
274
275    TEST_EXPECT_WIN_UNFOLDED(x01, y23);
276    TEST_EXPECT_WIN_UNFOLDED(x12, y23);
277    TEST_EXPECT_WIN_UNFOLDED(x23, y23);
278
279    for (int FACTOR = 1; FACTOR <= 100; FACTOR += 7) {
280        TEST_ANNOTATE(GBS_global_string("FACTOR=%i", FACTOR));
281        int H1 = FACTOR* 10;
282        int H2 = FACTOR* 40;
283        int V1 = FACTOR* 20;
284        int V2 = FACTOR* 80;
285
286        hor100->set_dimension(H1);
287        hor200->set_dimension(H2);
288        ver200->set_dimension(V1);
289        ver300->set_dimension(V2);
290
291        TEST_EXPECT_WIN_UNFOLDED     (x01, y01); // always in unfolded range
292        TEST_EXPECT_WIN_WORLD_FOLDING(x12, y01, V1,    0);
293        TEST_EXPECT_WIN_WORLD_FOLDING(x23, y01, V1+V2, 0);
294
295        TEST_EXPECT_WIN_WORLD_FOLDING(x01, y12, 0,     H1);
296        TEST_EXPECT_WIN_WORLD_FOLDING(x12, y12, V1,    H1);
297        TEST_EXPECT_WIN_WORLD_FOLDING(x23, y12, V1+V2, H1);
298
299        TEST_EXPECT_WIN_WORLD_FOLDING(x01, y23, 0,     H1+H2);
300        TEST_EXPECT_WIN_WORLD_FOLDING(x12, y23, V1,    H1+H2);
301        TEST_EXPECT_WIN_WORLD_FOLDING(x23, y23, V1+V2, H1+H2);
302
303        // test "folded" world positions.
304        // they result in win positions lower than folding line!
305        TEST_EXPECT_WORLD_WIN_FOLDING(X1-1,    Y1-1,    X1-1,    Y1-1);    // left of/above folded range
306        TEST_EXPECT_WORLD_WIN_FOLDING(X1,      Y1,      X1-V1,   Y1-H1);   // left/upper end of folded range
307        TEST_EXPECT_WORLD_WIN_FOLDING(X1+5,    Y1+5,    X1+5-V1, Y1+5-H1); // in folded range
308        TEST_EXPECT_WORLD_WIN_FOLDING(X1+V1,   Y1+H1,   X1,      Y1);      // right/lower end of folded range
309        TEST_EXPECT_WORLD_WIN_FOLDING(X1+V1+1, Y1+H1+1, X1+1,    Y1+1);    // right of/below folded range
310    }
311}
312
313#endif // UNIT_TESTS
314
315// --------------------------------------------------------------------------------
316
317ED4_returncode ED4_root::deselect_all() {
318    ED4_multi_species_manager *main_multi_man = middle_area_man->get_multi_species_manager();
319    main_multi_man->deselect_all_species_and_SAI();
320
321    main_multi_man = top_area_man->get_multi_species_manager();
322    main_multi_man->deselect_all_species_and_SAI();
323
324    ED4_setBlocktype(ED4_BT_NOBLOCK);
325
326    return ED4_R_OK;
327}
328
329void ED4_root::remove_from_highlighted(ED4_species_name_terminal *name_term) { // @@@ change param to ED4_species_manager?
330    if (name_term) {
331        if ((highlighted_objects->has_elem(name_term->highlight_info))) {
332            highlighted_objects->remove_elem(name_term->highlight_info);
333
334            delete name_term->highlight_info;
335            name_term->highlight_info = NULp;
336            name_term->containing_species_manager()->set_highlighted(false);
337            name_term->dragged = false; // @@@ caller shall do this
338
339#ifdef DEBUG
340            GBDATA *gbd = name_term->get_species_pointer();
341
342            if (gbd) {
343                GB_transaction ta(gbd);
344                printf("removed term '%s'\n", GB_read_char_pntr(gbd));
345            }
346            else {
347                ED4_species_manager *spec_man = name_term->get_parent(LEV_SPECIES)->to_species_manager();
348
349                if (spec_man->is_consensus_manager()) {
350                    printf("removed consensus '%s'\n", name_term->id);
351                }
352                else {
353                    printf("removed unknown term '%s'\n", name_term->id ? name_term->id : "NULp");
354                }
355            }
356#endif
357
358            name_term->request_refresh();
359            ED4_sequence_terminal *seq_term = name_term->corresponding_sequence_terminal();
360            if (seq_term) seq_term->request_refresh();
361
362            // ProtView: Refresh corresponding orf terminals
363            if (alignment_type == GB_AT_DNA) {
364                PV_CallBackFunction(this->aw_root);
365            }
366
367            ED4_multi_species_manager *multi_man = name_term->get_parent(LEV_MULTI_SPECIES)->to_multi_species_manager();
368            multi_man->invalidate_species_counters();
369        }
370    }
371}
372
373void ED4_root::announce_useraction_in(AW_window *aww) {
374    for (ED4_window *win = first_window; win; win = win->next) {
375        if (win->aww == aww) {
376            most_recently_used_window = win;
377        }
378    }
379}
380
381ED4_returncode ED4_root::add_to_highlighted(ED4_species_name_terminal *name_term) { // @@@ change param to ED4_species_manager?
382    if (!name_term || !name_term->has_property(PROP_SELECTABLE)) {   // check if object exists and may be selected
383        return ED4_R_IMPOSSIBLE;
384    }
385
386    if (!(highlighted_objects->has_elem(name_term->highlight_info))) {  // object is really new to our list => append it
387        ED4_highlighted_entry *hl_info = new ED4_highlighted_entry;
388        name_term->highlight_info       = hl_info;
389
390        if (name_term->has_property(PROP_IS_HANDLE)) { // object is a handle for an object up in the hierarchy => search it
391            ED4_level  mlevel     = name_term->spec.handled_level;
392            ED4_base  *tmp_object = name_term;
393
394            while (tmp_object && !(tmp_object->spec.level & mlevel)) {
395                tmp_object = tmp_object->parent;
396            }
397
398            if (!tmp_object) return ED4_R_WARNING; // no target level found
399            // ok, found handled object -> use handle ('name_term')
400        }
401        // otherwise selected object is no handle => take it directly
402
403        hl_info->object = name_term;
404        highlighted_objects->prepend_elem(hl_info);
405        name_term->containing_species_manager()->set_highlighted(true);
406
407#ifdef DEBUG
408        GBDATA *gbd = name_term->get_species_pointer();
409
410        if (gbd) {
411            printf("added term '%s'\n", GB_read_char_pntr(gbd));
412        }
413        else {
414            ED4_species_manager *spec_man = name_term->get_parent(LEV_SPECIES)->to_species_manager();
415            if (spec_man->is_consensus_manager()) {
416                printf("added consensus '%s'\n", name_term->id);
417            }
418            else {
419                printf("added unknown term '%s'\n", name_term->id ? name_term->id : "NULp");
420            }
421        }
422#endif
423
424        name_term->request_refresh();
425        ED4_sequence_terminal *seq_term = name_term->corresponding_sequence_terminal();
426        if (seq_term) seq_term->request_refresh();
427
428        // ProtView: Refresh corresponding orf terminals
429        if (alignment_type == GB_AT_DNA) {
430            PV_CallBackFunction(this->aw_root);
431        }
432
433        ED4_multi_species_manager *multi_man = name_term->get_parent(LEV_MULTI_SPECIES)->to_multi_species_manager();
434        multi_man->invalidate_species_counters();
435
436        return ED4_R_OK;
437    }
438
439    return ED4_R_IMPOSSIBLE;
440}
441
442void ED4_root::resize_all_requesting_childs() {
443    while (main_manager->update_info.resize) {
444        main_manager->resize_requested_children();
445    }
446}
447
448static ARB_ERROR change_char_table_length(ED4_base *base, int new_length) {
449    if (base->is_abstract_group_manager()) {
450        ED4_abstract_group_manager *group_man = base->to_abstract_group_manager();
451        group_man->table().change_table_length(new_length);
452    }
453    return NULp;
454}
455
456void ED4_alignment_length_changed(GBDATA *gb_alignment_len, GB_CB_TYPE IF_ASSERTION_USED(gbtype)) { // callback from database
457    e4_assert(gbtype==GB_CB_CHANGED);
458    int new_length = GB_read_int(gb_alignment_len);
459
460#if defined(DEBUG) && 1
461    printf("alignment_length_changed from %i to %i\n", MAXSEQUENCECHARACTERLENGTH, new_length);
462#endif
463
464    if (MAXSEQUENCECHARACTERLENGTH!=new_length) { // otherwise we already did this (i.e. we were called by changed_by_database)
465        bool was_increased = new_length>MAXSEQUENCECHARACTERLENGTH;
466
467        MAXSEQUENCECHARACTERLENGTH = new_length;
468
469        GBDATA *gb_main = ED4_ROOT->get_gb_main();
470        {
471            const char *err = ED4_ROOT->helix->init(gb_main); // reload helix
472            aw_message_if(err);
473        }
474        {
475            const char *err = ED4_ROOT->ecoli_ref->init(gb_main); // reload ecoli
476            aw_message_if(err);
477        }
478
479        if (ED4_ROOT->alignment_type == GB_AT_AA) {
480            // TODO: is this needed here?
481            const char *err = ED4_pfold_set_SAI(&ED4_ROOT->protstruct, gb_main, ED4_ROOT->get_alignment_name(), &ED4_ROOT->protstruct_len); // reload protstruct
482            aw_message_if(err);
483        }
484
485        if (was_increased) {
486            ED4_ROOT->main_manager->route_down_hierarchy(makeED4_route_cb(change_char_table_length, new_length)).expect_no_error();
487            ED4_ROOT->root_group_man->remap()->mark_compile_needed_force();
488        }
489    }
490}
491
492ARB_ERROR ED4_root::init_alignment() {
493    GB_transaction ta(gb_main);
494
495    alignment_name = GBT_get_startup_alignment(gb_main);
496    alignment_type = GBT_get_alignment_type(gb_main, alignment_name);
497    if (alignment_type==GB_AT_UNKNOWN) {
498        return GBS_global_string("You have to select a valid alignment before you can start ARB_EDIT4\n(%s)", GB_await_error());
499    }
500
501    GBDATA *gb_alignment = GBT_get_alignment(gb_main, alignment_name);
502    if (!gb_alignment) {
503        return GBS_global_string("You can't edit without an existing alignment\n(%s)", GB_await_error());
504    }
505
506    GBDATA *gb_alignment_len = GB_search(gb_alignment, "alignment_len", GB_FIND);
507    int alignment_length = GB_read_int(gb_alignment_len);
508    MAXSEQUENCECHARACTERLENGTH = alignment_length;
509
510    GB_add_callback(gb_alignment_len, GB_CB_CHANGED, makeDatabaseCallback(ED4_alignment_length_changed));
511
512    return NULp;
513}
514
515void ED4_root::recalc_font_group() {
516    int font_GC[] = {
517        ED4_G_SEQUENCES,
518        ED4_G_STANDARD,
519        ED4_G_FLAG_INFO,
520    };
521
522    font_group.unregisterAll();
523    for (unsigned i = 0; i<ARRAY_ELEMS(font_GC); ++i) {
524        ED4_MostRecentWinContext context;
525        font_group.registerFont(current_device(), font_GC[i]);
526    }
527}
528
529static ARB_ERROR force_group_update(ED4_base *base) {
530    if (base->is_multi_species_manager()) {
531        base->to_multi_species_manager()->update_requested_by_child();
532    }
533    return NULp;
534}
535
536ED4_returncode ED4_root::create_hierarchy(const char *area_string_middle, const char *area_string_top) {
537    // creates internal hierarchy of editor
538
539    long total_no_of_groups  = 0;
540    long total_no_of_species = 0;
541    {
542        // count species and related info (e.g. helix) displayed in the top region (a == 0)
543        // count no of species and sais including groups in middle region (a == 1)
544
545        const char *area_string[2] = { area_string_top, area_string_middle };
546        for (int a = 0; a<2; ++a) {
547            long group_count;
548            long species_count;
549
550            EDB_root_bact::calc_no_of_all(area_string[a], &group_count, &species_count);
551
552            total_no_of_groups  += group_count;
553            total_no_of_species += species_count;
554        }
555    }
556
557    SmartPtr<arb_progress> startup_progress = new arb_progress("EDIT4 startup");
558
559    GB_push_transaction(gb_main);
560
561    ecoli_ref = new BI_ecoli_ref;
562    ecoli_ref->init(gb_main);
563
564    // [former position of ali-init-code]
565
566    main_manager   = new ED4_main_manager("Main_Manager", 0, 0, NULp); // build a test hierarchy
567    root_group_man = new ED4_root_group_manager("Root_Group_Manager", 0, 0, main_manager);
568
569    main_manager->append_member(root_group_man);
570
571    ED4_device_manager *device_manager = new ED4_device_manager("Device_Manager", 0, 0, root_group_man);
572    root_group_man->append_member(device_manager);
573
574    {
575        int col_stat_term_height = 50; // @@@ Hoehe des ColumnStatistics Terminals ausrechnen
576
577        ref_terminals.init(
578            new ED4_sequence_info_terminal("Reference_Sequence_Info_Terminal",         MAXINFO_WIDTH, TERMINAL_HEIGHT,       NULp),
579            new ED4_sequence_terminal     ("Reference_Sequence_Terminal",              300,           TERMINAL_HEIGHT,       NULp, false),
580            new ED4_sequence_info_terminal("Reference_ColumnStatistics_Info_Terminal", MAXINFO_WIDTH, col_stat_term_height, NULp),
581            new ED4_columnStat_terminal   ("Reference_ColumnStatistics_Terminal",      300,           col_stat_term_height, NULp)
582            );
583    }
584
585    {
586        arb_progress species_progress("Loading species", total_no_of_species);
587
588        // ********** Top Area beginning **********
589
590        ED4_multi_species_manager *top_multi_species_manager;
591        ED4_spacer_terminal       *top_spacer_terminal;
592        ED4_spacer_terminal       *top_mid_spacer_terminal;
593        ED4_spacer_terminal       *top_multi_spacer_terminal_beg;
594        ED4_line_terminal         *top_mid_line_terminal;
595        {
596            ED4_area_manager *top_area_manager = new ED4_area_manager("Top_Area_Manager", 0, 0, device_manager);
597            device_manager->append_member(top_area_manager);
598            top_area_man = top_area_manager;
599
600            top_spacer_terminal = new ED4_spacer_terminal("Top_Spacer", false, 100, 10, top_area_manager);
601            top_area_manager->append_member(top_spacer_terminal);
602
603            top_multi_species_manager = new ED4_multi_species_manager("Top_MultiSpecies_Manager", 0, 0, top_area_manager);
604            top_area_manager->append_member(top_multi_species_manager);
605
606            top_multi_spacer_terminal_beg = new ED4_spacer_terminal("Top_Left_Spacer", false, 0, 3, top_multi_species_manager);
607            top_multi_species_manager->append_member(top_multi_spacer_terminal_beg);
608
609            reference = new ED4_reference;
610
611            int index = 0;
612            EDB_root_bact::scan_string(top_multi_species_manager, ref_terminals, area_string_top, &index, species_progress);
613            GB_pop_transaction(gb_main);
614
615            const int TOP_MID_LINE_HEIGHT   = 3;
616            int       TOP_MID_SPACER_HEIGHT = font_group.get_max_height()-TOP_MID_LINE_HEIGHT;
617
618            top_mid_line_terminal = new ED4_line_terminal("Top_Mid_Line_Terminal", 0, TOP_MID_LINE_HEIGHT, device_manager);    // width will be set below
619            device_manager->append_member(top_mid_line_terminal);
620
621            top_mid_spacer_terminal = new ED4_spacer_terminal("Top_Middle_Spacer", true, 880, TOP_MID_SPACER_HEIGHT, device_manager);
622            device_manager->append_member(top_mid_spacer_terminal);
623
624            // needed to avoid text-clipping problems:
625            main_manager->set_top_middle_spacer_terminal(top_mid_spacer_terminal);
626            main_manager->set_top_middle_line_terminal(top_mid_line_terminal);
627        }
628
629        // ********** Middle Area beginning **********
630
631        ED4_area_manager          *middle_area_manager;
632        ED4_tree_terminal         *tree_terminal;
633        ED4_multi_species_manager *mid_multi_species_manager;
634        ED4_spacer_terminal       *mid_multi_spacer_terminal_beg;
635        ED4_line_terminal         *mid_bot_line_terminal;
636        ED4_spacer_terminal       *total_bottom_spacer;
637        {
638            middle_area_manager = new ED4_area_manager("Middle_Area_Manager", 0, 0, device_manager);
639            device_manager->append_member(middle_area_manager);
640            middle_area_man = middle_area_manager;
641
642            tree_terminal = new ED4_tree_terminal("Tree", 2, 0, middle_area_manager);
643            middle_area_manager->append_member(tree_terminal);
644
645            mid_multi_species_manager = new ED4_multi_species_manager("Middle_MultiSpecies_Manager", 0, 0, middle_area_manager);
646            middle_area_manager->append_member(mid_multi_species_manager);
647
648            mid_multi_spacer_terminal_beg = new ED4_spacer_terminal("Mid_Multi_Spacer_Terminal_Beg", false, 0, 3, mid_multi_species_manager);
649            mid_multi_species_manager->append_member(mid_multi_spacer_terminal_beg);
650
651            scroll_links.link_for_ver_slider = middle_area_manager;
652
653            {
654                GB_transaction ta(gb_main);
655                int index  = 0;
656                EDB_root_bact::scan_string(mid_multi_species_manager, ref_terminals, area_string_middle, &index, species_progress);
657            }
658
659            {
660                ED4_spacer_terminal *mid_bot_spacer_terminal = new ED4_spacer_terminal("Middle_Bot_Spacer_Terminal", false, 880, 10, device_manager);
661                device_manager->append_member(mid_bot_spacer_terminal);
662            }
663
664            mid_bot_line_terminal = new ED4_line_terminal("Mid_Bot_Line_Terminal", 0, 3, device_manager);    // width will be set below
665            device_manager->append_member(mid_bot_line_terminal);
666
667            total_bottom_spacer = new ED4_spacer_terminal("Total_Bottom_Spacer_terminal", false, 0, 10000, device_manager);
668            total_bottom_spacer->clr_property(PROP_DYNA_RESIZE);
669            device_manager->append_member(total_bottom_spacer);
670        }
671
672        if (scroll_links.link_for_hor_slider) {
673            const long ext_width    = long(scroll_links.link_for_hor_slider->extension.size[WIDTH]);
674            const long spacer_width = ext_width + MAXNAME_WIDTH + SEQUENCE_INFO_WIDTH;
675            const long line_width   = spacer_width + TREE_TERMINAL_WIDTH;
676
677            top_multi_spacer_terminal_beg->extension.size[WIDTH] = spacer_width;
678            mid_multi_spacer_terminal_beg->extension.size[WIDTH] = spacer_width;
679            total_bottom_spacer->extension.size[WIDTH]           = spacer_width;
680
681            top_mid_line_terminal->extension.size[WIDTH] = line_width;
682            mid_bot_line_terminal->extension.size[WIDTH] = line_width;
683
684        }
685
686        tree_terminal->set_links(NULp, mid_multi_species_manager);                          // set links
687        top_spacer_terminal->set_links(tree_terminal, top_multi_species_manager);
688        top_mid_spacer_terminal->set_links(middle_area_manager, NULp);
689        total_bottom_spacer->set_links(mid_bot_line_terminal, NULp);
690
691        species_progress.done();
692    }
693
694    first_window->update_window_coords();
695    resize_all_requesting_childs();
696
697    main_manager->route_down_hierarchy(makeED4_route_cb(force_group_update)).expect_no_error();
698
699    if (!scroll_links.link_for_hor_slider) { // happens when no species AND no SAI has data
700        startup_progress->done();
701        startup_progress.setNull(); // make progress disappear (otherwise prompter below is often behind progress window)
702        GB_pop_transaction(gb_main);
703
704        aw_popup_ok(GBS_global_string("No species/SAI contains data in '%s'\nARB_EDIT4 will terminate", alignment_name));
705        ED4_exit();
706    }
707
708    // build consensi
709    {
710        arb_progress consensi_progress("Initializing consensi", total_no_of_species+total_no_of_groups+1); // 1 is root_group_man
711
712        root_group_man->create_consensus(root_group_man, &consensi_progress);
713        e4_assert(root_group_man->table().ok());
714        consensi_progress.done(); // if there is a "top"-group, progress increment is one to low
715    }
716
717    root_group_man->remap()->mark_compile_needed_force();
718    root_group_man->update_remap();
719
720    // calc size and display:
721
722    resize_all_requesting_childs();
723
724    e4_assert(main_manager);
725
726    {
727        ED4_base *x_link      = scroll_links.link_for_hor_slider;
728        ED4_base *y_link      = scroll_links.link_for_ver_slider;
729        ED4_base *width_link  = x_link;
730        ED4_base *height_link = y_link;
731
732        ED4_window *win = first_window;
733        while (win) {
734            win->set_scrolled_rectangle(x_link, y_link, width_link, height_link);
735            win->aww->show();
736            win->update_scrolled_rectangle();
737            win = win->next;
738        }
739    }
740
741    ED4_request_relayout();
742    ED4_finish_and_show_notFoundMessage();
743
744#if defined(DEBUG) && 0
745    // dump created hierarchy:
746    puts("---------------------------------------- [main_manager dump start]");
747    main_manager->dump(1);
748    puts("---------------------------------------- [main_manager dump end]");
749#endif
750
751    return ED4_R_OK;
752}
753
754ED4_returncode ED4_root::get_area_rectangle(AW_screen_area *rect, AW_pos x, AW_pos y) {
755    // returns win-coordinates of area (defined by folding lines) which contains position x/y
756    int                    x1, x2, y1, y2;
757    const AW_screen_area&  area_rect = current_device()->get_area_size();
758
759    x1 = area_rect.l;
760    for (const ED4_folding_line *flv=current_ed4w()->get_vertical_folding(); ; flv = flv->get_next()) {
761        if (flv) {
762            x2 = int(flv->get_pos()); // @@@ use AW_INT ?
763        }
764        else {
765            x2 = area_rect.r;
766            if (x1==x2) {
767                break;
768            }
769        }
770
771        y1 = area_rect.t;
772        for (const ED4_folding_line *flh=current_ed4w()->get_horizontal_folding(); ; flh = flh->get_next()) {
773            if (flh) {
774                y2 = int(flh->get_pos()); // @@@ use AW_INT ?
775            }
776            else {
777                y2 = area_rect.b;
778                if (y1==y2) {
779                    break;
780                }
781            }
782
783            if (x1<=x && x<=x2 && y1<=y && y<=y2) {
784                rect->t = y1;
785                rect->b = y2;
786                rect->l = x1;
787                rect->r = x2;
788                return ED4_R_OK;
789            }
790            y1 = y2;
791            if (!flh) break;
792        }
793        x1 = x2;
794        if (!flv) break;
795    }
796    return ED4_R_IMPOSSIBLE; // no area contains x/y :-(
797}
798
799void ED4_root::copy_window_struct(ED4_window *source, ED4_window *destination) {
800    destination->slider_pos_horizontal  = source->slider_pos_horizontal;
801    destination->slider_pos_vertical    = source->slider_pos_vertical;
802    destination->coords         = source->coords;
803}
804
805
806static void reload_helix_cb() {
807    const char *err = ED4_ROOT->helix->init(ED4_ROOT->get_gb_main());
808    if (err) aw_message(err);
809    ED4_request_full_refresh();
810}
811
812
813static void reload_ecoli_cb() {
814    const char *err = ED4_ROOT->ecoli_ref->init(ED4_ROOT->get_gb_main());
815    if (err) aw_message(err);
816    ED4_request_full_refresh();
817}
818
819// ---------------------------------------
820//      recursion through all species
821
822DECLARE_CBTYPE_FVV_AND_BUILDERS(ED4_Species_Callback, ARB_ERROR, GBDATA *); // generates makeED4_Species_Callback
823
824static ARB_ERROR do_sth_with_species(ED4_base *base, const ED4_Species_Callback *cb) {
825    ARB_ERROR error = NULp;
826
827    if (base->is_species_manager()) {
828        ED4_species_manager       *species_manager       = base->to_species_manager();
829        ED4_species_name_terminal *species_name_terminal = species_manager->search_spec_child_rek(LEV_SPECIES_NAME)->to_species_name_terminal();
830
831        if (species_name_terminal->get_species_pointer()) {
832            char *species_name = GB_read_as_string(species_name_terminal->get_species_pointer());
833
834            e4_assert(species_name);
835            GBDATA *species = GBT_find_species(ED4_ROOT->get_gb_main(), species_name);
836
837            error = species
838                ? (*cb)(species)
839                : GB_append_exportedError(GBS_global_string("can't find species '%s'", species_name));
840
841            free(species_name);
842        }
843    }
844
845    return error;
846}
847
848
849static ARB_ERROR ED4_with_all_loaded_species(const ED4_Species_Callback& cb) {
850    return ED4_ROOT->root_group_man->route_down_hierarchy(makeED4_route_cb(do_sth_with_species, &cb));
851}
852
853static bool is_named(ED4_base *base, const char *wanted_name) {
854    ED4_species_name_terminal *name_term = base->to_species_name_terminal();
855    GBDATA                    *gbd       = name_term->get_species_pointer();
856    if (gbd) {
857        const char *name = GB_read_char_pntr(gbd);
858        e4_assert(name);
859
860        return strcmp(name, wanted_name) == 0;
861    }
862    return false;
863}
864
865static bool is_species_named(ED4_base *base, const char *species_name) {
866    return base->inside_species_seq_manager() && is_named(base, species_name);
867}
868
869static bool is_SAI_named(ED4_base *base, const char *sai_name) {
870    return base->inside_SAI_manager() && is_named(base, sai_name);
871}
872
873ED4_species_name_terminal *ED4_find_species_or_SAI_name_terminal(const char *species_name) {
874    ED4_base *base = ED4_ROOT->root_group_man->find_first_that(LEV_SPECIES_NAME, makeED4_basePredicate(is_species_named, species_name));
875    return base ? base->to_species_name_terminal() : NULp;
876}
877ED4_species_name_terminal *ED4_find_species_name_terminal(const char *species_name) {
878    ED4_base *base = ED4_ROOT->root_group_man->find_first_that(LEV_SPECIES_NAME, makeED4_basePredicate(is_species_named, species_name));
879    return base ? base->to_species_name_terminal() : NULp;
880}
881ED4_species_name_terminal *ED4_find_SAI_name_terminal(const char *sai_name) {
882    ED4_base *base = ED4_ROOT->root_group_man->find_first_that(LEV_SPECIES_NAME, makeED4_basePredicate(is_SAI_named, sai_name));
883    return base ? base->to_species_name_terminal() : NULp;
884}
885
886static char *get_group_consensus(const char *species_name, PosRange range) {
887    ED4_species_name_terminal *name_term = ED4_find_species_name_terminal(species_name);
888    char *consensus = NULp;
889
890    if (name_term) {
891        ED4_abstract_group_manager *group_man = name_term->get_parent(ED4_level(LEV_GROUP|LEV_ROOTGROUP))->to_abstract_group_manager();
892        if (group_man) {
893            consensus = group_man->build_consensus_string(range);
894        }
895    }
896
897    return consensus;
898}
899
900static bool get_selected_range(PosRange& range) {
901    ED4_highlighted_elem *listElem = ED4_ROOT->highlighted_objects->head();
902    if (listElem) {
903        ED4_sequence_terminal *seqTerm = listElem->elem()->object->corresponding_sequence_terminal();
904        return ED4_get_highlighted_range(seqTerm, range);
905    }
906    return false;
907}
908
909static ED4_highlighted_elem *curr_aligner_elem = NULp;
910
911static GBDATA *get_next_selected_species() {
912    if (!curr_aligner_elem) return NULp;
913
914    ED4_species_manager *specMan = curr_aligner_elem->elem()->object->containing_species_manager();
915    curr_aligner_elem = curr_aligner_elem->next();
916    return specMan->get_species_pointer();
917}
918
919static GBDATA *get_first_selected_species(int *total_no_of_selected_species) {
920    int selected = ED4_ROOT->highlighted_objects->size();
921
922    if (total_no_of_selected_species) {
923        *total_no_of_selected_species = selected;
924    }
925
926    if (selected) {
927        curr_aligner_elem = ED4_ROOT->highlighted_objects->head();
928    }
929    else {
930        curr_aligner_elem = NULp;
931    }
932
933    return get_next_selected_species();
934}
935
936static ARB_ERROR ED4_delete_temp_entries(GBDATA *species, GB_CSTR alignment_name) {
937    return FastAligner_delete_temp_entries(species, alignment_name);
938}
939
940static void ED4_remove_faligner_entries() {
941    GBDATA    *gb_main = ED4_ROOT->get_gb_main();
942    ARB_ERROR  error   = GB_begin_transaction(gb_main);
943    if (!error) error  = ED4_with_all_loaded_species(makeED4_Species_Callback(ED4_delete_temp_entries, ED4_ROOT->get_alignment_name()));
944    GB_end_transaction_show_error(gb_main, error, aw_message);
945}
946
947static void toggle_helix_for_SAI(AW_window *aww) {
948    ED4_LocalWinContext  uses(aww);
949    ED4_cursor          *cursor = &current_cursor();
950
951    if (cursor->in_SAI_terminal()) {
952        ED4_sequence_terminal      *sai_term      = cursor->owner_of_cursor->to_sequence_terminal();
953        ED4_sequence_info_terminal *sai_info_term = sai_term->parent->search_spec_child_rek(LEV_SEQUENCE_INFO)->to_sequence_info_terminal();
954
955        GBDATA         *gb_sai_data = sai_info_term->data();
956        GB_transaction  ta(gb_sai_data);
957
958        GBDATA *gb_sai      = GB_get_grandfather(gb_sai_data);
959        GBDATA *gb_disp_sec = GB_searchOrCreate_int(gb_sai, "showsec", 0);
960
961        bool show_sec = 1-bool(GB_read_int(gb_disp_sec));
962        GB_ERROR error = GB_write_int(gb_disp_sec, show_sec);
963        if (!error) {
964            sai_term->set_secstruct_display(show_sec);
965            sai_term->request_refresh();
966        }
967        if (error) aw_message(error);
968    }
969    else {
970        aw_message("Please select an SAI");
971    }
972}
973
974static void title_mode_changed(AW_root *aw_root, AW_window *aww) {
975    int title_mode = aw_root->awar(AWAR_EDIT_TITLE_MODE)->read_int();
976
977    if (title_mode==0) {
978        aww->set_info_area_height(57);
979    }
980    else {
981        aww->set_info_area_height(170);
982    }
983}
984
985static void ED4_undo_redo(AW_window *aww, GB_UNDO_TYPE undo_type) {
986    ED4_LocalWinContext uses(aww);
987
988    GBDATA   *gb_main = ED4_ROOT->get_gb_main();
989    GB_ERROR  error   = GB_undo(gb_main, undo_type);
990
991    if (error) {
992        aw_message(error);
993    }
994    else {
995        GB_begin_transaction(gb_main);
996        GB_commit_transaction(gb_main);
997        ED4_cursor *cursor = &current_cursor();
998        if (cursor->owner_of_cursor) cursor->owner_of_cursor->request_refresh();
999    }
1000}
1001
1002static AW_window *ED4_zoom_message_window(AW_root *root) {
1003    AW_window_simple *aws = new AW_window_simple;
1004
1005    aws->init(root, "ZOOM_ERR_MSG", "Errors and warnings");
1006    aws->load_xfig("edit4/message.fig");
1007
1008    aws->callback(AW_POPDOWN);
1009    aws->at("hide");
1010    aws->create_button("HIDE", "HIDE");
1011
1012    aws->callback(aw_clear_message_cb);
1013    aws->at("clear");
1014    aws->create_button("CLEAR", "CLEAR");
1015
1016    aws->at("errortext");
1017    aws->create_text_field(AWAR_ERROR_MESSAGES);
1018
1019    return aws;
1020}
1021
1022
1023static char *cat(char *toBuf, const char *s1, const char *s2) {
1024    char *buf = toBuf;
1025
1026    while ((*buf++=*s1++)!=0) ;
1027    buf--;
1028    while ((*buf++=*s2++)!=0) ;
1029
1030    return toBuf;
1031}
1032
1033static void insert_search_fields(AW_window_menu_modes *awmm,
1034                                 const char *label_prefix, const char *macro_prefix,
1035                                 const char *pattern_awar_name, const char *show_awar_name,
1036                                 int short_form, ED4_SearchPositionType type, ED4_window *ed4w)
1037{
1038    char buf[200];
1039
1040    if (!short_form) {
1041        awmm->at(cat(buf, label_prefix, "search"));
1042        awmm->create_input_field(pattern_awar_name, 30);
1043    }
1044
1045    awmm->at(cat(buf, label_prefix, "n"));
1046    awmm->help_text("e4_search.hlp");
1047    awmm->callback(makeWindowCallback(ED4_search_cb, ED4_encodeSearchDescriptor(+1, type), ed4w));
1048    awmm->create_button(cat(buf, macro_prefix, "_SEARCH_NEXT"), "#edit/next.xpm");
1049
1050    awmm->at(cat(buf, label_prefix, "l"));
1051    awmm->help_text("e4_search.hlp");
1052    awmm->callback(makeWindowCallback(ED4_search_cb, ED4_encodeSearchDescriptor(-1, type), ed4w));
1053    awmm->create_button(cat(buf, macro_prefix, "_SEARCH_LAST"), "#edit/last.xpm");
1054
1055    awmm->at(cat(buf, label_prefix, "d"));
1056    awmm->help_text("e4_search.hlp");
1057    awmm->callback(makeWindowCallback(ED4_popup_search_window, type));
1058    awmm->create_button(cat(buf, macro_prefix, "_SEARCH_DETAIL"), "#edit/detail.xpm");
1059
1060    awmm->at(cat(buf, label_prefix, "s"));
1061    awmm->create_toggle(show_awar_name);
1062}
1063
1064static void ED4_set_protection(AW_window *aww, int wanted_protection) {
1065    ED4_LocalWinContext uses(aww);
1066    ED4_cursor *cursor = &current_cursor();
1067    GB_ERROR    error  = NULp;
1068
1069    if (cursor->owner_of_cursor) {
1070        ED4_sequence_terminal      *seq_term      = cursor->owner_of_cursor->to_sequence_terminal();
1071        ED4_sequence_info_terminal *seq_info_term = seq_term->parent->search_spec_child_rek(LEV_SEQUENCE_INFO)->to_sequence_info_terminal();
1072        GBDATA                     *gbd           = seq_info_term->data();
1073
1074        GB_transaction      ta(gbd);
1075        GB_topSecurityLevel unsecured(gbd);
1076
1077        error = GB_write_security_write(gbd, wanted_protection);
1078        error = ta.close(error);
1079    }
1080    else {
1081        error = "No species selected";
1082    }
1083
1084    if (error) aw_message(error);
1085}
1086
1087enum MenuHighlightType {
1088    ED4_MS_NONE,
1089    ED4_MS_ALL,
1090    ED4_MS_INVERT,
1091    ED4_MS_INVERT_GROUP,
1092    ED4_MS_UNMARK_ALL,
1093    ED4_MS_MARK_SELECTED,
1094    ED4_MS_UNMARK_SELECTED,
1095    ED4_MS_SELECT_MARKED,
1096    ED4_MS_DESELECT_MARKED,
1097    ED4_MS_TOGGLE_BLOCKTYPE
1098};
1099
1100static void ED4_menu_highlight(AW_window *aww, MenuHighlightType hilight) {
1101    GBDATA         *gb_main = ED4_ROOT->get_gb_main();
1102    GB_transaction  ta(gb_main);
1103
1104    ED4_multi_species_manager *middle_multi_man = ED4_ROOT->middle_area_man->get_multi_species_manager();
1105
1106    e4_assert(middle_multi_man);
1107
1108    switch (hilight) {
1109        case ED4_MS_NONE: {
1110            if (ED4_getBlocktype()!=ED4_BT_NOBLOCK) {
1111                ED4_ROOT->deselect_all();
1112            }
1113            break;
1114        }
1115        case ED4_MS_ALL: {
1116            middle_multi_man->select_all(true); // only species
1117            ED4_correctBlocktypeAfterModification();
1118            break;
1119        }
1120        case ED4_MS_INVERT: {
1121            middle_multi_man->invert_selection_of_all_species();
1122            ED4_correctBlocktypeAfterModification();
1123            break;
1124        }
1125        case ED4_MS_SELECT_MARKED: {
1126            middle_multi_man->marked_species_select(true);
1127            ED4_correctBlocktypeAfterModification();
1128            break;
1129        }
1130        case ED4_MS_DESELECT_MARKED: {
1131            middle_multi_man->marked_species_select(false);
1132            ED4_correctBlocktypeAfterModification();
1133            break;
1134        }
1135        case ED4_MS_UNMARK_ALL: {
1136            GBT_mark_all(gb_main, 0);
1137            break;
1138        }
1139        case ED4_MS_MARK_SELECTED: {
1140            middle_multi_man->selected_species_mark(true);
1141            ED4_correctBlocktypeAfterModification();
1142            break;
1143        }
1144        case ED4_MS_UNMARK_SELECTED: {
1145            middle_multi_man->selected_species_mark(false);
1146            ED4_correctBlocktypeAfterModification();
1147            break;
1148        }
1149        case ED4_MS_INVERT_GROUP: {
1150            ED4_cursor *cursor = &ED4_ROOT->first_window->get_matching_ed4w(aww)->cursor;
1151            int done = 0;
1152
1153            if (cursor->owner_of_cursor) {
1154                ED4_multi_species_manager *multi_man = cursor->owner_of_cursor->get_parent(LEV_MULTI_SPECIES)->to_multi_species_manager();
1155
1156                multi_man->invert_selection_of_all_species();
1157                ED4_correctBlocktypeAfterModification();
1158                done = 1;
1159            }
1160
1161            if (!done) {
1162                aw_message("Place cursor into group");
1163            }
1164            break;
1165        }
1166        case ED4_MS_TOGGLE_BLOCKTYPE: {
1167            ED4_toggle_block_type();
1168            break;
1169        }
1170        default: {
1171            e4_assert(0);
1172            break;
1173        }
1174    }
1175
1176    ED4_request_full_refresh();
1177}
1178
1179static void ED4_menu_perform_block_operation(AW_window *, ED4_blockoperation_type type) {
1180    ED4_perform_block_operation(type);
1181}
1182
1183static void modes_cb(AW_window*, ED4_species_mode smode) {
1184    ED4_ROOT->species_mode = smode;
1185    for (ED4_window *win = ED4_ROOT->first_window; win; win = win->next) {
1186        win->aww->select_mode(smode);
1187    }
1188    if (smode == ED4_SM_INFO) {
1189        AWT_trigger_remote_action(NULp, ED4_ROOT->get_gb_main(), "ARB_NT:species_info");
1190    }
1191}
1192
1193void ED4_no_dangerous_modes() {
1194    if (ED4_ROOT->species_mode == ED4_SM_KILL) {
1195        modes_cb(NULp, ED4_SM_MOVE);
1196    }
1197}
1198
1199static char *get_helix_string(GBDATA *gb_main, const char *alignment_name) {
1200    GB_transaction ta(gb_main);
1201
1202    char   *helix_string = NULp;
1203    char   *helix_name   = GBT_get_default_helix(gb_main);
1204    GBDATA *gb_helix_con = GBT_find_SAI(gb_main, helix_name);
1205    if (gb_helix_con) {
1206        GBDATA *gb_helix = GBT_find_sequence(gb_helix_con, alignment_name);
1207        if (gb_helix) helix_string = GB_read_string(gb_helix);
1208    }
1209    free(helix_name);
1210
1211    return helix_string;
1212}
1213
1214const AlignDataAccess *ED4_get_aligner_data_access() {
1215    static SmartPtr<AlignDataAccess> aliDataAccess;
1216
1217    if (aliDataAccess.isNull()) {
1218        aliDataAccess = new AlignDataAccess(ED4_ROOT->get_gb_main(),
1219                                            ED4_ROOT->get_alignment_name(),
1220                                            true, ED4_trigger_instant_refresh, // perform refresh
1221                                            get_group_consensus,               // aligner fetches consensus of group of species via this function
1222                                            get_selected_range,                // aligner fetches column range of selection via this function
1223                                            get_first_selected_species,        // aligner fetches first and..
1224                                            get_next_selected_species,         // .. following selected species via these functions
1225                                            get_helix_string);                 // used by island_hopping (if configured to use sec-structure)
1226    }
1227
1228    return aliDataAccess.content();
1229}
1230
1231static AW_window *ED4_create_faligner_window(AW_root *awr, const AlignDataAccess *data_access) {
1232#if defined(DEBUG)
1233    static const AlignDataAccess *last_data_access = NULp;
1234
1235    e4_assert(!last_data_access || (last_data_access == data_access)); // there shall be only one AlignDataAccess
1236    last_data_access = data_access;
1237#endif
1238
1239    static AW_window *aws = NULp;
1240    if (!aws) aws = FastAligner_create_window(awr, data_access);
1241    return aws;
1242}
1243
1244static const char *propertyName(GBDATA *gb_main, int mode) {
1245    // mode == 0 -> alignment specific          (e.g. "edit4_ali_16s.arb")
1246    // mode == 1 -> alignment-type specific     (e.g. "edit4_rna.arb")
1247    // mode == 2 -> unspecific (normal)         (always "edit4.arb")
1248    //
1249    // Note : result is only valid until next call
1250
1251    e4_assert(mode >= 0 && mode <= 2);
1252
1253    const char *result;
1254    if (mode == 2) {
1255        result = "edit4.arb";
1256    }
1257    else {
1258        static char *ali_name    = NULp;
1259        static char *ali_type    = NULp;
1260        static char *result_copy = NULp;
1261
1262        if (!ali_name) {
1263            GB_transaction ta(gb_main);
1264
1265            ali_name = GBT_get_startup_alignment(gb_main);
1266            if (!ali_name) {
1267                e4_assert(!ED4_ROOT); // this should only occur during startup (and only while running from debugger)
1268                GBK_terminatef("Failed to detect default alignment (Reason: %s)", GB_await_error());
1269            }
1270            ali_type    = GBT_get_alignment_type_string(gb_main, ali_name);
1271            result_copy = new char[21+strlen(ali_name)];
1272        }
1273
1274        sprintf(result_copy, "edit4_%s.arb", mode == 0 ? ali_name : ali_type);
1275        result = result_copy;
1276    }
1277
1278    return result;
1279}
1280
1281static void ED4_save_properties(AW_window *aw, int mode) {
1282    AW_save_specific_properties(aw, propertyName(ED4_ROOT->get_gb_main(), mode));
1283}
1284
1285void ED4_popup_gc_window(AW_window *awp, AW_gc_manager *gcman) {
1286    typedef std::map<AW_gc_manager*, AW_window*> gcwin;
1287    static gcwin win;
1288
1289    gcwin::iterator found = win.find(gcman);
1290
1291    AW_window *aww = NULp;
1292    if (found == win.end()) {
1293        aww        = AW_create_gc_window(awp->get_root(), gcman);
1294        win[gcman] = aww;
1295    }
1296    else {
1297        aww = win[gcman];
1298    }
1299    aww->activate();
1300}
1301
1302static void gc_change_cb(GcChange whatChanged) {
1303    if (whatChanged == GC_FONT_CHANGED) {
1304        ED4_resize_all_extensions();
1305    }
1306    ED4_request_full_instant_refresh();
1307}
1308
1309static void ED4_popup_helix_or_pfold_window(AW_window *aw_parent, GB_alignment_type aliType) {
1310    static AW_window *aww = NULp;
1311
1312    if (!aww) {
1313        AW_root *aw_root = aw_parent->get_root();
1314
1315        if (aliType == GB_AT_AA) {
1316            static WindowCallback reqRelCb = makeWindowCallback(ED4_request_relayout);
1317
1318            aww = ED4_pfold_create_props_window(aw_root, &reqRelCb);
1319        }
1320        else {
1321            ED4_ROOT->helix->add_callback(makeRootCallback(ED4_request_relayout));
1322            aww = create_helix_props_window(aw_root);
1323        }
1324    }
1325
1326    aww->activate();
1327}
1328
1329ED4_returncode ED4_root::generate_window(AW_device **device, ED4_window **new_window) {
1330    {
1331        ED4_window *ed4w = first_window;
1332
1333        while (ed4w) { // before creating a window look for a hidden window
1334            if (ed4w->is_hidden) {
1335                ed4w->aww->show();
1336                ed4w->is_hidden = false;
1337                return ED4_R_BREAK;
1338            }
1339            ed4w = ed4w->next;
1340        }
1341    }
1342
1343    if (ED4_window::no_of_windows == MAXWINDOWS) { // no more than 5 windows allowed
1344        aw_message(GBS_global_string("Restricted to %i windows", MAXWINDOWS));
1345        return ED4_R_BREAK;
1346    }
1347
1348    AW_window_menu_modes *awmm = new AW_window_menu_modes;
1349    {
1350        int   winNum   = ED4_window::no_of_windows+1;
1351        char *winName  = winNum>1 ? GBS_global_string_copy("ARB_EDIT4_%i", winNum) : ARB_strdup("ARB_EDIT4");
1352        char *winTitle = GBS_global_string_copy("ARB_EDIT4 *%d* [%s]", winNum, alignment_name);
1353
1354        awmm->init(aw_root, winName, winTitle, 800, 450);
1355
1356        free(winTitle);
1357        free(winName);
1358    }
1359
1360    *device     = awmm->get_device(AW_MIDDLE_AREA); // points to Middle Area device
1361    *new_window = ED4_window::insert_window(awmm);   // append to window list
1362
1363    e4_assert(ED4_window::no_of_windows >= 1);
1364    bool clone = ED4_window::no_of_windows>1;
1365    if (!clone) {                                   // this is the first window
1366        AW_init_color_group_defaults("arb_edit4");
1367    }
1368    else { // additional edit windows
1369        copy_window_struct(first_window, *new_window);
1370    }
1371
1372    ED4_LocalWinContext uses(*new_window);
1373
1374    // each window has its own gc-manager
1375    gc_manager = AW_manage_GC(awmm,
1376                              "ARB_EDIT4",                   // but all gc-managers use the same colors
1377                              *device,
1378                              ED4_G_DRAG,
1379                              AW_GCM_DATA_AREA,
1380                              makeGcChangedCallback(gc_change_cb), // callback triggering refresh on gc-change
1381
1382                              "#f8f8f8",
1383                              "STANDARD$black",              // standard color showing species/group info (name, ...)
1384                              "FlagInfo$#DDD",
1385                              "#SEQUENCES (0)$#505050",      // default color for sequences (color 0)
1386
1387                              "+-HELIX (1)$#8E0000",  "+-COLOR 2$#0000dd",    "-COLOR 3$#00AA55",
1388                              "+-COLOR 4$#80f",       "+-COLOR 5$#c0a020",    "-COLOR 6$grey",
1389                              "+-COLOR 7$#ff0000",    "+-COLOR 8$#44aaff",    "-COLOR 9$#ffaa00",
1390
1391                              "+-CURSOR$#FF0080",     "+-MARKED$#f4f8e0",     "-SELECTED$#FFFF80",
1392
1393                              "+-RANGE 0$#FFFFFF",    "+-RANGE 1$#F0F0F0",    "-RANGE 2$#E0E0E0",
1394                              "+-RANGE 3$#D8D8D8",    "+-RANGE 4$#D0D0D0",    "-RANGE 5$#C8C8C8",
1395                              "+-RANGE 6$#C0C0C0",    "+-RANGE 7$#B8B8B8",    "-RANGE 8$#B0B0B0",
1396                              "-RANGE 9$#A0A0A0",
1397
1398                              // colors used to Paint search patterns
1399                              // (do not change the names of these gcs)
1400                              "+-User1$#B8E2F8",      "+-User2$#B8E2F8",      "-Probe$#B8E2F8", // see also SEC_graphic::init_devices
1401                              "+-Primer(l)$#A9FE54",  "+-Primer(r)$#A9FE54",  "-Primer(g)$#A9FE54",
1402                              "+-Sig(l)$#DBB0FF",     "+-Sig(r)$#DBB0FF",     "-Sig(g)$#DBB0FF",
1403
1404                              "+-MISMATCHES$#FF9AFF", "+-Flag$#7c7ce3",       "-FlagFill$#aacef1",
1405
1406                              "&color_groups", // use color groups
1407
1408                              NULp);
1409
1410    // since the gc-managers of all EDIT4-windows point to the same window properties,
1411    // changing fonts and colors is always done on first gc-manager
1412    static AW_gc_manager *first_gc_manager = NULp;
1413    if (!first_gc_manager) first_gc_manager = gc_manager;
1414
1415    // --------------
1416    //      File
1417
1418#if defined(DEBUG)
1419    AWT_create_debug_menu(awmm);
1420#endif // DEBUG
1421
1422    awmm->create_menu("File", "F", AWM_ALL);
1423
1424    awmm->insert_menu_topic("new_win", "New Editor Window", "N", NULp, AWM_ALL, ED4_new_editor_window);
1425    awmm->sep______________();
1426    awmm->insert_menu_topic("save_config",                    "Save configuration",        "S", "species_configs_saveload.hlp", AWM_ALL, makeWindowCallback(ED4_saveConfiguration, false));
1427    awmm->insert_menu_topic(awmm->local_id("save_config_as"), "Save configuration as ...", "a", "species_configs_saveload.hlp", AWM_ALL, ED4_create_saveConfigurationAs_window);
1428    awmm->insert_menu_topic(awmm->local_id("load_config"),    "Load configuration ...",    "L", "species_configs_saveload.hlp", AWM_ALL, ED4_create_loadConfiguration_window);
1429    awmm->insert_menu_topic("reload_config",                  "Reload configuration",      "R", "species_configs_saveload.hlp", AWM_ALL, ED4_reloadConfiguration);
1430    insert_macro_menu_entry(awmm, true);
1431    awmm->sep______________();
1432    // keep the following entries in sync with ../NTREE/NT_extern.cxx@common_save_menu_entries
1433    awmm->insert_menu_topic("save_changes", "Quicksave changes",          "c", "save.hlp", AWM_ALL, makeWindowCallback(AWT_trigger_remote_action, gb_main, "ARB_NT:save_changes"));
1434    awmm->insert_menu_topic("save_all_as",  "Save whole database as ...", "w", "save.hlp", AWM_ALL, makeWindowCallback(AWT_trigger_remote_action, gb_main, "ARB_NT:save_all_as"));
1435#if defined(DEBUG)
1436    awmm->sep______________();
1437    awmm->insert_menu_topic("deb1", "[DEBUG] remote: invalid app", "D", NULp, AWM_ALL, makeWindowCallback(AWT_trigger_remote_action, gb_main, "ARB_NTREE:aljdlaisjdlad"));
1438    awmm->insert_menu_topic("deb2", "[DEBUG] remote: invalid cmd", "E", NULp, AWM_ALL, makeWindowCallback(AWT_trigger_remote_action, gb_main, "ARB_NT:aljdlaisjdlad"));
1439#endif
1440    awmm->sep______________();
1441    GDE_load_menu(awmm, AWM_ALL, "Print");
1442    awmm->sep______________();
1443
1444    if (clone) awmm->insert_menu_topic("close", "CLOSE", "C", NULp, AWM_ALL, ED4_quit_editor);
1445    else       awmm->insert_menu_topic("quit",  "QUIT",  "Q", NULp, AWM_ALL, ED4_quit_editor);
1446
1447    // ----------------
1448    //      Create
1449
1450    awmm->create_menu("Create", "C", AWM_ALL);
1451    awmm->insert_menu_topic(awmm->local_id("create_species"),                "Create new species",                "n", NULp, AWM_ALL, makeCreateWindowCallback(ED4_create_new_seq_window, CREATE_NEW_SPECIES));
1452    awmm->insert_menu_topic(awmm->local_id("create_species_from_consensus"), "Create new species from consensus", "u", NULp, AWM_ALL, makeCreateWindowCallback(ED4_create_new_seq_window, CREATE_FROM_CONSENSUS));
1453    awmm->insert_menu_topic(awmm->local_id("copy_species"),                  "Copy current species",              "C", NULp, AWM_ALL, makeCreateWindowCallback(ED4_create_new_seq_window, COPY_SPECIES));
1454    awmm->sep______________();
1455    awmm->insert_menu_topic("create_group",           "Create new Group (from selected)", "G", NULp, AWM_ALL, makeWindowCallback(group_species_cb, false));
1456    awmm->insert_menu_topic("create_groups_by_field", "Create new groups using Field",    "F", NULp, AWM_ALL, makeWindowCallback(group_species_cb, true));
1457
1458    // --------------
1459    //      Edit
1460
1461    awmm->create_menu("Edit", "E", AWM_ALL);
1462    awmm->insert_menu_topic("refresh",                  "Refresh [Ctrl-L]",           "f", NULp,                 AWM_ALL, makeWindowCallback(ED4_request_full_refresh));
1463    awmm->insert_menu_topic("load_current",             "Load current species [GET]", "G", "e4_get_species.hlp", AWM_ALL, makeWindowCallback(ED4_get_and_jump_to_current));
1464    awmm->insert_menu_topic("load_marked",              "Load marked species",        "m", "e4_get_species.hlp", AWM_ALL, makeWindowCallback(ED4_get_marked_from_menu));
1465    awmm->insert_menu_topic(awmm->local_id("load_SAI"), "Load SAI ...",               "L", "e4_get_species.hlp", AWM_ALL, ED4_create_loadSAI_window);
1466    awmm->sep______________();
1467    awmm->insert_menu_topic("refresh_ecoli",       "Reload Ecoli sequence",        "E", "ecoliref.hlp", AWM_ALL, makeWindowCallback(reload_ecoli_cb));
1468    awmm->insert_menu_topic("refresh_helix",       "Reload Helix",                 "H", "helix.hlp",    AWM_ALL, makeWindowCallback(reload_helix_cb));
1469    awmm->insert_menu_topic("helix_jump_opposite", "Jump helix opposite [Ctrl-J]", "J", NULp,           AWM_ALL, ED4_helix_jump_opposite);
1470    awmm->sep______________();
1471
1472    awmm->insert_sub_menu("Set protection of current ", "p");
1473    {
1474        char macro[] = "to_0",
1475            topic[] = ".. to 0",
1476            hotkey[] = "0";
1477
1478        for (char i='0'; i<='6'; i++) {
1479            macro[3] = topic[6] = hotkey[0] = i;
1480            awmm->insert_menu_topic(macro, topic, hotkey, "security.hlp", AWM_ALL, makeWindowCallback(ED4_set_protection, i-'0'));
1481        }
1482    }
1483    awmm->close_sub_menu();
1484
1485    awmm->sep______________();
1486    awmm->insert_menu_topic(awmm->local_id("fast_aligner"),   INTEGRATED_ALIGNERS_TITLE,            "I", "faligner.hlp",     AWM_ALL,            makeCreateWindowCallback(ED4_create_faligner_window, ED4_get_aligner_data_access()));
1487    awmm->insert_menu_topic("fast_align_set_ref",             "Set aligner reference [Ctrl-R]",     "R", "faligner.hlp",     AWM_ALL,            RootAsWindowCallback::simple(FastAligner_set_reference_species));
1488    awmm->insert_menu_topic(awmm->local_id("align_sequence"), "Old aligner from ARB_EDIT [broken]", "O", "ne_align_seq.hlp", AWM_DISABLED,       makeCreateWindowCallback(create_naligner_window, get_gb_main()));
1489    awmm->insert_menu_topic("sina",                           "SINA (SILVA Incremental Aligner)",   "S", "sina_main.hlp",    sina_mask(aw_root), makeWindowCallback(show_sina_window, ED4_get_aligner_data_access()));
1490    awmm->insert_menu_topic("del_ali_tmp",                    "Remove all aligner Entries",         "v", NULp,               AWM_ALL,            makeWindowCallback(ED4_remove_faligner_entries));
1491
1492    static WindowCallback helixOrPfoldSettings_cb = makeWindowCallback(ED4_popup_helix_or_pfold_window, alignment_type);
1493    if (alignment_type != GB_AT_AA) {
1494        awmm->insert_menu_topic("detect_bad_ali", "Detect bad helix alignments", "b", NULp, AWM_ALL, makeWindowCallback(ED4_popup_detect_bad_alignment_window, &helixOrPfoldSettings_cb));
1495    }
1496
1497    awmm->sep______________();
1498    awmm->insert_menu_topic("missing_bases", "Dot potentially missing bases", "D", "missbase.hlp", AWM_EXP, ED4_popup_dot_missing_bases_window);
1499
1500    if (alignment_type == GB_AT_RNA) { // if the database contains valid alignment of rRNA sequences
1501        awmm->sep______________();
1502        awmm->insert_menu_topic("sec_edit", "Edit secondary structure", "c", "arb_secedit.hlp", AWM_ALL, makeWindowCallback(ED4_start_plugin, gb_main, "SECEDIT"));
1503#if defined(ARB_OPENGL)
1504        awmm->insert_menu_topic("rna3d", "View 3D molecule", "3", "rna3d_general.hlp", AWM_ALL, makeWindowCallback(ED4_start_plugin, gb_main, "RNA3D"));
1505#endif // ARB_OPENGL
1506#if defined(DEBUG)
1507        awmm->insert_menu_topic("noplugin", "DEBUG: call unknown plugin", "u", NULp, AWM_ALL, makeWindowCallback(ED4_start_plugin, gb_main, "testplugin"));
1508#endif // DEBUG
1509    }
1510
1511    // --------------
1512    //      View
1513
1514    awmm->create_menu("View", "V", AWM_ALL);
1515    awmm->insert_sub_menu("Search", "S");
1516    {
1517        int         s;
1518        const char *hotkeys  = "12Poiclrg";
1519        char        hotkey[] = "_";
1520
1521        e4_assert(strlen(hotkeys) == SEARCH_PATTERNS);
1522
1523        for (s=0; s<SEARCH_PATTERNS; s++) {
1524            ED4_SearchPositionType type = ED4_SearchPositionType(s);
1525            const char *id = ED4_SearchPositionTypeId[type];
1526            int len = strlen(id);
1527            char *macro_name = GB_give_buffer(2*(len+8));
1528            char *menu_entry_name = macro_name+(len+8);
1529
1530#ifndef NDEBUG
1531            memset(macro_name, 0, 2*(len+8)); // to avoid memchk-warning
1532#endif
1533            sprintf(macro_name, "%s_SEARCH", id);
1534            char *p = macro_name;
1535            while (1) {
1536                char c = *p++;
1537                if (!c) break;
1538                p[-1] = toupper(c);
1539            }
1540            sprintf(menu_entry_name, "%s Search", id);
1541
1542            hotkey[0] = hotkeys[s];
1543            awmm->insert_menu_topic(awmm->local_id(macro_name), menu_entry_name, hotkey, "e4_search.hlp", AWM_ALL, makeWindowCallback(ED4_popup_search_window, type));
1544        }
1545    }
1546    awmm->close_sub_menu();
1547    awmm->sep______________();
1548    awmm->insert_sub_menu("Cursor position ", "p");
1549    awmm->insert_menu_topic("store_curpos",   "Store cursor position",    "S", NULp, AWM_ALL, ED4_store_curpos);
1550    awmm->insert_menu_topic("restore_curpos", "Restore cursor position ", "R", NULp, AWM_ALL, ED4_restore_curpos);
1551    awmm->insert_menu_topic("clear_curpos",   "Clear stored positions",   "C", NULp, AWM_ALL, makeWindowCallback(ED4_clear_stored_curpos));
1552    awmm->close_sub_menu();
1553
1554    awmm->sep______________();
1555    awmm->insert_menu_topic("change_cursor",             "Change cursor type",   "t", NULp,           AWM_ALL, ED4_change_cursor);
1556    awmm->insert_menu_topic(awmm->local_id("view_diff"), "View differences ...", "V", "viewdiff.hlp", AWM_ALL, ED4_create_viewDifferences_window);
1557    awmm->sep______________();
1558    awmm->insert_menu_topic("enable_col_stat",  "Activate column statistics", "A", "st_ml.hlp", AWM_EXP, ED4_activate_col_stat);
1559    awmm->insert_menu_topic("disable_col_stat", "Disable column statistics",  "i", "st_ml.hlp", AWM_EXP, ED4_disable_col_stat);
1560    awmm->insert_menu_topic("detail_col_stat",  "Toggle detailed Col.-Stat.", "C", "st_ml.hlp", AWM_EXP, ED4_toggle_detailed_column_stats);
1561    awmm->insert_menu_topic("dcs_threshold",    "Set threshold for D.c.s.",   "f", "st_ml.hlp", AWM_EXP, makeWindowCallback(ED4_set_col_stat_threshold));
1562    awmm->sep______________();
1563    awmm->insert_menu_topic(awmm->local_id("visualize_SAI"), "Visualize SAIs",                "z", "visualizeSAI.hlp",   AWM_ALL, ED4_createVisualizeSAI_window);
1564    awmm->insert_menu_topic("toggle_saisec",                 "Toggle secondary info for SAI", "o", "toggle_secinfo.hlp", AWM_ALL, toggle_helix_for_SAI);
1565
1566    // Enable ProteinViewer only for DNA sequence type
1567    if (alignment_type == GB_AT_DNA) {
1568        awmm->insert_menu_topic(awmm->local_id("Protein_Viewer"), "Protein Viewer", "w", "proteinViewer.hlp", AWM_ALL, ED4_CreateProteinViewer_window);
1569    }
1570
1571    // ---------------
1572    //      Block
1573
1574    awmm->create_menu("Block", "B", AWM_ALL);
1575
1576    awmm->insert_menu_topic("select_marked",   "Highlight marked species",    "e", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_SELECT_MARKED));
1577    awmm->insert_menu_topic("deselect_marked", "De-highlight marked species", "k", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_DESELECT_MARKED));
1578    awmm->insert_menu_topic("select_all",      "Highlight all species",       "s", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_ALL));
1579    awmm->insert_menu_topic("deselect_all",    "De-highlight all species",    "D", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_NONE));
1580    awmm->sep______________();
1581    awmm->insert_menu_topic("mark_selected",   "Mark highlighted species",   "M", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_MARK_SELECTED));
1582    awmm->insert_menu_topic("unmark_selected", "Unmark highlighted species", "n", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_UNMARK_SELECTED));
1583    awmm->insert_menu_topic("unmark_all",      "Unmark all species",         "U", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_UNMARK_ALL));
1584    awmm->sep______________();
1585    awmm->insert_menu_topic("invert_all",   "Invert highlighted species", "I", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_INVERT));
1586    awmm->insert_menu_topic("invert_group", "Invert group",               "g", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_INVERT_GROUP));
1587    awmm->sep______________();
1588    awmm->insert_menu_topic("lowcase", "Change to lower case ", "w", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_LOWER_CASE));
1589    awmm->insert_menu_topic("upcase",  "Change to upper case",  "p", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_UPPER_CASE));
1590    awmm->sep______________();
1591    awmm->insert_menu_topic("reverse",            "Reverse highlighted ",    "v", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_REVERSE));
1592    awmm->insert_menu_topic("complement",         "Complement highlighted ", "o", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_COMPLEMENT));
1593    awmm->insert_menu_topic("reverse_complement", "Reverse complement",      "t", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_REVERSE_COMPLEMENT));
1594    awmm->sep______________();
1595    awmm->insert_menu_topic("unalignBlockLeft",   "Unalign block left",   "a", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_UNALIGN_LEFT));
1596    awmm->insert_menu_topic("unalignBlockCenter", "Unalign block center", "c", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_UNALIGN_CENTER));
1597    awmm->insert_menu_topic("unalignBlockRight",  "Unalign block right",  "b", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_UNALIGN_RIGHT));
1598    awmm->sep______________();
1599    awmm->insert_menu_topic(awmm->local_id("replace"), "Search & Replace ", "h", "e4_replace.hlp", AWM_ALL, ED4_create_replace_window);
1600    awmm->insert_menu_topic(awmm->local_id("setsai"),  "Modify SAI ",       "y", "e4_modsai.hlp",  AWM_ALL, ED4_create_modsai_window);
1601    awmm->sep______________();
1602    awmm->insert_menu_topic("toggle_block_type", "Exchange: Line<->Column", "x", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_highlight, ED4_MS_TOGGLE_BLOCKTYPE));
1603    awmm->insert_menu_topic("shift_left",        "Shift block left ",       "l", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_SHIFT_LEFT));
1604    awmm->insert_menu_topic("shift_right",       "Shift block right",       "r", "e4_block.hlp", AWM_ALL, makeWindowCallback(ED4_menu_perform_block_operation, ED4_BO_SHIFT_RIGHT));
1605
1606    // --------------------
1607    //      Properties
1608
1609    awmm->create_menu("Properties", "P", AWM_ALL);
1610
1611    awmm->insert_menu_topic(awmm->local_id("props_frame"),     "Frame settings ...",    "g", NULp,               AWM_ALL, AW_preset_window);
1612    awmm->insert_menu_topic(awmm->local_id("props_options"),   "Editor Options ",       "O", "e4_options.hlp",   AWM_ALL, ED4_create_editor_options_window);
1613    awmm->insert_menu_topic(awmm->local_id("props_consensus"), "Consensus Definition ", "u", "e4_consensus.hlp", AWM_ALL, ED4_create_consensus_definition_window);
1614    awmm->sep______________();
1615
1616    awmm->insert_menu_topic("props_data",                       "Change Colors & Fonts ", "C", NULp,                  AWM_ALL, makeWindowCallback      (ED4_popup_gc_window,          first_gc_manager));
1617    awmm->insert_menu_topic(awmm->local_id("props_seq_colors"), "Sequence color mapping", "S", "sequence_colors.hlp", AWM_ALL, makeCreateWindowCallback(ED4_create_seq_colors_window, sequence_colors));
1618
1619    awmm->sep______________();
1620
1621    awmm->insert_menu_topic(awmm->local_id("props_nds"),     "Select visible info (NDS) ", "D", "ed4_nds.hlp",   AWM_ALL, ED4_create_nds_window);
1622    awmm->insert_menu_topic(awmm->local_id("props_flags"),   "Select species flags",       "f", "ed4_flags.hlp", AWM_ALL, makeCreateWindowCallback(ED4_configure_species_flags, gb_main));
1623    {
1624        if (alignment_type == GB_AT_AA) awmm->insert_menu_topic(awmm->local_id("props_pfold"),     "Protein Match Settings ", "P", "pfold_props.hlp", AWM_ALL, helixOrPfoldSettings_cb);
1625        else                            awmm->insert_menu_topic(awmm->local_id("props_helix_sym"), "Helix Settings ",         "H", "helixsym.hlp",    AWM_ALL, helixOrPfoldSettings_cb);
1626    }
1627    awmm->insert_menu_topic(awmm->local_id("props_key_map"), "Key Mappings ",              "K", "nekey_map.hlp", AWM_ALL, create_key_map_window);
1628
1629    awmm->sep______________();
1630    AW_insert_common_property_menu_entries(awmm);
1631    awmm->sep______________();
1632    awmm->insert_sub_menu("Save properties ...", "a");
1633    {
1634        static const char * const tag[] = { "save_alispecific_props", "save_alitype_props", "save_props" };
1635        static const char * const entry_type[] = { "alignment specific ", "ali-type specific ", "" };
1636
1637        // check what is the default mode
1638        int default_mode = -1;
1639        for (int mode = 0; mode <= 2; ++mode) {
1640            if (strcmp(GB_path_in_arbprop(propertyName(gb_main, mode)), db_name) == 0) {
1641                default_mode = mode;
1642                break;
1643            }
1644        }
1645        if (default_mode == -1) default_mode = 2; // no properties yet -> use 'edit4.arb'
1646
1647        const char *entry = GBS_global_string("Save loaded Properties (%s)", propertyName(gb_main, default_mode));
1648        awmm->insert_menu_topic("save_loaded_props", entry, "l", "e4_defaults.hlp", AWM_ALL, makeWindowCallback(ED4_save_properties, default_mode));
1649        awmm->sep______________();
1650
1651        for (int mode = 2; mode >= 0; --mode) {
1652            char hotkey[] = "x";
1653            hotkey[0]     = "Pta"[mode];
1654            entry         = GBS_global_string("Save %sProperties (%s)", entry_type[mode], propertyName(gb_main, mode));
1655            awmm->insert_menu_topic(tag[mode], entry, hotkey, "e4_defaults.hlp", AWM_ALL, makeWindowCallback(ED4_save_properties, mode));
1656        }
1657    }
1658    awmm->close_sub_menu();
1659
1660    awmm->insert_help_topic("ARB_EDIT4 help",     "E", "e4.hlp", AWM_ALL, makeHelpCallback("e4.hlp"));
1661
1662    // ----------------------------------------------------------------------------------------------------
1663
1664    aw_root->awar_int(AWAR_EDIT_TITLE_MODE)->add_callback(makeRootCallback(title_mode_changed, static_cast<AW_window*>(awmm)));
1665    awmm->set_bottom_area_height(0);   // No bottom area
1666
1667    awmm->auto_space(5, -2);
1668    awmm->shadow_width(3);
1669
1670    int db_pathx, db_pathy;
1671    awmm->get_at_position(&db_pathx, &db_pathy);
1672
1673    awmm->shadow_width(1);
1674    awmm->load_xfig("edit4/editmenu.fig", false);
1675
1676    // --------------------------
1677    //      help /quit /fold
1678
1679    awmm->button_length(0);
1680
1681    awmm->at("quit");
1682    awmm->callback(ED4_quit_editor);
1683    awmm->help_text("quit.hlp");
1684
1685    if (clone) awmm->create_button("CLOSE", "#close.xpm");
1686    else       awmm->create_button("QUIT",  "#quit.xpm");
1687
1688    awmm->at("help");
1689    awmm->callback(AW_help_entry_pressed);
1690    awmm->help_text("e4.hlp");
1691    awmm->create_button("HELP", "#help.xpm");
1692
1693    awmm->at("fold");
1694    awmm->help_text("e4.hlp");
1695    awmm->create_toggle(AWAR_EDIT_TITLE_MODE, "#more.xpm", "#less.xpm");
1696
1697    // -------------------
1698    //      positions
1699
1700    awmm->button_length(0);
1701
1702    awmm->at("posTxt");     awmm->create_button(NULp, "Position");
1703
1704    awmm->button_length(6+1);
1705
1706    awmm->at("ecoliTxt");   awmm->create_button(NULp, ED4_AWAR_NDS_ECOLI_NAME, NULp, "+");
1707
1708    awmm->button_length(0);
1709
1710    awmm->at("baseTxt");    awmm->create_button(NULp, "Base");
1711    awmm->at("iupacTxt");   awmm->create_button(NULp, "IUPAC");
1712    awmm->at("helixnrTxt"); awmm->create_button(NULp, "Helix#");
1713
1714    awmm->at("pos");
1715    awmm->callback(makeWindowCallback(ED4_jump_to_cursor_position, current_ed4w()->awar_path_for_cursor, ED4_POS_SEQUENCE)); // @@@ used as INPUTFIELD_CB (see #559)
1716    awmm->create_input_field(current_ed4w()->awar_path_for_cursor, 7);
1717
1718    awmm->at("ecoli");
1719    awmm->callback(makeWindowCallback(ED4_jump_to_cursor_position, current_ed4w()->awar_path_for_Ecoli, ED4_POS_ECOLI)); // @@@ used as INPUTFIELD_CB (see #559)
1720    awmm->create_input_field(current_ed4w()->awar_path_for_Ecoli, 6);
1721
1722    awmm->at("base");
1723    awmm->callback(makeWindowCallback(ED4_jump_to_cursor_position, current_ed4w()->awar_path_for_basePos, ED4_POS_BASE)); // @@@ used as INPUTFIELD_CB (see #559)
1724    awmm->create_input_field(current_ed4w()->awar_path_for_basePos, 6);
1725
1726    awmm->at("iupac");
1727    awmm->callback(makeWindowCallback(ED4_set_iupac, current_ed4w()->awar_path_for_IUPAC)); // @@@ used as INPUTFIELD_CB (see #559)
1728    awmm->create_input_field(current_ed4w()->awar_path_for_IUPAC, 4);
1729
1730    awmm->at("helixnr");
1731    awmm->callback(makeWindowCallback(ED4_set_helixnr, current_ed4w()->awar_path_for_helixNr)); // @@@ used as INPUTFIELD_CB (see #559)
1732    awmm->create_input_field(current_ed4w()->awar_path_for_helixNr, 5);
1733
1734    // ----------------------------
1735    //      jump/get/undo/redo
1736
1737    awmm->button_length(4);
1738
1739    awmm->at("jump");
1740    awmm->callback(ED4_jump_to_current_species);
1741    awmm->help_text("e4_get_species.hlp");
1742    awmm->create_button("JUMP", "Jump");
1743
1744    awmm->at("get");
1745    awmm->callback(makeWindowCallback(ED4_get_and_jump_to_current));
1746    awmm->help_text("e4_get_species.hlp");
1747    awmm->create_button("GET", "Get");
1748
1749    awmm->button_length(0);
1750
1751    awmm->at("undo");
1752    awmm->callback(makeWindowCallback(ED4_undo_redo, GB_UNDO_UNDO));
1753    awmm->help_text("undo.hlp");
1754    awmm->create_button("UNDO", "#undo.xpm");
1755
1756    awmm->at("redo");
1757    awmm->callback(makeWindowCallback(ED4_undo_redo, GB_UNDO_REDO));
1758    awmm->help_text("undo.hlp");
1759    awmm->create_button("REDO", "#redo.xpm");
1760
1761    // --------------------------
1762    //      aligner / SAIviz
1763
1764    awmm->button_length(7);
1765
1766    awmm->at("aligner");
1767    awmm->callback(makeCreateWindowCallback(ED4_create_faligner_window, ED4_get_aligner_data_access()));
1768    awmm->help_text("faligner.hlp");
1769    awmm->create_button("ALIGNER", "Aligner");
1770
1771    awmm->at("saiviz");
1772    awmm->callback(ED4_createVisualizeSAI_window);
1773    awmm->help_text("visualizeSAI.hlp");
1774    awmm->create_button("SAIVIZ", "SAIviz");
1775
1776    // -------------------------------------------
1777    //      align/insert/protection/direction
1778
1779    awmm->button_length(0);
1780
1781    awmm->at("protect");
1782    awmm->create_option_menu(AWAR_EDIT_SECURITY_LEVEL);
1783    awmm->insert_option        ("0", NULp, 0);
1784    awmm->insert_option        ("1", NULp, 1);
1785    awmm->insert_option        ("2", NULp, 2);
1786    awmm->insert_option        ("3", NULp, 3);
1787    awmm->insert_option        ("4", NULp, 4);
1788    awmm->insert_option        ("5", NULp, 5);
1789    awmm->insert_default_option("6", NULp, 6);
1790    awmm->update_option_menu();
1791
1792    // draw protection icon AFTER protection!!
1793    awmm->at("pico");
1794    awmm->create_button(NULp, "#protect.xpm");
1795
1796    // draw align/edit-button AFTER protection!!
1797    awmm->at("edit");
1798    awmm->create_toggle(AWAR_EDIT_MODE, "#edit/align.xpm", "#edit/editseq.xpm", 7);
1799
1800    awmm->at("insert");
1801    awmm->create_text_toggle(AWAR_INSERT_MODE, "Replace", "Insert", 7);
1802
1803    awmm->at("direct");
1804    awmm->create_toggle(AWAR_EDIT_RIGHTWARD, "#edit/3to5.xpm", "#edit/5to3.xpm", 7);
1805
1806    // -------------------------
1807    //      secedit / rna3d
1808
1809    int xoffset = 0;
1810
1811    if (alignment_type == GB_AT_RNA) { // if the database contains valid alignment of rRNA sequences
1812        // add buttons for RNA3D and SECEDIT plugins
1813
1814        awmm->button_length(0);
1815
1816        awmm->at("secedit");
1817        awmm->callback(makeWindowCallback(ED4_start_plugin, gb_main, "SECEDIT"));
1818        awmm->help_text("arb_secedit.hlp");
1819        awmm->create_button("SECEDIT", "#edit/secedit.xpm");
1820
1821#if defined(ARB_OPENGL)
1822        awmm->at("rna3d");
1823        awmm->callback(makeWindowCallback(ED4_start_plugin, gb_main, "RNA3D"));
1824        awmm->help_text("rna3d_general.hlp");
1825        awmm->create_button("RNA3D", "#edit/rna3d.xpm");
1826#endif // ARB_OPENGL
1827    }
1828    else {
1829        awmm->at("secedit");
1830        int xsecedit = awmm->get_at_xposition();
1831        awmm->at("zoom");
1832        int xzoom    = awmm->get_at_xposition();
1833        xoffset      = xsecedit-xzoom; // shift message stuff to the left by xoffset
1834    }
1835
1836    {
1837        int x, y;
1838
1839        awmm->at("zoom");
1840        if (xoffset) { awmm->get_at_position(&x, &y); awmm->at(x+xoffset, y); }
1841        awmm->callback(ED4_zoom_message_window);
1842        awmm->create_button("ZOOM", "#edit/zoom.xpm");
1843
1844        awmm->at("clear");
1845        if (xoffset) { awmm->get_at_position(&x, &y); awmm->at(x+xoffset, y); }
1846        awmm->callback(aw_clear_message_cb);
1847        awmm->create_button("CLEAR", "#edit/clear.xpm");
1848
1849        awmm->at("errortext");
1850        if (xoffset) { awmm->get_at_position(&x, &y); awmm->at(x+xoffset, y); }
1851        aw_root->awar_string(AWAR_ERROR_MESSAGES, "This is ARB Edit4 [Build " ARB_VERSION "]");
1852        awmm->create_text_field(AWAR_ERROR_MESSAGES);
1853        aw_set_local_message();
1854    }
1855
1856    // ---------------------
1857    //      'more' area
1858
1859    awmm->at("cons");
1860    awmm->create_toggle(ED4_AWAR_CONSENSUS_SHOW, "#edit/nocons.xpm", "#edit/cons.xpm");
1861
1862    awmm->at("num");
1863    awmm->create_toggle(ED4_AWAR_DIGITS_AS_REPEAT, "#edit/norepeat.xpm", "#edit/repeat.xpm");
1864
1865    awmm->at("key");
1866    awmm->create_toggle("key_mapping/enable", "#edit/nokeymap.xpm", "#edit/keymap.xpm");
1867
1868    // search
1869
1870    awmm->button_length(0);
1871#define INSERT_SEARCH_FIELDS(Short, label_prefix, prefix)       \
1872    insert_search_fields(awmm,                                  \
1873                         #label_prefix,                         \
1874                         #prefix,                               \
1875                         ED4_AWAR_##prefix##_SEARCH_PATTERN,    \
1876                         ED4_AWAR_##prefix##_SEARCH_SHOW,       \
1877                         Short,                                 \
1878                         ED4_##prefix##_PATTERN,                \
1879                         current_ed4w()                         \
1880        )
1881
1882    INSERT_SEARCH_FIELDS(0, u1, USER1);
1883    INSERT_SEARCH_FIELDS(0, u2, USER2);
1884    INSERT_SEARCH_FIELDS(0, pro, PROBE);
1885    INSERT_SEARCH_FIELDS(1, pri1, PRIMER1);
1886    INSERT_SEARCH_FIELDS(1, pri2, PRIMER2);
1887    INSERT_SEARCH_FIELDS(1, pri3, PRIMER3);
1888    INSERT_SEARCH_FIELDS(1, sig1, SIG1);
1889    INSERT_SEARCH_FIELDS(1, sig2, SIG2);
1890    INSERT_SEARCH_FIELDS(1, sig3, SIG3);
1891
1892#undef INSERT_SEARCH_FIELDS
1893
1894    awmm->at("alast");
1895    awmm->callback(makeWindowCallback(ED4_search_cb, ED4_encodeSearchDescriptor(-1, ED4_ANY_PATTERN), current_ed4w()));
1896    awmm->create_button("ALL_SEARCH_LAST", "#edit/last.xpm");
1897
1898    awmm->at("anext");
1899    awmm->callback(makeWindowCallback(ED4_search_cb, ED4_encodeSearchDescriptor(+1, ED4_ANY_PATTERN), current_ed4w()));
1900    awmm->create_button("ALL_SEARCH_NEXT", "#edit/next.xpm");
1901
1902    title_mode_changed(aw_root, awmm);
1903
1904    // Buttons at left window border
1905
1906    awmm->create_mode("edit/arrow.xpm", "e4_mode.hlp", AWM_ALL, makeWindowCallback(modes_cb, ED4_SM_MOVE));
1907    awmm->create_mode("edit/kill.xpm",  "e4_mode.hlp", AWM_ALL, makeWindowCallback(modes_cb, ED4_SM_KILL));
1908    awmm->create_mode("edit/mark.xpm",  "e4_mode.hlp", AWM_ALL, makeWindowCallback(modes_cb, ED4_SM_MARK));
1909    awmm->create_mode("mode_info.xpm",  "e4_mode.hlp", AWM_ALL, makeWindowCallback(modes_cb, ED4_SM_INFO));
1910
1911    FastAligner_create_variables(awmm->get_root(), props_db);
1912
1913#if defined(DEBUG)
1914    AWT_check_action_ids(awmm->get_root(), "");
1915#endif
1916
1917    announce_useraction_in(awmm);
1918
1919    return ED4_R_OK;
1920}
1921
1922AW_window *ED4_root::create_first_window() {
1923    // Note: other windows are generated by generate_window
1924    AW_device  *device     = NULp;
1925    ED4_window *new_window = NULp;
1926
1927    generate_window(&device, &new_window);
1928
1929    ED4_LocalWinContext uses(new_window);
1930
1931    ED4_calc_terminal_extentions(); // (Note: done again later, but otherwise variables are used uninitialized);
1932
1933    DRAW                    = 1;
1934    max_seq_terminal_length = 0;
1935
1936    ED4_init_notFoundMessage();
1937
1938    return new_window->aww;
1939}
1940
1941ED4_index ED4_root::pixel2pos(AW_pos click_x) {
1942    // 'click_x' is the x-offset into the terminal in pixels
1943    // returns the x-offset into the terminal in base positions (clipped to max. allowed position)
1944
1945    int       length_of_char = font_group.get_width(ED4_G_SEQUENCES);
1946    ED4_index scr_pos        = int((click_x-CHARACTEROFFSET) / length_of_char);
1947    int       max_scrpos     = root_group_man->remap()->get_max_screen_pos();
1948
1949    if (scr_pos>max_scrpos) scr_pos = max_scrpos;
1950
1951    return scr_pos;
1952}
1953
1954inline char *detectProperties(GBDATA *gb_main) {
1955    char *propname = NULp;
1956
1957    // check if edit4_?na.arb / edit4_ali_???.arb exist in $ARB_PROP
1958    for (int mode = 0; !propname && mode <= 1; ++mode) {
1959        const char *fullprop = GB_path_in_arbprop(propertyName(gb_main, mode));
1960        if (GB_is_regularfile(fullprop)) {
1961            freedup(propname, fullprop);
1962        }
1963    }
1964
1965    // if not, use 'mode 2', i.e. "edit4.arb"
1966    // (no full path, we want to load default from arb_defaults)
1967    if (!propname) propname = ARB_strdup(propertyName(gb_main, 2));
1968
1969    return propname;
1970}
1971
1972ED4_root::ED4_root(GBDATA *gb_main_)
1973    : most_recently_used_window(NULp),
1974      cons_param(NULp),
1975      gb_main(gb_main_),
1976      alignment_name(NULp),
1977      db_name(detectProperties(gb_main)),
1978      aw_root(AWT_create_root(db_name, "ARB_EDIT4", need_macro_ability())),
1979      props_db(AW_ROOT_DEFAULT),
1980      first_window(NULp),
1981      main_manager(NULp),
1982      middle_area_man(NULp),
1983      top_area_man(NULp),
1984      root_group_man(NULp),
1985      highlighted_objects(new ED4_highlighted_list),
1986      folding_action(false),
1987      species_mode(ED4_SM_MOVE),
1988      ecoli_ref(NULp),
1989      alignment_type(GB_AT_UNKNOWN),
1990      reference(NULp),
1991      sequence_colors(NULp),
1992      gc_manager(NULp),
1993      st_ml(NULp),
1994      helix(NULp),
1995      helix_spacing(0),
1996      helix_add_spacing(0),
1997      terminal_add_spacing(0),
1998      protstruct(NULp),
1999      protstruct_len(0),
2000      edk(NULp),
2001      column_stat_activated(false),
2002      column_stat_initialized(false),
2003      visualizeSAI(false),
2004      visualizeSAI_allSpecies(false),
2005      loadable_SAIs(LSAI_UNUSED),
2006      temp_gc(0)
2007{}
2008
2009
2010ED4_root::~ED4_root() {
2011    delete aw_root;
2012    delete first_window;
2013    delete reference; // needs to be deleted before main_manager (to ensure reference callbacks are removed)
2014    delete main_manager; // also deletes middle_area_man + top_area_man
2015    delete ecoli_ref;
2016    delete highlighted_objects;
2017    delete helix;
2018    delete sequence_colors;
2019    delete edk;
2020    STAT_destroy_ST_ML(st_ml);
2021
2022    free(protstruct);
2023    free(db_name);
2024    free(alignment_name);
2025}
Note: See TracBrowser for help on using the repository browser.