| 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 | |
|---|
| 35 | inline 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 | |
|---|
| 46 | void 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 | |
|---|
| 112 | struct ShowHelix_cd { |
|---|
| 113 | AW_helix *helix; |
|---|
| 114 | int real_sequence_length; |
|---|
| 115 | }; |
|---|
| 116 | |
|---|
| 117 | static 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 | |
|---|
| 141 | static 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 | |
|---|
| 173 | void 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 | |
|---|
| 316 | void 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 | |
|---|
| 545 | void 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 | |
|---|
| 579 | void 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 | |
|---|
| 655 | ED4_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 | |
|---|