source: trunk/EDIT4/ED4_terminal.cxx

Last change on this file was 19218, checked in by westram, 2 years ago
  • rename "select" → "highlight" (part II)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 48.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ED4_terminal.cxx                                  //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include <ed4_extern.hxx>
12#include "ed4_class.hxx"
13#include "ed4_awars.hxx"
14#include "ed4_edit_string.hxx"
15#include "ed4_block.hxx"
16#include "ed4_nds.hxx"
17#include "ed4_ProteinViewer.hxx"
18#include "ed4_seq_colors.hxx"
19#include "ed4_flags.hxx"
20
21#include <arbdbt.h>
22#include <items.h>
23
24#include <aw_preset.hxx>
25#include <aw_awar.hxx>
26#include <aw_awar_defs.hxx>
27#include <aw_msg.hxx>
28#include <aw_root.hxx>
29#include <aw_question.hxx>
30
31#include <st_window.hxx>
32
33// -----------------------------------
34//      static terminal properties
35
36static ED4_objspec tree_terminal_spec(
37    PROP_IS_TERMINAL,  // static props
38    LEV_TREE,           // level
39    LEV_NONE,           // allowed children level
40    LEV_NONE,           // handled object
41    LEV_NONE            // restriction level
42    );
43
44static ED4_objspec bracket_terminal_spec(
45    PROP_IS_TERMINAL,  // static props
46    LEV_BRACKET,        // level
47    LEV_NONE,           // allowed children level
48    LEV_NONE,           // handled object
49    LEV_NONE            // restriction level
50    );
51
52static ED4_objspec species_name_terminal_spec(
53    ED4_properties(PROP_IS_TERMINAL | PROP_DYNA_RESIZE),  // static props
54    LEV_SPECIES_NAME,   // level
55    LEV_NONE,           // allowed children level
56    LEV_SPECIES,        // handled object
57    LEV_NONE            // restriction level
58    );
59
60static ED4_objspec flag_header_spec(
61    ED4_properties(PROP_IS_TERMINAL | PROP_DYNA_RESIZE),  // static props
62    LEV_FLAG_HEADER,    // level
63    LEV_NONE,           // allowed children level
64    LEV_NONE,           // handled object
65    LEV_NONE            // restriction level
66    );
67
68static ED4_objspec flag_spec(
69    ED4_properties(PROP_IS_TERMINAL | PROP_DYNA_RESIZE), // static props
70    LEV_FLAG,           // level
71    LEV_NONE,           // allowed children level
72    LEV_NONE,           // handled object
73    LEV_NONE            // restriction level
74    );
75
76static ED4_objspec sequence_info_terminal_spec(
77    ED4_properties(PROP_IS_TERMINAL | PROP_DYNA_RESIZE),  // static props
78    LEV_SEQUENCE_INFO,  // level
79    LEV_NONE,           // allowed children level
80    LEV_SEQUENCE,       // handled object
81    LEV_NONE            // restriction level
82    );
83
84static ED4_objspec sequence_terminal_spec(
85    PROP_IS_TERMINAL,     // static props
86    LEV_SEQUENCE_STRING,   // level
87    LEV_NONE,              // allowed children level
88    LEV_NONE,              // handled object
89    LEV_NONE               // restriction level
90    );
91
92static ED4_objspec orf_terminal_spec(
93    PROP_IS_TERMINAL,     // static props
94    LEV_ORF,               // level
95    LEV_NONE,              // allowed children level
96    LEV_NONE,              // handled object
97    LEV_NONE               // restriction level
98    );
99
100static ED4_objspec pure_text_terminal_spec(
101    PROP_IS_TERMINAL,     // static props
102    LEV_PURE_TEXT,         // level
103    LEV_NONE,              // allowed children level
104    LEV_NONE,              // handled object
105    LEV_NONE               // restriction level
106    );
107
108static ED4_objspec spacer_terminal_spec(
109    ED4_properties(PROP_IS_TERMINAL | PROP_DYNA_RESIZE), // static props
110    LEV_SPACER,            // level
111    LEV_NONE,              // allowed children level
112    LEV_NONE,              // handled object
113    LEV_NONE               // restriction level
114    );
115
116static ED4_objspec line_terminal_spec(
117    ED4_properties(PROP_IS_TERMINAL | PROP_DYNA_RESIZE), // static props
118    LEV_LINE,              // level
119    LEV_NONE,              // allowed children level
120    LEV_NONE,              // handled object
121    LEV_NONE               // restriction level
122    );
123
124static ED4_objspec column_stat_terminal_spec(
125    PROP_IS_TERMINAL,     // static props
126    LEV_COL_STAT,          // level
127    LEV_NONE,              // allowed children level
128    LEV_NONE,              // handled object
129    LEV_NONE               // restriction level
130    );
131
132
133char *ED4_terminal::resolve_pointer_to_string_copy(int *str_len) const {
134    int         len;
135    const char *s = resolve_pointer_to_char_pntr(&len);
136    char       *t = ARB_strduplen(s, len); // space for zero byte is allocated by ARB_strduplen
137
138    if (str_len) *str_len = len;
139    return t;
140}
141
142const char *ED4_terminal::resolve_pointer_to_char_pntr(int *str_len) const {
143    const char *result     = NULp;
144    GBDATA     *gbd        = get_species_pointer();
145    bool        detect_len = true;
146
147    if (!gbd) {
148        result = id; // if we don't have a link to the database we (have to) use our id
149    }
150    else {
151        GB_transaction ta(ED4_ROOT->get_gb_main());
152
153        switch (GB_read_type(gbd)) {
154            case GB_STRING:
155                result = GB_read_char_pntr(gbd);
156                if (str_len) {
157                    *str_len   = GB_read_string_count(gbd);
158                    detect_len = false;
159                }
160                break;
161            case GB_BITS:
162                result = GB_read_bits_pntr(gbd, '.', '+');
163                if (str_len) {
164                    *str_len = GB_read_bits_count(gbd);
165                    detect_len = false;
166                }
167                break;
168            case GB_BYTES:
169                result = GB_read_bytes_pntr(gbd);
170                if (str_len) {
171                    *str_len = GB_read_bytes_count(gbd);
172                    detect_len = false;
173                }
174                break;
175
176            case GB_DB:     result = "GB_DB";     break;
177            case GB_INT:    result = "GB_INT";    break;
178            case GB_INTS:   result = "GB_INTS";   break;
179            case GB_FLOAT:  result = "GB_FLOAT";  break;
180            case GB_FLOATS: result = "GB_FLOATS"; break;
181
182            default:
183                result = "Unknown data type\n";
184                e4_assert(0);
185                break;
186        }
187    }
188
189    if (str_len) {
190        if (detect_len) {
191            *str_len = result ? strlen(result) : 0;
192        }
193        else {
194            e4_assert(*str_len == (int)strlen(result));
195        }
196    }
197
198    return result;
199}
200
201GB_ERROR ED4_terminal::write_sequence(const char *seq, int seq_len) {
202    GB_ERROR  err = NULp;
203    GBDATA   *gbd = get_species_pointer();
204    e4_assert(gbd); // we must have a link to the database!
205
206    GBDATA *gb_main = ED4_ROOT->get_gb_main();
207    GB_push_transaction(gb_main);
208
209    int   old_seq_len;
210    char *old_seq = resolve_pointer_to_string_copy(&old_seq_len);
211
212    bool allow_write_data = true;
213    if (ED4_ROOT->aw_root->awar(ED4_AWAR_ANNOUNCE_CHECKSUM_CHANGES)->read_int()) {
214        long old_checksum = GBS_checksum(old_seq, 1, "-.");
215        long new_checksum = GBS_checksum(seq, 1, "-.");
216
217        if (old_checksum != new_checksum) {
218            if (aw_question(NULp, "Checksum changed!", "Allow, Reject") == 1) {
219                allow_write_data = false;
220            }
221
222        }
223    }
224
225    if (allow_write_data) {
226        GB_TYPES gb_type = GB_read_type(gbd);
227        switch (gb_type) {
228            case GB_STRING: {
229                err = GB_write_string(gbd, seq);
230                break;
231            }
232            case GB_BITS: {
233                err = GB_write_bits(gbd, seq, seq_len, ".-");
234                break;
235            }
236            default: {
237                e4_assert(0);
238                break;
239            }
240        }
241    }
242
243    GB_pop_transaction(gb_main);
244
245    if (!err && has_property(PROP_CONSENSUS_RELEVANT)) {
246        if (old_seq) {
247            curr_timestamp = GB_read_clock(gb_main);
248
249            get_parent(LEV_MULTI_SPECIES)->to_multi_species_manager()
250                ->update_bases_and_rebuild_consensi(old_seq, old_seq_len, get_parent(LEV_SPECIES)->to_species_manager(), ED4_U_UP); // bases_check
251        }
252        else {
253            aw_message("Couldn't read old sequence data");
254        }
255
256        request_refresh();
257    }
258
259    if (old_seq) free(old_seq);
260
261    return err;
262}
263
264
265void ED4_terminal::remove_callbacks() {
266    if (get_species_pointer()) {
267        set_species_pointer(NULp);
268        tflag.deleted = 1; // @@@ why ?
269        clr_property(PROP_CURSOR_ALLOWED);
270        request_refresh();
271    }
272}
273
274#if 0
275static ARB_ERROR ed4_remove_species_manager_callbacks(ED4_base *base) { // @@@ unused since [8286]
276    if (base->is_species_manager()) {
277        base->to_species_manager()->remove_all_callbacks();
278    }
279    return NULp;
280}
281#endif
282
283inline void remove_from_consensus(ED4_manager *group_or_species_man) {
284    GB_transaction ta(ED4_ROOT->get_gb_main());
285    ED4_manager *parent_manager = group_or_species_man->parent;
286    parent_manager->update_consensus(parent_manager, NULp, group_or_species_man);
287    parent_manager->rebuild_consensi(parent_manager, ED4_U_UP);
288}
289
290ED4_returncode ED4_terminal::kill_object() {
291    ED4_species_manager *species_manager = get_parent(LEV_SPECIES)->to_species_manager();
292
293    if (species_manager->is_consensus_manager()) { // kill whole group
294        if (ED4_find_MoreSequences_manager()==species_manager->parent) {
295            aw_message("This group has to exist - deleting it isn't allowed");
296            return ED4_R_IMPOSSIBLE;
297        }
298
299        ED4_manager *group_manager = species_manager->get_parent(LEV_GROUP)->to_group_manager();
300        remove_from_consensus(group_manager);
301        group_manager->Delete();
302    }
303    else { // kill single species/SAI
304        remove_from_consensus(species_manager);
305        species_manager->Delete();
306    }
307
308    return ED4_R_OK;
309}
310
311ED4_returncode ED4_terminal::draw_drag_box(AW_pos x, AW_pos y, GB_CSTR text, int cursor_y) {
312    // draws drag box of object at location abs_x, abs_y
313
314    if (cursor_y!=-1) {
315        ED4_base *drag_target = NULp;
316        {
317            ED4_extension location;
318            location.position[X_POS] = 0;
319            location.position[Y_POS] = (AW_pos)cursor_y;           // cursor_y is already in world coordinates
320
321            ED4_ROOT->get_device_manager()->search_target_species(&location, PROP_HORIZONTAL, &drag_target, LEV_NONE);
322        }
323
324        if (drag_target) {
325            AW_pos target_x, target_y;
326
327            drag_target->calc_world_coords (&target_x, &target_y);
328            current_ed4w()->world_to_win_coords(&target_x, &target_y);
329
330#define ARROW_LENGTH 3
331            AW_pos drag_line_x0[3], drag_line_y0[3];
332            AW_pos drag_line_x1[3], drag_line_y1[3];
333
334            drag_line_x0[0] = target_x + 5;                                                 // horizontal
335            drag_line_y0[0] = target_y + drag_target->extension.size[HEIGHT];
336            drag_line_x1[0] = drag_line_x0[0] + 50;
337            drag_line_y1[0] = target_y + drag_target->extension.size[HEIGHT];
338
339            drag_line_x0[1] = drag_line_x0[0] -ARROW_LENGTH;                                // arrow
340            drag_line_y0[1] = drag_line_y0[0] -ARROW_LENGTH;
341            drag_line_x1[1] = drag_line_x0[0];
342            drag_line_y1[1] = drag_line_y0[0];
343
344            drag_line_x0[2] = drag_line_x0[0] -ARROW_LENGTH;                                // arrow
345            drag_line_y0[2] = drag_line_y0[0] + ARROW_LENGTH;
346            drag_line_x1[2] = drag_line_x0[0];
347            drag_line_y1[2] = drag_line_y0[0];
348#undef ARROW_LENGTH
349
350            for (ED4_index i = 0; i <= 2; i++) {
351                current_device()->line(ED4_G_DRAG, drag_line_x0[i], drag_line_y0[i], drag_line_x1[i], drag_line_y1[i], AW_SCREEN);
352            }
353        }
354    }
355
356    if (text) {
357        current_device()->text(ED4_G_DRAG, text, (x + 20), (y + INFO_TERM_TEXT_YOFFSET), 0, AW_SCREEN);
358    }
359
360    return ED4_R_OK;
361}
362
363void ED4_multi_species_manager::toggle_selected_species() {
364    if (all_are_selected()) deselect_all_species_and_SAI();
365    else select_all(false); // species and SAI
366
367    ED4_correctBlocktypeAfterModification();
368}
369
370#if defined(DEBUG) && 1
371static inline void dumpEvent(const char *where, AW_event *event) {
372    printf("%s: x=%i y=%i\n", where, event->x, event->y);
373}
374#else
375#define dumpEvent(w, e)
376#endif
377
378struct ED4_dragNdrop_info {
379    // contains data set by drag and used by drop.
380    AW_pos off_x, off_y;
381    AW_pos old_x, old_y;
382    int    old_event_y;
383};
384
385ED4_returncode ED4_terminal::event_sent_by_parent(AW_event *event, AW_window *aww) {
386    // handles an input event coming from parent
387
388    // static data to move terminal:
389    static ED4_species_name_terminal *dragged_name_terminal = NULp;
390
391    static bool pressed_left_button  = false;
392    static int  other_x, other_y;                                    // coordinates of last event
393    static bool dragged_was_selected = false;                        // the dragged terminal is temp. added to selected
394
395    static ED4_dragNdrop_info drag; // sole instance (there is only one move at a time)
396
397    // ----------------------------
398    //      drag/drop terminal
399    if (dragged_name_terminal) {
400        if (event->button == AW_BUTTON_LEFT) {
401            switch (event->type) {
402                case AW_Mouse_Drag: {
403                    if (pressed_left_button) {
404                        AW_pos world_x, world_y;
405
406                        dragged_name_terminal->calc_world_coords(&world_x, &world_y);
407                        current_ed4w()->world_to_win_coords(&world_x, &world_y);
408
409                        drag.old_x = world_x;
410                        drag.old_y = world_y;
411                        drag.off_x = world_x-other_x;
412                        drag.off_y = world_y-other_y;
413                        drag.old_event_y = -1;
414
415                        pressed_left_button = false;
416                    }
417
418                    GB_CSTR text = dragged_name_terminal->get_displayed_text();
419
420                    if (dragged_name_terminal->dragged) {
421                        dragged_name_terminal->draw_drag_box(drag.old_x, drag.old_y, text, drag.old_event_y);
422                    }
423
424                    AW_pos new_x = drag.off_x + event->x;
425                    AW_pos new_y = drag.off_y + event->y;
426
427                    dragged_name_terminal->draw_drag_box(new_x, new_y, text, event->y); // @@@ event->y ist falsch, falls vertikal gescrollt ist!
428
429                    drag.old_x = new_x;
430                    drag.old_y = new_y;
431                    drag.old_event_y = event->y;
432
433                    dragged_name_terminal->dragged = true;
434                    break;
435                }
436                case AW_Mouse_Release: {
437                    if (dragged_name_terminal->dragged) {
438                        {
439                            char *db_pointer = dragged_name_terminal->resolve_pointer_to_string_copy();
440
441                            dragged_name_terminal->draw_drag_box(drag.old_x, drag.old_y, db_pointer, drag.old_event_y);
442                            dragged_name_terminal->dragged = false;
443
444                            free(db_pointer);
445                        }
446                        {
447                            ED4_move_info mi;
448
449                            mi.object = dragged_name_terminal;
450                            mi.end_x = event->x;
451                            mi.end_y = event->y;
452                            mi.mode = ED4_M_FREE;
453                            mi.preferred_parent = LEV_NONE;
454
455                            dragged_name_terminal->parent->move_requested_by_child(&mi);
456                        }
457                        {
458                            ED4_device_manager *device_manager = ED4_ROOT->get_device_manager();
459
460                            for (int i=0; i<device_manager->members(); i++) { // when moving species numbers have to be recalculated
461                                ED4_base *member = device_manager->member(i);
462
463                                if (member->is_area_manager()) {
464                                    member->to_area_manager()->get_multi_species_manager()->update_requested_by_child();
465                                }
466                            }
467                        }
468                    }
469                    if (!dragged_was_selected) {
470                        ED4_ROOT->remove_from_highlighted(dragged_name_terminal);
471                    }
472
473                    pressed_left_button   = false;
474                    dragged_name_terminal = NULp;
475                    break;
476                }
477                default:
478                    break;
479            }
480        }
481    }
482    else {
483        switch (event->button) {
484            case AW_BUTTON_LEFT: {
485                if (is_species_name_terminal()) {
486                    switch (ED4_ROOT->species_mode) {
487                        case ED4_SM_KILL: {
488                            if (event->type == AW_Mouse_Press) {
489                                if (containing_species_manager()->is_highlighted()) ED4_ROOT->remove_from_highlighted(this->to_species_name_terminal());
490                                kill_object();
491                                return ED4_R_BREAK;
492                            }
493                            break;
494                        }
495                        case ED4_SM_MOVE: {
496                            if (event->type == AW_Mouse_Press) {
497                                dragged_name_terminal = to_species_name_terminal();
498                                pressed_left_button   = true;
499
500                                other_x = event->x;
501                                other_y = event->y;
502
503                                dragged_was_selected = containing_species_manager()->is_highlighted();
504                                if (!dragged_was_selected) {
505                                    ED4_ROOT->add_to_highlighted(dragged_name_terminal);
506                                    ED4_trigger_instant_refresh();
507                                }
508                            }
509                            break;
510                        }
511                        case ED4_SM_INFO:
512                        case ED4_SM_MARK: {
513                            static ED4_species_manager *prev_clicked_species_man = NULp;
514                            ED4_species_manager        *species_man              = get_parent(LEV_SPECIES)->to_species_manager();
515
516                            GBDATA *gbd = species_man->get_species_pointer();
517                            if (gbd) {
518                                bool       acceptClick = false;
519                                static int markHow     = -1;  // -1=invert, 0=unmark, 1=mark
520                                {
521                                    switch (event->type) {
522                                        case AW_Mouse_Press:
523                                            acceptClick = true;
524                                            markHow     = -1;
525                                            break;
526
527                                        case AW_Mouse_Drag:
528                                            acceptClick = prev_clicked_species_man != species_man;
529                                            break;
530
531                                        case AW_Mouse_Release:
532                                            acceptClick              = prev_clicked_species_man != species_man;
533                                            prev_clicked_species_man = NULp;
534                                            break;
535
536                                        case AW_Keyboard_Press:
537                                        case AW_Keyboard_Release:
538                                            e4_assert(0); // impossible
539                                            break;
540                                    }
541                                }
542
543                                if (acceptClick) {
544                                    if (ED4_ROOT->species_mode == ED4_SM_MARK) {
545                                        if (markHow<0) markHow = !GB_read_flag(gbd);
546                                        GB_write_flag(gbd, markHow);
547                                        request_refresh();
548                                        if (ED4_ROOT->alignment_type ==  GB_AT_DNA) PV_RefreshWindow(aww->get_root()); // ProtView: Refreshing orf terminals (@@@ weird place to perform refresh)
549                                    }
550                                    else {
551                                        e4_assert(ED4_ROOT->species_mode == ED4_SM_INFO);
552
553                                        const char *name = GBT_get_name(gbd);
554                                        if (name) {
555                                            const char *awar_select = species_man->inside_SAI_manager() ? AWAR_SAI_NAME : AWAR_SPECIES_NAME;
556                                            ED4_ROOT->aw_root->awar(awar_select)->write_string(name);
557                                        }
558                                    }
559                                    prev_clicked_species_man = species_man;
560                                }
561                            }
562                            else {
563                                prev_clicked_species_man = NULp;
564                            }
565                            break;
566                        }
567                    }
568                }
569                else if (is_bracket_terminal()) { // fold/unfold group
570                    if (event->type == AW_Mouse_Press) {
571                        to_bracket_terminal()->toggle_folding();
572                    }
573                }
574                else if (is_sequence_terminal()) {
575                    if (has_property(PROP_CURSOR_ALLOWED)) {
576                        ED4_no_dangerous_modes();
577                        current_cursor().show_clicked_cursor(event->x, this);
578                    }
579                }
580                else if (is_flag_terminal()) {
581                    if (event->type == AW_Mouse_Press) {
582                        to_flag_terminal()->handle_left_click(current_ed4w()->world_to_win_coords(AW::Position(event->x, event->y)));
583                    }
584                }
585
586                break;
587            }
588            case AW_BUTTON_RIGHT: {
589                // static data for block-selection:
590                static bool select_started_on_seqterm = false;
591
592                switch (event->type) {
593                    case AW_Mouse_Press: {
594                        select_started_on_seqterm = false;
595                        if (is_species_name_terminal()) {
596                            ED4_species_manager *species_man = get_parent(LEV_SPECIES)->to_species_manager();
597
598                            if (species_man->is_consensus_manager()) { // click on consensus-name
599                                ED4_multi_species_manager *multi_man = species_man->get_parent(LEV_MULTI_SPECIES)->to_multi_species_manager();
600                                multi_man->toggle_selected_species();
601                            }
602                            else { // click on species or SAI name
603                                if (!species_man->is_highlighted()) { // select if not selected
604                                    if (ED4_ROOT->add_to_highlighted(this->to_species_name_terminal()) == ED4_R_OK) ED4_correctBlocktypeAfterModification();
605                                }
606                                else { // deselect if already selected
607                                    ED4_ROOT->remove_from_highlighted(this->to_species_name_terminal());
608                                    ED4_correctBlocktypeAfterModification();
609                                }
610                            }
611                        }
612                        else if (is_bracket_terminal()) {
613                            ED4_base *group = get_parent(LEV_GROUP);
614                            if (group) {
615                                group->to_group_manager()->get_multi_species_manager()->toggle_selected_species();
616                            }
617                        }
618                        else if (is_sequence_terminal()) {
619                            ED4_no_dangerous_modes();
620                            ED4_setColumnblockCorner(event, to_sequence_terminal()); // mark columnblock
621                            select_started_on_seqterm = true;
622                        }
623                        break;
624                    }
625
626                    case AW_Mouse_Drag:
627                    case AW_Mouse_Release:
628                        if (select_started_on_seqterm && is_sequence_terminal()) {
629                            ED4_no_dangerous_modes();
630                            ED4_setColumnblockCorner(event, to_sequence_terminal()); // mark columnblock
631                        }
632                        break;
633
634                    default:
635                        break;
636                }
637                break;
638            }
639
640            default: break;
641        }
642    }
643
644    return ED4_R_OK;
645}
646
647void ED4_terminal::update_requested_children() {}
648
649bool ED4_terminal::calc_bounding_box() {
650    // calculates the smallest rectangle containing the object.
651    // requests refresh and returns true if bounding box has changed.
652
653    bool bb_changed = false;
654
655    if (width_link) {
656        bb_changed = extension.set_size_does_change(WIDTH, width_link->extension.size[WIDTH]) || bb_changed;
657    }
658
659    if (height_link) {
660        bb_changed = extension.set_size_does_change(HEIGHT, height_link->extension.size[HEIGHT]) || bb_changed;
661    }
662
663
664    if (bb_changed) {
665        request_resize_of_linked();
666        request_refresh();
667    }
668    return bb_changed;
669}
670
671void ED4_terminal::resize_requested_children() {
672    if (update_info.resize) { // likes to resize?
673        if (calc_bounding_box()) request_resize();
674    }
675}
676
677
678void ED4_terminal::request_refresh(int clear) {
679    update_info.set_refresh(1);
680    update_info.set_clear_at_refresh(clear);
681    if (parent) parent->refresh_requested_by_child();
682}
683
684
685ED4_base* ED4_terminal::search_ID(const char *temp_id) {
686    if (id && strcmp(temp_id, id) == 0) return this;
687    return NULp;
688}
689
690void ED4_terminal::Show(bool IF_ASSERTION_USED(refresh_all), bool is_cleared) {
691    e4_assert(update_info.refresh || refresh_all);
692    current_device()->push_clip_scale();
693    if (adjust_clipping_rectangle()) {
694        if (update_info.clear_at_refresh && !is_cleared) {
695            clear_background();
696        }
697        draw();
698    }
699    current_device()->pop_clip_scale();
700}
701
702ED4_terminal::ED4_terminal(const ED4_objspec& spec_, GB_CSTR temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
703    ED4_base(spec_, temp_id, width, height, temp_parent)
704{
705    memset((char*)&tflag, 0, sizeof(tflag));
706    curr_timestamp = 0;
707}
708
709
710ED4_terminal::~ED4_terminal() {
711    for (ED4_window *window = ED4_ROOT->first_window; window; window=window->next) {
712        ED4_cursor& cursor = window->cursor;
713        if (this == cursor.owner_of_cursor) {
714            cursor.init();
715        }
716    }
717}
718
719ED4_tree_terminal::ED4_tree_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
720    : ED4_terminal(tree_terminal_spec, temp_id, width, height, temp_parent)
721{}
722
723void ED4_tree_terminal::draw() {
724    AW_pos  x, y;
725    AW_pos  text_x, text_y;
726    char   *db_pointer;
727
728    calc_world_coords(&x, &y);
729    current_ed4w()->world_to_win_coords(&x, &y);
730
731    text_x = x + CHARACTEROFFSET;                           // don't change
732    text_y = y + SEQ_TERM_TEXT_YOFFSET;
733
734    db_pointer = resolve_pointer_to_string_copy();
735    current_device()->text(ED4_G_STANDARD, db_pointer, text_x, text_y, 0, AW_SCREEN);
736    free(db_pointer);
737}
738
739ED4_bracket_terminal::ED4_bracket_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
740    : ED4_terminal(bracket_terminal_spec, temp_id, width, height, temp_parent)
741{}
742
743void ED4_bracket_terminal::draw() {
744    using namespace AW;
745
746    Rectangle  term_area = get_win_area(current_ed4w());
747    AW_device *device    = current_device();
748
749    ED4_multi_species_manager *multi_man = get_parent(LEV_GROUP)->to_group_manager()->get_multi_species_manager();
750    if (multi_man->get_no_of_selected_species()) {  // if multi_species_manager contains selected species
751#if defined(DEBUG) && 0
752        static bool toggle = false;
753        toggle             = !toggle;
754        device->box(toggle ? ED4_G_SELECTED : ED4_G_SELECTED+1, AW::FillStyle::SOLID, term_area);
755#else // !defined(DEBUG)
756        device->box(ED4_G_SELECTED, AW::FillStyle::SOLID, term_area);
757#endif
758    }
759
760    e4_assert(parent->is_group_manager());
761    if (parent->has_property(PROP_IS_FOLDED)) { // for folded group, paint triangle pointing rightwards
762        Position t = term_area.upper_left_corner()+Vector(4,4);
763        Position b = t+Vector(0,12);
764
765        for (int i = 0; i<6; ++i) {
766            device->line(ED4_G_STANDARD, t, b, AW_SCREEN);
767            t += Vector(1,  1);
768            b += Vector(1, -1);
769        }
770        e4_assert(nearlyEqual(t, b));
771        device->line(ED4_G_STANDARD, t, b, AW_SCREEN); // arrowhead
772    }
773    else { // for unfolded group, paint triangle pointing downwards
774        Position l = term_area.upper_left_corner()+Vector(4,5);
775        Position r = l+Vector(6,0);
776
777        for (int i = 0; i<3; ++i) {
778            device->line(ED4_G_STANDARD, l, r, AW_SCREEN);
779            l += Vector( 0, 1);
780            r += Vector( 0, 1);
781            device->line(ED4_G_STANDARD, l, r, AW_SCREEN);
782            l += Vector( 1, 1);
783            r += Vector(-1, 1);
784        }
785        e4_assert(nearlyEqual(l, r));
786        device->line(ED4_G_STANDARD, l, r+Vector(0,1), AW_SCREEN); // arrowhead
787    }
788
789    {
790        Rectangle bracket(term_area.upper_left_corner()+Vector(2,2), term_area.diagonal()+Vector(-2,-4));
791
792        device->line(ED4_G_STANDARD, bracket.upper_edge(), AW_SCREEN);
793        device->line(ED4_G_STANDARD, bracket.lower_edge(), AW_SCREEN);
794        device->line(ED4_G_STANDARD, bracket.left_edge(), AW_SCREEN);
795    }
796}
797
798ED4_species_name_terminal::ED4_species_name_terminal(GB_CSTR temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
799    ED4_text_terminal(species_name_terminal_spec, temp_id, width, height, temp_parent),
800    highlight_info(NULp),
801    dragged(false)
802{}
803
804#define MAXNAMELEN MAXNAME_WIDTH // @@@ seems wrong (MAXNAME_WIDTH contains pixel)
805#define BUFFERSIZE (MAXNAMELEN<<1)
806GB_CSTR ED4_species_name_terminal::get_displayed_text() const {
807    static char *real_name;
808    static int allocatedSize;
809
810    if (!real_name || allocatedSize<(BUFFERSIZE+1)) {
811        free(real_name);
812        allocatedSize = BUFFERSIZE+1;
813        ARB_alloc(real_name, allocatedSize);
814    }
815    memset(real_name, 0, allocatedSize);
816
817    ED4_species_manager *spec_man = get_parent(LEV_SPECIES)->to_species_manager();
818
819    if (spec_man->is_consensus_manager()) {
820        char *db_pointer = resolve_pointer_to_string_copy();
821        char *bracket = strchr(db_pointer, '(');
822
823        if (bracket) {
824            int bracket_len = strlen(bracket);
825            int name_len = bracket-db_pointer;
826
827            if (bracket[-1]==' ') {
828                name_len--;
829            }
830
831            if ((name_len+1+bracket_len)<=MAXNAMELEN) {
832                strcpy(real_name, db_pointer);
833            }
834            else {
835                int short_name_len = MAXNAMELEN-bracket_len-1;
836
837                memcpy(real_name, db_pointer, short_name_len);
838                real_name[short_name_len] = ' ';
839                strcpy(real_name+short_name_len+1, bracket);
840            }
841        }
842        else {
843            strncpy(real_name, db_pointer, BUFFERSIZE);
844        }
845
846        free(db_pointer);
847    }
848    else if (spec_man->is_SAI_manager()) {
849        char *db_pointer = resolve_pointer_to_string_copy();
850
851        strcpy(real_name, "SAI: ");
852        if (strcmp(db_pointer, "ECOLI")==0) {
853            const char *name_for_ecoli = ED4_ROOT->aw_root->awar(ED4_AWAR_NDS_ECOLI_NAME)->read_char_pntr();
854            if (name_for_ecoli[0]==0) name_for_ecoli = db_pointer;
855            strncpy(real_name+5, name_for_ecoli, BUFFERSIZE-5);
856        }
857        else {
858            strncpy(real_name+5, db_pointer, BUFFERSIZE-5);
859        }
860        free(db_pointer);
861    }
862    else { // normal species
863        char *result = ED4_get_NDS_text(spec_man);
864        strncpy(real_name, result, BUFFERSIZE);
865        free(result);
866    }
867
868    return real_name;
869}
870#undef MAXNAMELEN
871#undef BUFFERSIZE
872
873
874ED4_sequence_info_terminal::ED4_sequence_info_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
875    : ED4_text_terminal(sequence_info_terminal_spec, temp_id, width, height, temp_parent)
876{}
877
878ED4_consensus_sequence_terminal::ED4_consensus_sequence_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
879    : ED4_sequence_terminal(temp_id, width, height, temp_parent, false),
880      temp_cons_seq(NULp)
881{
882    species_name = NULp;
883}
884
885int ED4_consensus_sequence_terminal::get_length() const {
886    return get_char_table().size();
887}
888
889
890ED4_abstract_sequence_terminal::ED4_abstract_sequence_terminal(const ED4_objspec& spec_, const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
891    : ED4_text_terminal(spec_, temp_id, width, height, temp_parent)
892{
893    species_name = NULp;
894}
895
896ED4_abstract_sequence_terminal::~ED4_abstract_sequence_terminal() {
897    free(species_name);
898}
899
900ED4_orf_terminal::ED4_orf_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
901    : ED4_abstract_sequence_terminal(orf_terminal_spec, temp_id, width, height, temp_parent)
902{
903    aaSequence   = NULp;
904    aaSeqLen     = 0;
905    aaColor      = NULp;
906    aaStartPos   = 0;
907    aaStrandType = 0;
908}
909
910ED4_orf_terminal::~ED4_orf_terminal() {
911    free(aaSequence);
912    free(aaColor);
913}
914
915ED4_sequence_terminal::ED4_sequence_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent, bool shall_display_secstruct_info_)
916    : ED4_abstract_sequence_terminal(sequence_terminal_spec, temp_id, width, height, temp_parent),
917      shall_display_secstruct_info(shall_display_secstruct_info_)
918{
919    st_ml_node = NULp;
920}
921
922ED4_pure_text_terminal::ED4_pure_text_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
923    : ED4_text_terminal(pure_text_terminal_spec, temp_id, width, height, temp_parent)
924{}
925
926#if defined(DEVEL_RALF) && 0
927// # define DEBUG_SPACER_TERMINALS 0 // show placeholder-spacers (normally not drawn)
928// # define DEBUG_SPACER_TERMINALS 1 // show erasing spacers (normally area gets erased)
929# define DEBUG_SPACER_TERMINALS 2 // show all spacers
930#endif
931
932void ED4_spacer_terminal::Show(bool /*refresh_all*/, bool is_cleared) {
933#if defined(DEBUG_SPACER_TERMINALS)
934    if (DEBUG_SPACER_TERMINALS == 1) {
935        if (shallDraw) {
936            draw();
937        }
938        else if (update_info.clear_at_refresh && !is_cleared) {
939            clear_background(0);
940        }
941    }
942    else {
943        draw();
944    }
945#else // !DEBUG_SPACER_TERMINALS
946    if (shallDraw || (update_info.clear_at_refresh && !is_cleared)) {
947        draw();
948    }
949#endif
950}
951
952
953void ED4_spacer_terminal::draw() {
954    int gc = 0;
955#if defined(DEBUG_SPACER_TERMINALS)
956    const int GC_COUNT = ED4_G_LAST_COLOR_GROUP - ED4_G_FIRST_COLOR_GROUP + 1;
957    gc                 = ((long(this)/32)%GC_COUNT)+ED4_G_FIRST_COLOR_GROUP; // draw colored spacers to make them visible
958
959    if (DEBUG_SPACER_TERMINALS != 2) {
960        bool highlight     = bool(DEBUG_SPACER_TERMINALS) == shallDraw;
961        if (!highlight) gc = 0;
962    }
963#endif // DEBUG_SPACER_TERMINALS
964    clear_background(gc);
965}
966
967ED4_spacer_terminal::ED4_spacer_terminal(const char *temp_id, bool shallDraw_, AW_pos width, AW_pos height, ED4_manager *temp_parent)
968    : ED4_terminal(spacer_terminal_spec, temp_id, width, height, temp_parent),
969      shallDraw(shallDraw_)
970{
971    // 'shallDraw_'==true is only needed in very special cases,
972    // eg. for 'Top_Middle_Spacer' (to remove overlapping relicts from half-displayed species below)
973}
974
975void ED4_line_terminal::draw() {
976    AW_pos x1, y1;
977    calc_world_coords(&x1, &y1);
978    current_ed4w()->world_to_win_coords(&x1, &y1);
979
980    AW_pos x2 = x1+extension.size[WIDTH]-1;
981    AW_pos y2 = y1+extension.size[HEIGHT]-1;
982
983    AW_device *device = current_device();
984
985    device->line(ED4_G_STANDARD, x1, y1, x2, y1);
986#if defined(DEBUG)
987    device->box(ED4_G_MARKED, AW::FillStyle::SOLID, x1, y1+1, x2-x1+1, y2-y1-1);
988#else
989    device->clear_part(x1, y1+1, x2-x1+1, y2-y1-1, AW_ALL_DEVICES);
990#endif // DEBUG
991    device->line(ED4_G_STANDARD, x1, y2, x2, y2);
992}
993
994ED4_line_terminal::ED4_line_terminal(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
995    : ED4_terminal(line_terminal_spec, temp_id, width, height, temp_parent)
996{}
997
998// ---------------------------------
999//      ED4_columnStat_terminal
1000
1001inline char stat2display(int val, bool is_upper_digit) {
1002    if (val<0) {
1003        e4_assert(val==-1); // -1 indicates that no statistic is existing for that column
1004        return '?';
1005    }
1006    if (val==20) return ' '; // value if ACGT and - are distributed equally
1007    if (val==100) return '^'; // we have only 2 characters to display likelihood (100 cannot be displayed)
1008
1009    e4_assert(val>=0 && val<100);
1010
1011    return '0' + (is_upper_digit ? (val/10) : (val%10));
1012}
1013
1014inline int find_significant_positions(int sig, int like_A, int like_C, int like_G, int like_TU, int *sumPtr) {
1015    // result == 0      -> no base-char has a significant likelihood (>=sig)
1016    // result == 1, 2, 4, 8     -> A, C, G, T/U has a significant likelihood
1017    // else             -> the sum two of the likelihoods >= sig (bit-or-ed as in line above)
1018
1019    int like[4];
1020    like[0] = like_A;
1021    like[1] = like_C;
1022    like[2] = like_G;
1023    like[3] = like_TU;
1024
1025    int bestSum = 0;
1026    int bestResult = 0;
1027
1028    int b, c;
1029    for (b=0; b<4; b++) {
1030        int sum = like[b];
1031        if (sum>=sig && sum>=bestSum) {
1032            bestSum = sum;
1033            bestResult = 1<<b;
1034        }
1035    }
1036
1037    if (!bestResult) {
1038        for (b=0; b<4; b++) {
1039            for (c=b+1; c<4; c++) {
1040                int sum = like[b]+like[c];
1041                if (sum>=sig && sum>=bestSum) {
1042                    bestSum = sum;
1043                    bestResult = (1<<b)|(1<<c);
1044                }
1045            }
1046        }
1047    }
1048
1049    if (bestResult) {
1050        if (sumPtr) *sumPtr = bestSum;
1051        return bestResult;
1052    }
1053
1054    return 0;
1055}
1056
1057void ED4_columnStat_terminal::draw() {
1058    AW_pos x, y;
1059    calc_world_coords(&x, &y);
1060    current_ed4w()->world_to_win_coords(&x, &y);
1061
1062    AW_pos term_height = extension.size[HEIGHT];
1063    AW_pos font_height = ED4_ROOT->font_group.get_height(ED4_G_SEQUENCES);
1064    AW_pos font_width  = ED4_ROOT->font_group.get_width(ED4_G_SEQUENCES);
1065
1066    AW_pos text_x = x + CHARACTEROFFSET;
1067    AW_pos text_y = y + term_height - font_height;
1068
1069    AW_device *device = current_device();
1070
1071    if (!update_likelihood()) {
1072        const char *warning = "Failed to calculate likelihood";
1073
1074        device->text(ED4_G_STANDARD, warning, text_x, text_y, 0, AW_SCREEN);
1075        return;
1076    }
1077
1078    ED4_sequence_terminal *seq_term = corresponding_sequence_terminal();
1079    const ED4_remap       *rm       = ED4_ROOT->root_group_man->remap();
1080
1081    PosRange index_range = rm->clip_screen_range(seq_term->calc_update_interval());
1082    {
1083        int max_seq_len = seq_term->get_length();
1084        int max_seq_pos = rm->sequence_to_screen(max_seq_len);
1085
1086        index_range = ExplicitRange(index_range, max_seq_pos);
1087        if (index_range.is_empty()) return; // nothing to draw
1088    }
1089
1090    const int left  = index_range.start();
1091    const int right = index_range.end();
1092
1093    char *sbuffer = new char[right+2];  // used to build displayed terminal content  (values = '0'-'9')
1094    memset(sbuffer, ' ', right+1);
1095    sbuffer[right+1] = 0; // eos
1096
1097    AW_pos y2;
1098    int r;
1099
1100    // Set background:
1101    {
1102        int significance = int(get_threshold());
1103        // normal columns are colored in ED4_G_STANDARD
1104        // all columns with one (or sum of two) probability above 'significance' are back-colored in ED4_G_CBACK_0
1105        // the responsible probabilities (one or two) are back-colored in ED4_G_CBACK_1..ED4_G_CBACK_9
1106
1107        int old_color = ED4_G_STANDARD;
1108
1109        AW_pos x2     = text_x + font_width*left + 1;
1110        AW_pos old_x2 = x2;
1111
1112        PosRange selection;
1113        bool     is_selected = ED4_get_highlighted_range(seq_term, selection);
1114
1115        for (int i=left; i<=right; i++, x2+=font_width) { // colorize significant columns in ALL rows
1116            int p     = rm->screen_to_sequence(i);
1117            int found = find_significant_positions(significance, likelihood[0][p], likelihood[1][p], likelihood[2][p], likelihood[3][p], NULp);
1118
1119            int color;
1120            if (is_selected && selection.contains(p)) {
1121                color = ED4_G_SELECTED;
1122            }
1123            else {
1124                color = found ? ED4_G_CBACK_0 : ED4_G_STANDARD;
1125            }
1126
1127            if (color!=old_color) {
1128                if (x2>old_x2 && old_color!=ED4_G_STANDARD) {
1129                    device->box(old_color, AW::FillStyle::SOLID, old_x2, y, x2-old_x2, term_height);
1130                }
1131                old_color = color;
1132                old_x2 = x2;
1133            }
1134        }
1135        if (x2>old_x2 && old_color!=ED4_G_STANDARD) {
1136            device->box(old_color, AW::FillStyle::SOLID, old_x2, y, x2-old_x2, term_height);
1137        }
1138
1139        x2 = text_x + font_width*left + 1;
1140
1141        for (int i=left; i<=right; i++, x2+=font_width) { // colorize significant columns in SINGLE rows
1142            int p = rm->screen_to_sequence(i);
1143            int sum;
1144            int found = find_significant_positions(significance, likelihood[0][p], likelihood[1][p], likelihood[2][p], likelihood[3][p], &sum);
1145
1146            if (found && significance<100) {
1147                e4_assert(sum>=significance && sum<=100);
1148                int color = ED4_G_CBACK_1+((sum-significance)*(ED4_G_CBACK_9-ED4_G_CBACK_1))/(100-significance);
1149                e4_assert(color>=ED4_G_CBACK_1 && color<=ED4_G_CBACK_9);
1150
1151                if (color!=ED4_G_STANDARD) {
1152                    int bit;
1153
1154                    for (r=3, y2=text_y+1, bit=1<<3;
1155                         r>=0;
1156                         r--, y2-=COLUMN_STAT_ROW_HEIGHT(font_height), bit>>=1)
1157                    {
1158                        if (found&bit) {
1159                            device->box(color, AW::FillStyle::SOLID, x2, y2-2*font_height+1, font_width, 2*font_height);
1160                        }
1161                    }
1162                }
1163            }
1164        }
1165    }
1166
1167    // Draw text:
1168    for (r=3, y2=text_y;
1169         r>=0;
1170         r--, y2-=COLUMN_STAT_ROW_HEIGHT(font_height)) { // 4 rows (one for T/U, G, C and A)
1171
1172        int gc = ED4_ROOT->sequence_colors->char_2_gc[(unsigned char)"ACGU"[r]];
1173        int i;
1174        for (i=left; i<=right; i++) {
1175            int p = rm->screen_to_sequence(i);
1176            int val = likelihood[r][p];
1177            sbuffer[i] = stat2display(val, 0); // calc lower digit
1178        }
1179
1180        device->text(gc, SizedCstr(sbuffer, right), text_x+font_width*0.2, y2, 0, AW_SCREEN); // draw lower-significant digit (shifted a bit to the right)
1181
1182        for (i=left; i<=right; i++) {
1183            int p = rm->screen_to_sequence(i);
1184            int val = likelihood[r][p];
1185            sbuffer[i] = stat2display(val, 1); // calc upper digit
1186        }
1187        device->text(gc, SizedCstr(sbuffer, right), text_x, y2-font_height, 0, AW_SCREEN); // draw higher-significant digit
1188    }
1189
1190    delete [] sbuffer;
1191}
1192
1193int ED4_columnStat_terminal::update_likelihood() {
1194    ED4_sequence_terminal *seq_term = corresponding_sequence_terminal();
1195
1196    return STAT_update_ml_likelihood(ED4_ROOT->st_ml, likelihood, latest_update, NULp, seq_term->st_ml_node);
1197}
1198
1199ED4_columnStat_terminal::ED4_columnStat_terminal(GB_CSTR temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1200    ED4_text_terminal(column_stat_terminal_spec, temp_id, width, height, temp_parent)
1201{
1202    for (int i=0; i<4; i++) likelihood[i] = NULp;
1203    latest_update = 0;
1204}
1205
1206ED4_columnStat_terminal::~ED4_columnStat_terminal() {
1207    for (int i=0; i<4; i++) free(likelihood[i]);
1208}
1209
1210// ------------------------
1211//      flag terminals
1212
1213ED4_flag_header_terminal::ED4_flag_header_terminal(GB_CSTR id_, AW_pos width, AW_pos height, ED4_manager *parent_) :
1214    ED4_text_terminal(flag_header_spec, id_, width, height, parent_)
1215{}
1216
1217GB_CSTR ED4_flag_header_terminal::get_displayed_text() const {
1218    return SpeciesFlags::instance().get_header_text();
1219}
1220int ED4_flag_header_terminal::get_length() const {
1221    return SpeciesFlags::instance().get_header_length();
1222}
1223
1224ED4_flag_terminal::ED4_flag_terminal(const char *id_, AW_pos width, AW_pos height, ED4_manager *parent_) :
1225    ED4_terminal(flag_spec, id_, width, height, parent_)
1226{}
1227
1228using namespace AW;
1229
1230class FlagLayout {
1231    double    flag_centerx; // flag x-position relative to terminal
1232    Rectangle box;          // box at flag_centerx
1233
1234public:
1235    FlagLayout(const Rectangle& area, const SpeciesFlags& flags) {
1236        double boxsize = std::max(1.0, std::min(double(flags.get_min_flag_distance()), area.height()*0.95));
1237        Vector box_diag(boxsize, -boxsize);
1238
1239        SpeciesFlagCiter curr_flag  = flags.begin();
1240        flag_centerx                = curr_flag->center_xpos();
1241        Position         box_center = area.left_edge().centroid() + Vector(flag_centerx, 0);
1242        box                         = Rectangle(box_center-box_diag/2, box_diag);
1243    }
1244
1245    void move_box(double new_flag_centerx) {
1246        box.move(Vector(new_flag_centerx - flag_centerx, 0));
1247        flag_centerx = new_flag_centerx;
1248    }
1249
1250    const Rectangle& get_box() const { return box; }
1251};
1252
1253void ED4_flag_terminal::draw() {
1254    const SpeciesFlags& flags = SpeciesFlags::instance();
1255
1256    int boxes = flags.size();
1257    if (boxes>0) {
1258        FlagLayout layout(get_win_area(current_ed4w()), flags);
1259
1260        SpeciesFlagCiter curr_flag = flags.begin();
1261        SpeciesFlagCiter end       = flags.end();
1262
1263        AW_device *device = current_device();
1264
1265        GBDATA   *gb_species = get_species();
1266        GB_ERROR  error      = NULp;
1267
1268        for (int b = 0; b<boxes && !error; ++b) {
1269            bool filled = false;
1270            {
1271                GBDATA *gb_field = GB_entry(gb_species, curr_flag->get_fieldname().c_str());
1272                if (gb_field) {
1273                    uint8_t as_byte  = GB_read_lossless_byte(gb_field, error);
1274                    if (error) error = GBS_global_string("Failed to read flag value (Reason: %s)", error);
1275                    else    filled   = as_byte;
1276                }
1277            }
1278
1279            if (filled) device->box(ED4_G_FLAG_FILL,  FillStyle::SOLID, layout.get_box(), AW_SCREEN); // filled?
1280            device->box(            ED4_G_FLAG_FRAME, FillStyle::EMPTY, layout.get_box(), AW_SCREEN); // frame
1281
1282            ++curr_flag;
1283            if (curr_flag != end) layout.move_box(curr_flag->center_xpos());
1284        }
1285
1286        aw_message_if(error);
1287    }
1288}
1289
1290void ED4_flag_terminal::handle_left_click(const Position& click) {
1291    const SpeciesFlags& flags = SpeciesFlags::instance();
1292
1293    int boxes = flags.size();
1294    if (boxes>0) {
1295        FlagLayout layout(get_win_area(current_ed4w()), flags);
1296
1297        SpeciesFlagCiter curr_flag = flags.begin();
1298        SpeciesFlagCiter end       = flags.end();
1299
1300        for (int b = 0; b<boxes; ++b) {
1301            if (layout.get_box().contains(click)) break;
1302            ++curr_flag;
1303            if (curr_flag != end) layout.move_box(curr_flag->center_xpos());
1304        }
1305
1306        if (curr_flag != end) {
1307            GBDATA   *gb_species = get_species();
1308            GBDATA   *gb_field   = GB_entry(gb_species, curr_flag->get_fieldname().c_str());
1309            GB_ERROR  error      = GB_incur_error_if(!gb_field);
1310
1311            if (!error && !gb_field) {
1312                const char *key   = curr_flag->prepare_itemfield(); // impl using prepare_and_get_selected_itemfield
1313                if (key) gb_field = GBT_searchOrCreate_itemfield_according_to_changekey(gb_species, key, SPECIES_get_selector().change_key_path);
1314                error             = GB_incur_error_if(!gb_field);
1315            }
1316
1317            if (gb_field) {
1318                uint8_t val       = GB_read_lossless_byte(gb_field, error);
1319                if (!error) error = GB_write_lossless_byte(gb_field, !val);
1320            }
1321
1322            aw_message_if(error);
1323            if (!error) request_refresh();
1324        }
1325    }
1326}
1327
1328// ---------------------------------
1329//      ED4_reference_terminals
1330
1331void ED4_reference_terminals::clear() {
1332    delete ref_sequence_info;
1333    delete ref_sequence;
1334    delete ref_column_stat;
1335    delete ref_column_stat_info;
1336    null();
1337}
1338
1339void ED4_reference_terminals::init(ED4_sequence_info_terminal *ref_sequence_info_,
1340                                   ED4_sequence_terminal *ref_sequence_,
1341                                   ED4_sequence_info_terminal *ref_column_stat_info_,
1342                                   ED4_columnStat_terminal *ref_column_stat_)
1343{
1344    clear();
1345    ref_sequence_info    = ref_sequence_info_;
1346    ref_sequence     = ref_sequence_;
1347    ref_column_stat_info = ref_column_stat_info_;
1348    ref_column_stat      = ref_column_stat_;
1349}
Note: See TracBrowser for help on using the repository browser.