source: trunk/EDIT4/ED4_text_terminals.cxx

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