source: branches/help/EDIT4/ED4_text_terminals.cxx

Last change on this file was 18781, checked in by westram, 3 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.7 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ED4_text_terminals.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
13#include "ed4_class.hxx"
14#include "ed4_awars.hxx"
15#include "ed4_edit_string.hxx"
16#include "ed4_block.hxx"
17#include "ed4_nds.hxx"
18#include "ed4_visualizeSAI.hxx"
19#include "ed4_ProteinViewer.hxx"
20#include "ed4_protein_2nd_structure.hxx"
21#include "ed4_seq_colors.hxx"
22
23#include <aw_preset.hxx>
24#include <aw_awar.hxx>
25
26#include <AW_helix.hxx>
27#include <aw_msg.hxx>
28#include <aw_root.hxx>
29
30#include <st_window.hxx>
31#include <arbdbt.h>
32
33#include <iostream>
34
35inline void ensure_buffer(char*& buffer, size_t& buffer_size, size_t needed) {
36    if (needed>buffer_size) {
37        delete [] buffer;
38        buffer_size = needed+10;
39        buffer      = new char[buffer_size];
40
41        memset(buffer, ' ', buffer_size-1);
42        buffer[buffer_size-1] = 0;
43    }
44}
45
46void ED4_consensus_sequence_terminal::draw() {
47    static char   *buffer      = NULp;
48    static size_t  buffer_size = 0;
49
50    AW_pos x, y;
51    calc_world_coords(&x, &y);
52    current_ed4w()->world_to_win_coords(&x, &y);
53
54    PosRange index_range = calc_update_interval();
55    if (index_range.is_empty()) return; // nothing to draw
56
57    AW_pos text_x = x + CHARACTEROFFSET; // don't change
58    AW_pos text_y = y + SEQ_TERM_TEXT_YOFFSET;
59
60    buffer_size = 0;
61
62    if (index_range.is_unlimited()) {
63        e4_assert(MAXSEQUENCECHARACTERLENGTH == 0); // allow missing update interval when no seqdata is present (yet)
64
65        const char *no_data = "No consensus data";
66        size_t      len     = strlen(no_data);
67        ensure_buffer(buffer, buffer_size, len+1);
68        memcpy(buffer, no_data, len);
69
70        index_range = ExplicitRange(index_range, buffer_size-1);
71    }
72    else {
73        const ED4_remap *rm = ED4_ROOT->root_group_man->remap();
74
75        index_range = rm->clip_screen_range(index_range);
76        if (index_range.is_empty()) return; // nothing to draw
77
78        ExplicitRange seq_range = ExplicitRange(rm->screen_to_sequence(index_range), MAXSEQUENCECHARACTERLENGTH);
79        index_range             = rm->sequence_to_screen(seq_range);
80
81        char *cons = NULp;
82        if (!seq_range.is_empty()) {
83            cons = GB_give_buffer(seq_range.size()+1);
84            get_char_table().build_consensus_string_to(cons, seq_range, ED4_ROOT->get_consensus_params());
85        }
86
87        ensure_buffer(buffer, buffer_size, index_range.end()+1);
88
89        ED4_reference *ref            = ED4_ROOT->reference;
90        bool           only_show_diff = ref->only_show_diff_for(this);
91
92        for (int pos = index_range.start(); pos <= index_range.end(); ++pos) {
93            int seq_pos = rm->screen_to_sequence(pos);
94            if (seq_pos<0) {
95                buffer[pos] = ' ';
96            }
97            else {
98                char c      = cons[seq_pos-seq_range.start()];
99                buffer[pos] = only_show_diff ? ref->convert(c, seq_pos) : c;
100                e4_assert(buffer[pos]);
101            }
102        }
103    }
104
105    if (buffer_size) {
106        current_device()->set_vertical_font_overlap(true);
107        current_device()->text(ED4_G_SEQUENCES, SizedCstr(buffer, index_range.end()+1), text_x, text_y, 0, AW_SCREEN);
108        current_device()->set_vertical_font_overlap(false);
109    }
110}
111
112struct ShowHelix_cd {
113    AW_helix *helix;
114    int       real_sequence_length;
115};
116
117static bool ED4_show_helix_on_device(AW_device *device, int gc, const char *helixBuffer, size_t helixStart, size_t helixLen, const AW::Position& pos, AW_CL cduser) {
118    ShowHelix_cd    *cd     = (ShowHelix_cd*)cduser;
119    AW_helix        *helix  = cd->helix;
120    const ED4_remap *rm     = ED4_ROOT->root_group_man->remap();
121    char            *buffer = GB_give_buffer(helixLen+1);
122    long             i, j, k;
123
124    helixLen = std::min(rm->get_max_screen_pos(), helixLen);
125
126    for (k=0; size_t(k)<helixLen; k++) {
127        i = rm->screen_to_sequence(k+helixStart);
128
129        BI_PAIR_TYPE pairType = helix->pairtype(i);
130        if (pairType == HELIX_NONE) {
131            buffer[k] = ' ';
132        }
133        else {
134            j             = helix->opposite_position(i);
135            char pairchar = j<cd->real_sequence_length ? helixBuffer[j] : '.';
136            buffer[k]     = helix->get_symbol(helixBuffer[i], pairchar, pairType);
137        }
138    }
139    buffer[helixLen] = 0;
140    return device->text(gc, buffer, pos);
141}
142
143static bool ED4_show_protein_match_on_device(AW_device *device, int gc, const char *pfoldBuffer, size_t pfoldStart, size_t pfoldLen, const AW::Position& pos, AW_CL cl_protstruct) {
144    /*! \brief Calls ED4_pfold_calculate_secstruct_match() for the visible area in the
145     *         editor to compute the protein secondary structure match and outputs the
146     *         result to the device.
147     *  \param[in] pfoldBuffer   The protein structure (primary or secondary) that should be compared to \a cl_protstruct
148     *  \param[in] cl_protstruct The reference protein secondary structure SAI
149     */
150
151    GB_ERROR error = NULp;
152    // TODO: proper use of ED4_remap?
153    const ED4_remap *rm = ED4_ROOT->root_group_man->remap();
154    char *buffer = GB_give_buffer(pfoldLen+1);
155    if (!buffer) {
156        error = GB_export_error("Out of memory.");
157    }
158    else {
159        error = ED4_pfold_calculate_secstruct_match((const unsigned char *)cl_protstruct,
160                                                    (const unsigned char *)pfoldBuffer,
161                                                    rm->screen_to_sequence(pfoldStart),
162                                                    rm->screen_to_sequence(pfoldStart + pfoldLen),
163                                                    buffer,
164                                                    (PFOLD_MATCH_METHOD)ED4_ROOT->aw_root->awar(PFOLD_AWAR_MATCH_METHOD)->read_int());
165    }
166    if (error) {
167        aw_message(error);
168        return false;
169    }
170
171    buffer[pfoldLen] = 0;
172    return device->text(gc, buffer, pos);
173}
174
175void ED4_orf_terminal::draw() {
176    // draw aminoacid ORFs below the DNA sequence
177
178    static int    color_is_used[ED4_G_DRAG];
179    static char **colored_strings        = NULp;
180    static int    len_of_colored_strings = 0;
181
182    AW_device *device = current_device();
183
184    // @@@ DRY calculation of index-range to-be-updated (done in several draw functions)
185    AW_pos world_x, world_y;
186    calc_world_coords(&world_x, &world_y);
187    current_ed4w()->world_to_win_coords(&world_x, &world_y);
188
189    AW_pos text_x = world_x + CHARACTEROFFSET; // don't change
190    AW_pos text_y = world_y + SEQ_TERM_TEXT_YOFFSET;
191
192    const ED4_remap *rm = ED4_ROOT->root_group_man->remap();
193
194    ExplicitRange index_range = rm->clip_screen_range(calc_update_interval());
195    {
196        int max_seq_len = aaSeqLen;
197        int max_seq_pos = rm->sequence_to_screen(max_seq_len-1);
198        index_range     = ExplicitRange(PosRange(index_range), max_seq_pos);
199    }
200
201    if (index_range.is_empty()) {
202        // @@@ looks wrong (index_range is empty depending on updated area!)
203        // compare to .@DRAW_WRONG_MESSAGE
204
205        const char *no_data = "No sequence data";
206
207        device->text(ED4_G_STANDARD, no_data, text_x, text_y, 0, AW_SCREEN);
208        return; // nothing to draw
209    }
210
211    if (index_range.end() >= len_of_colored_strings) {
212        len_of_colored_strings = index_range.end() + 256;
213        if (!colored_strings) ARB_calloc(colored_strings, ED4_G_DRAG);
214
215        for (int i=0; i<ED4_G_DRAG; i++) {
216            freeset(colored_strings[i], ARB_alloc<char>(len_of_colored_strings+1));
217            memset(colored_strings[i], ' ', len_of_colored_strings);
218            colored_strings[i][len_of_colored_strings] = 0;
219        }
220    }
221
222    int seq_end = rm->screen_to_sequence(index_range.end());
223
224    // mark all strings as unused
225    memset(color_is_used, 0, sizeof(color_is_used));
226
227    int iDisplayMode = ED4_ROOT->aw_root->awar(AWAR_PROTVIEW_DISPLAY_OPTIONS)->read_int();
228    {
229        const unsigned char *aaSequence_u = (const unsigned char *)aaSequence;
230        const unsigned char *aaColor_u    = (const unsigned char *)aaColor;
231
232        if (iDisplayMode == PV_AA_NAME || iDisplayMode == PV_AA_CODE) {
233            // transform strings, compress if needed
234            ED4_reference *ref = ED4_ROOT->reference;
235            ref->expand_to_length(seq_end);
236
237            char *char_2_char = ED4_ROOT->sequence_colors->char_2_char_aa;
238            char *char_2_gc   = ED4_ROOT->sequence_colors->char_2_gc_aa;
239
240            if (iDisplayMode == PV_AA_NAME) {
241                for (int scr_pos=index_range.start(); scr_pos <= index_range.end(); scr_pos++) {
242                    int           seq_pos = rm->screen_to_sequence(scr_pos);
243                    unsigned char c       = aaSequence_u[seq_pos];
244                    unsigned char cc      = aaColor_u[seq_pos];
245                    int           gc      = char_2_gc[safeCharIndex(cc)];
246
247                    color_is_used[gc] = scr_pos+1;
248                    colored_strings[gc][scr_pos] = char_2_char[safeCharIndex(c)];
249                }
250            }
251            else {
252                for (int scr_pos=index_range.start(); scr_pos <= index_range.end(); scr_pos++) {
253                    int  seq_pos = rm->screen_to_sequence(scr_pos);
254                    char c       = aaSequence_u[seq_pos];
255                    int  gc      = char_2_gc[safeCharIndex(c)];
256
257                    color_is_used[gc] = scr_pos+1;
258                    colored_strings[gc][scr_pos] = char_2_char[safeCharIndex(c)];
259                }
260            }
261        }
262
263        // paint background
264        if ((iDisplayMode == PV_AA_CODE) || (iDisplayMode == PV_AA_BOX)) {
265            AW_pos     width        = ED4_ROOT->font_group.get_width(ED4_G_SEQUENCES);
266            const int  real_left    = index_range.start();
267            const int  real_right   = index_range.end();
268            AW_pos     x2           = text_x + width*real_left;
269            AW_pos     y1           = world_y;
270            AW_pos     y2           = text_y+1;
271            AW_pos     height       = y2-y1+1;
272            int        color        = ED4_G_STANDARD;
273            char      *char_2_gc_aa = ED4_ROOT->sequence_colors->char_2_gc_aa;
274
275            for (int i = real_left; i <= real_right; i++, x2 += width) {
276                int  new_pos = rm->screen_to_sequence(i); // getting the real position of the base in the sequence
277                char base    = aaSequence_u[new_pos];
278
279                if (isupper(base) || (base=='*')) {
280                    AW_pos x1  = x2-width; // store current x pos to x1
281                    x2 += width*2; // add 2 char width to x2
282                    i  += 2; // jump two pos
283
284                    int gcChar =  char_2_gc_aa[safeCharIndex(base)];
285                    if ((gcChar>=0) && (gcChar<ED4_G_DRAG)) {
286                        color = gcChar;
287                        if (iDisplayMode == PV_AA_BOX) {
288                            device->box(color, AW::FillStyle::SOLID, x1, y1, width*3, height);
289                        }
290                        else {
291                            double    rad_x    = width*1.5;
292                            double    rad_y    = height*0.7;
293                            double    center_x = x1+rad_x;
294                            const int DRAW_DEG = 62;
295
296                            device->arc(ED4_G_SEQUENCES, AW::FillStyle::EMPTY, center_x, y1, rad_x, rad_y,   0,  DRAW_DEG);
297                            device->arc(ED4_G_SEQUENCES, AW::FillStyle::EMPTY, center_x, y1, rad_x, rad_y, 180, -DRAW_DEG);
298                        }
299                    }
300                }
301            }
302        }
303    }
304
305    if ((iDisplayMode == PV_AA_NAME) || (iDisplayMode == PV_AA_CODE)) {
306        device->set_vertical_font_overlap(true);
307        // output strings
308        for (int gc = 0; gc < ED4_G_DRAG; gc++) {
309            if (color_is_used[gc] && (int)strlen(colored_strings[gc]) >= color_is_used[gc]) {
310                device->text(gc, SizedCstr(colored_strings[gc], color_is_used[gc]), text_x, text_y, 0, AW_SCREEN);
311                memset(colored_strings[gc] + index_range.start(), ' ', index_range.size()); // clear string
312            }
313        }
314        device->set_vertical_font_overlap(false);
315    }
316}
317
318void ED4_sequence_terminal::draw() {
319    static int    color_is_used[ED4_G_DRAG];
320    static char **colored_strings        = NULp;
321    static int    len_of_colored_strings = 0;
322
323#if defined(TRACE_REFRESH)
324    fprintf(stderr, "ED4_sequence_terminal::draw for id='%s'\n", id); fflush(stderr);
325#endif
326
327    AW_device *device = current_device();
328
329    int max_seq_len;
330    resolve_pointer_to_char_pntr(&max_seq_len);
331    e4_assert(max_seq_len>0);
332
333    AW_pos world_x, world_y;
334    calc_world_coords(&world_x, &world_y);
335    current_ed4w()->world_to_win_coords(&world_x, &world_y);
336
337    AW_pos text_x = world_x + CHARACTEROFFSET;    // don't change
338    AW_pos text_y = world_y + SEQ_TERM_TEXT_YOFFSET;
339
340    const ED4_remap *rm = ED4_ROOT->root_group_man->remap();
341
342    ExplicitRange index_range = rm->clip_screen_range(calc_update_interval());
343    if (index_range.is_empty()) return; // nothing to draw
344
345    int left  = index_range.start(); // @@@ do similar to ED4_orf_terminal::draw here
346    int right = index_range.end();
347
348    {
349        int max_seq_pos = rm->sequence_to_screen(max_seq_len-1);
350
351        if (right>max_seq_len) right = max_seq_pos;
352        if (left>right) {
353            // @@@ may be correct here
354            // compare to .@DRAW_WRONG_MESSAGE
355
356            const char *no_data = "No sequence data";
357
358            device->text(ED4_G_STANDARD, no_data, text_x, text_y, 0, AW_SCREEN);
359            return; // nothing to draw
360        }
361    }
362
363    if (right >= len_of_colored_strings) {
364        len_of_colored_strings = right + 256;
365        if (!colored_strings) ARB_calloc(colored_strings, ED4_G_DRAG);
366
367        for (int i=0; i<ED4_G_DRAG; i++) {
368            freeset(colored_strings[i], (char *)malloc(sizeof(char) * (len_of_colored_strings+1)));
369            memset(colored_strings[i], ' ', len_of_colored_strings);
370            colored_strings[i][len_of_colored_strings] = 0;
371        }
372    }
373
374    int seq_start = rm->screen_to_sequence(left); // real start of sequence
375    int seq_end = rm->screen_to_sequence(right);
376
377    // mark all strings as unused
378    memset(color_is_used, 0, sizeof(color_is_used));
379
380    // transform strings, compress if needed
381    {
382        ED4_reference *ref        = ED4_ROOT->reference;
383        unsigned char *db_pointer = (unsigned char *)resolve_pointer_to_string_copy();
384
385        ref->expand_to_length(seq_end);
386
387        GB_alignment_type aliType = GetAliType();
388        char *char_2_char = (aliType && (aliType==GB_AT_AA)) ? ED4_ROOT->sequence_colors->char_2_char_aa : ED4_ROOT->sequence_colors->char_2_char;
389        char *char_2_gc   = (aliType && (aliType==GB_AT_AA)) ? ED4_ROOT->sequence_colors->char_2_gc_aa : ED4_ROOT->sequence_colors->char_2_gc;
390
391        bool only_show_diff = ref->only_show_diff_for(this);
392        for (int scr_pos=left; scr_pos <= right; scr_pos++) {
393            int seq_pos = rm->screen_to_sequence(scr_pos);
394            int c = db_pointer[seq_pos];
395            int gc = char_2_gc[c];
396
397            color_is_used[gc] = scr_pos+1;
398            colored_strings[gc][scr_pos] = char_2_char[only_show_diff ? ref->convert(c, seq_pos) : c];
399        }
400
401        free(db_pointer);
402    }
403
404    // Set background
405
406    {
407        GB_transaction       ta(ED4_ROOT->get_gb_main());
408        ST_ML_Color         *statColors   = NULp;
409        char                *searchColors = results().buildColorString(this, seq_start, seq_end); // defined in ED4_SearchResults class : ED4_search.cxx
410        ED4_species_manager *spec_man     = get_parent(LEV_SPECIES)->to_species_manager();
411        int                  color_group  = AW_color_groups_active() ? GBT_get_color_group(spec_man->get_species_pointer()) : 0;
412
413        PosRange selection;
414        int      is_selected = ED4_get_selected_range(this, selection);
415        int      is_marked   = GB_read_flag(spec_man->get_species_pointer());
416
417        if (species_name &&
418            ED4_ROOT->column_stat_activated &&
419            (st_ml_node || (st_ml_node = STAT_find_node_by_name(ED4_ROOT->st_ml, this->species_name))))
420        {
421            statColors = STAT_get_color_string(ED4_ROOT->st_ml, NULp, st_ml_node, seq_start, seq_end);
422        }
423
424        const char *saiColors = NULp;
425
426        if (species_name                       &&
427            ED4_ROOT->visualizeSAI             &&
428            spec_man->get_type() != ED4_SP_SAI &&
429            (is_marked || ED4_ROOT->visualizeSAI_allSpecies))
430        {
431            saiColors = ED4_getSaiColorString(ED4_ROOT->aw_root, seq_start, seq_end);
432        }
433
434        if (statColors || searchColors || is_marked || is_selected || color_group || saiColors) {
435            int    i;
436            AW_pos width      = ED4_ROOT->font_group.get_width(ED4_G_SEQUENCES);
437            int    real_left  = left;
438            int    real_right = right;
439            AW_pos x2         = text_x + width*real_left;
440            AW_pos old_x      = x2;
441            AW_pos y1         = world_y;
442            AW_pos y2         = text_y+1;
443            AW_pos height     = y2-y1+1;
444            int    old_color  = ED4_G_STANDARD;
445            int    color      = ED4_G_STANDARD;
446
447            int back_color;
448            if      (is_marked)   back_color = ED4_G_MARKED;
449            else if (color_group) back_color = ED4_G_FIRST_COLOR_GROUP+color_group-1;
450            else                  back_color = ED4_G_STANDARD;
451
452            if (is_selected && selection.is_unlimited()) {
453                selection = ExplicitRange(selection, rm->screen_to_sequence(real_right));
454            }
455
456            for (i = real_left; i <= real_right; i++, x2 += width) {
457                int new_pos = rm->screen_to_sequence(i);  // getting the real position of the base in the sequence
458
459                // Note: if you change background color priorities,
460                // please update help in ../HELP_SOURCE/source/e4_background_priority.hlp@COLOR_PRIORITY
461
462                if (searchColors && searchColors[new_pos]) {
463                    color = searchColors[new_pos];
464                }
465                else if (is_selected && selection.contains(new_pos)) {
466                    color = ED4_G_SELECTED;
467                }
468                else if (statColors) {
469                    color = statColors[new_pos] + ED4_G_CBACK_0;
470                    if (color > ED4_G_CBACK_9) color = ED4_G_CBACK_9;
471                }
472                else if (saiColors) {
473                    color = saiColors[new_pos];
474                    if (color < ED4_G_CBACK_0 || color > ED4_G_CBACK_9)  color = back_color;
475                }
476                else {
477                    color = back_color;
478                }
479
480                if (color != old_color) {   // draw till oldcolor
481                    if (x2>old_x) {
482                        if (old_color!=ED4_G_STANDARD) {
483                            device->box(old_color, AW::FillStyle::SOLID, old_x, y1, x2-old_x, height); // paints the search pattern background
484                        }
485                    }
486                    old_x = x2;
487                    old_color = color;
488                }
489            }
490
491            if (x2>old_x) {
492                if (color!=ED4_G_STANDARD) {
493                    device->box(color, AW::FillStyle::SOLID, old_x, y1, x2-old_x, height);
494                }
495            }
496        }
497    }
498
499    device->set_vertical_font_overlap(true);
500
501    if (shall_display_secstruct_info) {
502        if (ED4_ROOT->helix->is_enabled()) {
503            // output helix
504            int   db_len;
505            char *db_pointer = resolve_pointer_to_string_copy(&db_len);
506
507            e4_assert(size_t(db_len) == ED4_ROOT->helix->size());
508            ShowHelix_cd  cd         = { ED4_ROOT->helix, max_seq_len };
509            device->text_overlay(ED4_G_HELIX,
510                                 SizedCstr(db_pointer, db_len),
511                                 AW::Position(text_x,  text_y + ED4_ROOT->helix_spacing), 0.0,  AW_ALL_DEVICES_UNSCALED,
512                                 ED4_show_helix_on_device, (AW_CL)&cd);
513            free(db_pointer);
514        }
515
516        if (ED4_ROOT->protstruct) {
517            // output protein structure match
518            ED4_species_manager *spec_man = get_parent(LEV_SPECIES)->to_species_manager();
519            if (spec_man->get_type() != ED4_SP_SAI && ED4_ROOT->aw_root->awar(PFOLD_AWAR_ENABLE)->read_int()) {  // should do a remap
520                int   db_len;
521                char *protstruct = resolve_pointer_to_string_copy(&db_len);
522
523                if (protstruct) {
524                    device->text_overlay(ED4_G_HELIX,
525                                         SizedCstr(protstruct, db_len),
526                                         AW::Position(text_x,  text_y + ED4_ROOT->helix_spacing),  0.0,  AW_ALL_DEVICES_UNSCALED,
527                                         ED4_show_protein_match_on_device, (AW_CL)ED4_ROOT->protstruct);
528                    free(protstruct);
529                }
530            }
531        }
532    }
533    // output strings
534    {
535        int gc;
536        for (gc = 0; gc < ED4_G_DRAG; gc++) {
537            if (!color_is_used[gc]) continue;
538            device->text(gc, SizedCstr(colored_strings[gc], color_is_used[gc]), text_x, text_y, 0, AW_SCREEN);
539            memset(colored_strings[gc] + left, ' ', right-left+1); // clear string
540        }
541    }
542
543    device->set_vertical_font_overlap(false);
544}
545
546
547void ED4_sequence_info_terminal::draw() {
548    AW_pos x, y;
549    calc_world_coords(&x, &y);
550    current_ed4w()->world_to_win_coords(&x, &y);
551
552    AW_pos text_x = x + CHARACTEROFFSET; // don't change
553    AW_pos text_y = y+INFO_TERM_TEXT_YOFFSET;
554
555    char    buffer[10];
556    GBDATA *gbdata = data();
557
558    if (gbdata) {
559        GB_push_transaction(gbdata);
560        buffer[0] = '0' + GB_read_security_write(gbdata);
561        GB_pop_transaction(gbdata);
562    }
563    else {
564        buffer[0] = ' ';
565    }
566    strncpy(&buffer[1], this->id, 8);
567    buffer[9] = 0;
568
569    if (containing_species_manager()->is_selected()) {
570        current_device()->box(ED4_G_SELECTED, AW::FillStyle::SOLID, x, y, extension.size[WIDTH], text_y-y+1);
571    }
572
573    current_device()->set_vertical_font_overlap(true);
574    current_device()->text(ED4_G_STANDARD, buffer, text_x, text_y, 0, AW_SCREEN);
575    current_device()->set_vertical_font_overlap(false);
576}
577
578// ---------------------------
579//      ED4_text_terminal
580
581void ED4_text_terminal::draw() {
582    AW_pos x, y;
583    calc_world_coords(&x, &y);
584    current_ed4w()->world_to_win_coords(&x, &y);
585
586    AW_pos text_x = x + CHARACTEROFFSET; // don't change
587    AW_pos text_y = y + INFO_TERM_TEXT_YOFFSET;
588
589    current_device()->set_vertical_font_overlap(true);
590
591    if (is_species_name_terminal()) { // @@@ handle by virtual method (eg. draw_text())
592        GB_CSTR real_name      = to_species_name_terminal()->get_displayed_text();
593        int     width_of_char;
594        int     height_of_char = -1;
595        bool    paint_box      = inside_species_seq_manager();
596        bool    is_marked      = false;
597
598        if (paint_box) {
599            ED4_species_manager *species_man = get_parent(LEV_SPECIES)->to_species_manager();
600            GBDATA *gbd = species_man->get_species_pointer();
601
602            if (gbd) {
603                GB_transaction ta(gbd);
604                is_marked = GB_read_flag(gbd);
605            }
606
607            width_of_char = ED4_ROOT->font_group.get_width(ED4_G_STANDARD);
608            height_of_char = ED4_ROOT->font_group.get_height(ED4_G_STANDARD);
609#define MIN_MARK_BOX_SIZE 8
610            if (width_of_char<MIN_MARK_BOX_SIZE) width_of_char = MIN_MARK_BOX_SIZE;
611            if (height_of_char<MIN_MARK_BOX_SIZE) height_of_char = MIN_MARK_BOX_SIZE;
612#undef MIN_MARK_BOX_SIZE
613        }
614        else {
615            width_of_char = 0;
616        }
617
618        if (containing_species_manager()->is_selected()) {
619            current_device()->box(ED4_G_SELECTED, AW::FillStyle::SOLID, x, y, extension.size[WIDTH], text_y-y+1);
620        }
621        current_device()->text(ED4_G_STANDARD, real_name, text_x+width_of_char, text_y, 0, AW_SCREEN);
622
623        if (paint_box) {
624            int xsize = (width_of_char*6)/10;
625            int ysize = (height_of_char*6)/10;
626            int xoff  = xsize>>1;
627            int yoff  = 0;
628            int bx    = int(text_x+xoff);
629            int by    = int(text_y-(yoff+ysize));
630
631            current_device()->box(ED4_G_STANDARD, AW::FillStyle::SOLID, bx, by, xsize, ysize);
632            if (!is_marked && xsize>2 && ysize>2) {
633                current_device()->clear_part(bx+1, by+1, xsize-2, ysize-2, AW_ALL_DEVICES);
634            }
635        }
636    }
637    else if (is_flag_header_terminal()) { // @@@ handle by virtual method (eg. draw_text())
638        ED4_flag_header_terminal *header_term = to_flag_header_terminal();
639        const char               *header_text = header_term->get_displayed_text();
640
641        text_y += (SEQ_TERM_TEXT_YOFFSET-INFO_TERM_TEXT_YOFFSET); // @@@ wrong vertical shift? (change fontsize to examine)
642        current_device()->text(ED4_G_FLAG_INFO, SizedCstr(header_text, header_term->get_length()), text_x, text_y, 0, AW_SCREEN);
643    }
644    else {
645        e4_assert(is_pure_text_terminal()); // unhandled terminal type that does not overload draw()
646
647        char *db_pointer = resolve_pointer_to_string_copy();
648
649        text_y += (SEQ_TERM_TEXT_YOFFSET-INFO_TERM_TEXT_YOFFSET);
650        current_device()->text(ED4_G_SEQUENCES, db_pointer, text_x, text_y, 0, AW_SCREEN);
651
652        free(db_pointer);
653    }
654    current_device()->set_vertical_font_overlap(false);
655}
656
657ED4_text_terminal::ED4_text_terminal(const ED4_objspec& spec_, GB_CSTR temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
658    ED4_terminal(spec_, temp_id, width, height, temp_parent)
659{}
660
Note: See TracBrowser for help on using the repository browser.