root/trunk/EDIT4/ED4_root.cxx

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