source: tags/initial/EDIT4/ED4_cursor.cxx

Last change on this file was 2, checked in by oldcode, 23 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 50.7 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <limits.h>
6
7#include <aw_keysym.hxx>
8#include <arbdb.h>
9#include <arbdbt.h>
10#include <aw_root.hxx>
11#include <aw_awars.hxx>
12#include <aw_window.hxx>
13#include <BI_helix.hxx>
14
15#include "ed4_class.hxx"
16#include "ed4_edit_string.hxx"
17#include "ed4_tools.hxx"
18#include "ed4_awars.hxx"
19#include "ed4_secedit.hxx"
20
21/* --------------------------------------------------------------------------------
22   CursorShape
23   -------------------------------------------------------------------------------- */
24
25#define MAXLINES  30
26#define MAXPOINTS (2*MAXLINES)
27
28class CursorShape {
29    int points;
30    int xpos[MAXPOINTS];
31    int ypos[MAXPOINTS];
32
33    int lines;
34    int start[MAXLINES];
35    int end[MAXLINES];
36
37
38    int point(int x, int y) {
39        e4_assert(points<MAXPOINTS);
40        xpos[points] = x;
41        ypos[points] = y;
42        return points++;
43    }
44    int line(int p1, int p2) {
45        e4_assert(p1>=0 && p1<points);
46        e4_assert(p2>=0 && p2<points);
47
48        e4_assert(lines<MAXLINES);
49        start[lines] = p1;
50        end[lines] = p2;
51
52        return lines++;
53    }
54    int horizontal_line(int x, int y, int half_width) {
55        return line(point(x-half_width, y), point(x+half_width, y));
56    }
57
58public:
59
60    CursorShape(ED4_CursorType type, int x, int y, int term_height, int character_width);
61    ~CursorShape() {}
62
63    void draw(AW_device *device) const {
64        e4_assert(lines);
65        for (int l=0; l<lines; l++) {
66            int p1 = start[l];
67            int p2 = end[l];
68            device->line(ED4_G_CURSOR, xpos[p1], ypos[p1], xpos[p2], ypos[p2], 1, 0, 0);
69        }
70        device->flush();
71    }
72
73    void get_bounding_box(int &xmin, int &ymin, int &xmax, int &ymax) const {
74        e4_assert(points);
75        xmin = ymin = INT_MAX;
76        xmax = ymax = INT_MIN;
77        for (int p=0; p<points; p++) {
78            if (xpos[p]<xmin)           { xmin = xpos[p]; }
79            else if (xpos[p]>xmax)      { xmax = xpos[p]; }
80            if (ypos[p]<ymin)           { ymin = ypos[p]; }
81            else if (ypos[p]>ymax)      { ymax = ypos[p]; }
82        }
83    }
84
85
86};
87
88CursorShape::CursorShape(ED4_CursorType typ, int x, int y, int term_height, int character_width)
89{
90    lines = 0;
91    points = 0;
92
93    switch (typ) {
94        case ED4_RIGHT_ORIENTED_CURSOR:  {
95
96#define UPPER_OFFSET    (-1)
97#define LOWER_OFFSET    (term_height-1)
98#define CWIDTH          (character_width)
99
100            // --CWIDTH--
101            //
102            // 0--------1               UPPER_OFFSET (from top)
103            // |3-------4
104            // ||
105            // ||
106            // ||
107            // ||
108            // ||
109            // ||
110            // 25                       LOWER_OFFSET (from top)
111            //
112            //
113            //  x
114
115            int p0 = point(x, y+UPPER_OFFSET);
116            int p3 = point(x+1, y+UPPER_OFFSET+1);
117
118            line(p0, point(x+CWIDTH-1, y+UPPER_OFFSET));        // 0->1
119            line(p3, point(x+CWIDTH-1, y+UPPER_OFFSET+1));      // 3->4
120            line(p0, point(x, y+LOWER_OFFSET));                 // 0->2
121            line(p3, point(x+1, y+LOWER_OFFSET));               // 3->5
122
123            break;
124
125#undef UPPER_OFFSET
126#undef LOWER_OFFSET
127#undef CWIDTH
128
129        }
130        case ED4_TRADITIONAL_CURSOR: {
131
132#define UPPER_OFFSET    1
133#define LOWER_OFFSET    (term_height-1)
134#define CWIDTH          3
135
136            //  -----2*CWIDTH----
137            //
138            //  0---------------1       UPPER_OFFSET (from top)
139            //  2---------------3
140            //
141            //        10/10
142            //        8---9
143            //     6---------7
144            //  4---------------5       LOWER_OFFSET (from top)
145
146            horizontal_line(x, y+UPPER_OFFSET, CWIDTH);
147            horizontal_line(x, y+UPPER_OFFSET+1, CWIDTH);
148
149            horizontal_line(x, y+LOWER_OFFSET, CWIDTH);
150            horizontal_line(x, y+LOWER_OFFSET-1, (CWIDTH*2)/3);
151            horizontal_line(x, y+LOWER_OFFSET-2, CWIDTH/3);
152
153            int p = point(x, y+LOWER_OFFSET-3);
154            line(p,p);
155
156            break;
157
158#undef UPPER_OFFSET
159#undef LOWER_OFFSET
160#undef CWIDTH
161
162        }
163        case ED4_FUCKING_BIG_CURSOR: {
164
165#define OUTER_HEIGHT    (term_height/4)
166#define INNER_HEIGHT    (term_height-1)
167#define CWIDTH          12
168#define STEPS           6
169#define THICKNESS       2
170
171#if (2*STEPS+THICKNESS > MAXLINES)
172#error Bad definitions!
173#endif
174
175            //          2               3               |
176            //            \           /                 | OUTER_HEIGHT
177            //               \     /                    |
178            //                  0               |       |
179            //                  |               | INNER_HEIGHT
180            //                  |               |
181            //                  1               |
182            //                /    \                    --
183            //             /          \                 --
184            //          4               5
185            //
186            //          -----------------
187            //                2*WIDTH
188
189            int s;
190            for (s=0; s<STEPS; s++) {
191                int size = ((STEPS-s)*CWIDTH)/STEPS;
192
193                horizontal_line(x, y-OUTER_HEIGHT+s,                    size);
194                horizontal_line(x, y+INNER_HEIGHT+OUTER_HEIGHT-s,       size);
195            }
196
197            int y_upper = ypos[s-4];
198            int y_lower = ypos[s-2];
199
200            int t;
201            for (t=0; t<THICKNESS; t++) {
202                int xp = x-(THICKNESS/2)+t+1;
203                line(point(xp, y_upper), point(xp, y_lower));
204            }
205
206            break;
207
208#undef OUTER_HEIGHT
209#undef INNER_HEIGHT
210#undef CWIDTH
211#undef STEPS
212#undef THICKNESS
213
214        }
215        default: {
216            e4_assert(0);
217            break;
218        }
219    }
220}
221
222/* --------------------------------------------------------------------------------
223   ED4_cursor
224   -------------------------------------------------------------------------------- */
225
226ED4_returncode ED4_cursor::draw_cursor(AW_pos x, AW_pos y, /*ED4_gc gc,*/ED4_base *target_terminal)
227{
228    CursorShape(ctype, int(x), int(y),
229                int(target_terminal->extension.size[HEIGHT]),
230                ED4_ROOT->font_info[ED4_G_SEQUENCES].get_width())
231        .draw(ED4_ROOT->temp_device);
232
233    return ED4_R_OK;
234}
235
236ED4_returncode ED4_cursor::delete_cursor(AW_pos del_mark, ED4_base *target_terminal)
237{
238    AW_pos x, y;
239    ED4_base *temp_parent;
240
241    e4_assert(is_visible());
242    target_terminal->calc_world_coords( &x, &y );
243    temp_parent = target_terminal->get_parent( ED4_L_SPECIES );
244    if (!temp_parent || temp_parent->flag.hidden) {
245        return ED4_R_BREAK;
246    }
247    x = del_mark;
248    ED4_ROOT->world_to_win_coords( ED4_ROOT->temp_aww, &x, &y );
249
250    // refresh own terminal + terminal above + terminal below
251
252    target_terminal->set_refresh();
253    target_terminal->parent->refresh_requested_by_child();
254
255    {
256        ED4_terminal *term = target_terminal->to_terminal();
257        int backward = 1;
258
259        while (1) {
260            int done = 0;
261
262            term = backward ? term->get_prev_terminal() : term->get_next_terminal();
263            if (!term) {
264                done = 1;
265            }
266            else if ((term->is_sequence_terminal()) && !term->is_in_folded_group()) {
267                term->set_refresh();
268                term->parent->refresh_requested_by_child();
269                done = 1;
270            }
271
272            if (done) {
273                if (!backward) {
274                    break;
275                }
276                backward = 0;
277                term = target_terminal->to_terminal();
278            }
279        }
280
281        term = target_terminal->to_terminal();
282        while(1) {
283            term = term->get_next_terminal();
284            if (!term) {
285                break;
286            }
287
288        }
289    }
290
291    // clear rectangle where cursor is displayed
292
293    AW_device *dev = ED4_ROOT->temp_device;
294    dev->push_clip_scale();
295
296    int xmin, xmax, ymin, ymax;
297    CursorShape shape(ctype, int(x), int(y),
298                      int(target_terminal->extension.size[HEIGHT]),
299                      ED4_ROOT->font_info[ED4_G_SEQUENCES].get_width());
300    shape.get_bounding_box(xmin, ymin, xmax, ymax);
301
302#if !defined(NDEBUG) && 0
303    dev->box(2, xmin, ymin, xmax-xmin+1, ymax-ymin+1, (AW_bitset)-1, 0, 0);
304#else
305    dev->clear_part(xmin, ymin, xmax-xmin+1, ymax-ymin+1);
306#endif
307
308    dev->set_top_font_overlap(1);
309    dev->set_bottom_font_overlap(1);
310    dev->set_left_font_overlap(1);
311    dev->set_right_font_overlap(1);
312
313#define EXPAND_SIZE 0
314    ED4_ROOT->temp_device->reduceClipBorders(ymin-EXPAND_SIZE, ymax+1+EXPAND_SIZE, xmin-EXPAND_SIZE, xmax+1+EXPAND_SIZE);
315
316    // refresh terminal
317
318    int old_allowed_to_draw = allowed_to_draw;
319    allowed_to_draw = 0;
320    ED4_ROOT->refresh_window(0);
321    allowed_to_draw = old_allowed_to_draw;
322
323    dev->pop_clip_scale();
324
325    return ( ED4_R_OK );
326}
327
328
329ED4_cursor::ED4_cursor()
330{
331    init();
332    allowed_to_draw = 1;
333
334    ctype = (ED4_CursorType)(ED4_ROOT->aw_root->awar(ED4_AWAR_CURSOR_TYPE)->read_int()%ED4_CURSOR_TYPES);
335}
336void ED4_cursor::init() // used by ED4_terminal-d-tor
337{
338    owner_of_cursor = NULL;
339    abs_x = 0;
340    screen_position = 0;
341    last_seq_position = 0;
342}
343ED4_cursor::~ED4_cursor()
344{
345}
346
347ED4_window *ED4_cursor::window() const
348{
349    ED4_window *window;
350
351    for (window=ED4_ROOT->first_window; window; window=window->next) {
352        if (&window->cursor==this) {
353            break;
354        }
355    }
356    e4_assert(window);
357    return window;
358}
359
360int ED4_cursor::get_sequence_pos() const
361{
362    ED4_remap *remap = ED4_ROOT->root_group_man->remap();
363    size_t max_scrpos = remap->get_max_screen_pos();
364
365    return remap->screen_to_sequence(size_t(screen_position)<=max_scrpos ? screen_position : max_scrpos);
366}
367
368void ED4_cursor::set_to_sequence_position(int seq_pos)
369{
370    if (owner_of_cursor) {
371        jump_centered_cursor_to_seq_pos(window()->aww, seq_pos);
372    }
373}
374
375int ED4_species_manager::setCursorTo(ED4_cursor *cursor, int position, int unfold_groups)
376{
377    ED4_group_manager *group_manager_to_unfold = is_in_folded_group();
378    int unfolded = 0;
379
380    while (group_manager_to_unfold && unfold_groups) {
381        ED4_base *base = group_manager_to_unfold->search_spec_child_rek(ED4_L_BRACKET);
382        if (!base) break;
383        ED4_bracket_terminal *bracket = base->to_bracket_terminal();
384        group_manager_to_unfold->unfold_group(bracket->id);
385        unfolded = 1;
386        group_manager_to_unfold = is_in_folded_group();
387    }
388
389    if (unfolded) {
390        //      ED4_ROOT->deselect_all();
391        ED4_ROOT->refresh_all_windows(1);
392    }
393
394    if (!group_manager_to_unfold) {
395        ED4_terminal *terminal = search_spec_child_rek(ED4_L_SEQUENCE_STRING)->to_terminal();
396        if (terminal) {
397            int seq_pos = position==-1 ? cursor->get_sequence_pos() : position;
398            cursor->set_to_terminal(ED4_ROOT->temp_aww, terminal, seq_pos);
399
400            //      e4_assert(cursor->is_visible());
401            return 1;
402        }
403    }
404
405    return 0;
406}
407
408static void jump_to_species(ED4_species_name_terminal *name_term, int position, int unfold_groups)
409{
410    ED4_species_manager *species_manager = name_term->get_parent(ED4_L_SPECIES)->to_species_manager();
411    ED4_cursor *cursor = &ED4_ROOT->temp_ed4w->cursor;
412    int jumped = 0;
413
414    if (species_manager) jumped = species_manager->setCursorTo(cursor, position, unfold_groups);
415    if (!jumped) cursor->HideCursor();
416}
417
418static int ignore_selected_species_changes_cb = 0;
419
420void ED4_selected_species_changed_cb(AW_root */*aw_root*/)
421{
422    ED4_update_global_cursor_awars_allowed = 0;
423
424    if (!ignore_selected_species_changes_cb) {
425        char *name = GBT_read_string(gb_main,AWAR_SPECIES_NAME);
426        if (name && name[0]) {
427#if defined(DEBUG) && 1
428            printf("Selected species is '%s'\n", name);
429#endif
430            ED4_species_name_terminal *name_term = ED4_find_species_name_terminal(name);
431            if (name_term) {
432                // lookup current name term
433                ED4_species_name_terminal *cursor_name_term = 0;
434                {
435                    ED4_cursor *cursor = &ED4_ROOT->temp_ed4w->cursor;
436                    if (cursor) {
437                        ED4_sequence_terminal *cursor_seq_term = cursor->owner_of_cursor->to_sequence_terminal();
438                        if (cursor_seq_term) {
439                            cursor_name_term = cursor_seq_term->corresponding_species_name_terminal();
440                        }
441                    }
442                }
443                if (name_term!=cursor_name_term) { // do not change if already there!
444#if defined(DEBUG) && 1
445                    printf("Selected species changed to '%s'\n", name);
446#endif
447                    jump_to_species(name_term, -1, 0);
448                }
449                else {
450#if defined(DEBUG) && 1
451                    printf("Change ignored because same name term!\n");
452#endif
453                }
454            }
455
456            free(name);
457        }
458    }
459    else {
460#if defined(DEBUG) && 1
461        printf("Change ignored because ignore_selected_species_changes_cb!\n");
462#endif
463    }
464    ignore_selected_species_changes_cb = 0;
465    ED4_update_global_cursor_awars_allowed = 1;
466}
467
468void ED4_jump_to_current_species(AW_window */*aw*/, AW_CL)
469{
470    char *name = GBT_read_string(gb_main, AWAR_SPECIES_NAME);
471    if (name && name[0]) {
472        GB_transaction dummy(gb_main);
473#if defined(DEBUG) && 1
474        printf("Jump to selected species (%s)\n", name);
475#endif
476        ED4_species_name_terminal *name_term = ED4_find_species_name_terminal(name);
477
478        if (name_term) {
479            jump_to_species(name_term, -1, 1);
480        }
481        else {
482            aw_message(GBS_global_string("Species '%s' is not loaded - use GET to load it.", name));
483        }
484    }
485    else {
486        aw_message("Please select a species");
487    }
488}
489
490static int multi_species_man_consensus_id_starts_with(ED4_base *base, AW_CL cl_start) { // TRUE if consensus id starts with 'start'
491    ED4_multi_species_manager *ms_man = base->to_multi_species_manager();
492    char *start = (char*)cl_start;
493    ED4_base *consensus = ms_man->search_spec_child_rek(ED4_L_SPECIES);
494
495    if (consensus) {
496        ED4_base *consensus_name = consensus->search_spec_child_rek(ED4_L_SPECIES_NAME);
497
498        if (consensus_name) {
499            if (strncmp(consensus_name->id, start, strlen(start))==0) {
500                ED4_multi_species_manager *cons_ms_man = consensus_name->get_parent(ED4_L_MULTI_SPECIES)->to_multi_species_manager();
501                return cons_ms_man==ms_man;
502            }
503        }
504    }
505
506    return 0;
507}
508
509ED4_multi_species_manager *ED4_new_species_multi_species_manager(void) { // returns manager into which new species should be inserted
510    ED4_base *manager = ED4_ROOT->root_group_man->find_first_that(ED4_L_MULTI_SPECIES, multi_species_man_consensus_id_starts_with, (AW_CL)"More Sequences");
511    return manager ? manager->to_multi_species_manager() : 0;
512}
513
514void ED4_get_and_jump_to_species(GB_CSTR species_name)
515{
516    e4_assert(species_name && species_name[0]);
517
518    GB_transaction dummy(gb_main);
519    ED4_species_name_terminal *name_term = ED4_find_species_name_terminal(species_name);
520    int loaded = 0;
521
522    if (!name_term) { // insert new species
523        ED4_multi_species_manager *insert_into_manager = ED4_new_species_multi_species_manager();
524        ED4_group_manager *group_man = insert_into_manager->get_parent(ED4_L_GROUP)->to_group_manager();
525        char *string = (char*)GB_calloc(strlen(species_name)+3, sizeof(*string));
526        int index = 0;
527        ED4_index y = 0;
528        ED4_index lot = 0;
529
530        sprintf(string, "-L%s", species_name);
531        ED4_ROOT->database->fill_species(insert_into_manager,
532                                         ED4_ROOT->ref_terminals.get_ref_sequence_info(), ED4_ROOT->ref_terminals.get_ref_sequence(),
533                                         string, &index, &y, 0, &lot, insert_into_manager->calc_group_depth());
534        loaded = 1;
535
536        {
537            GBDATA *gb_species = GBT_find_species(gb_main, species_name);
538            GBDATA *gbd = GBT_read_sequence(gb_species, ED4_ROOT->alignment_name);
539
540            if (gbd) {
541                char *data = GB_read_string(gbd);
542                int len = GB_read_string_count(gbd);
543                group_man->table().add(data, len);
544            }
545        }
546
547        name_term = ED4_find_species_name_terminal(species_name);
548        if (name_term) {
549            ED4_ROOT->main_manager->update_info.set_resize(1);
550            ED4_ROOT->main_manager->resize_requested_by_parent();
551        }
552        delete string;
553    }
554    if (name_term) {
555        jump_to_species(name_term, -1, 1);
556        if (!loaded) {
557            aw_message(GBS_global_string("'%s' is already loaded.", species_name));
558        }
559    }
560    else {
561        aw_message(GBS_global_string("Cannot get species '%s'", species_name));
562    }
563}
564
565void ED4_get_and_jump_to_actual(AW_window *, AW_CL)
566{
567    char *name = GBT_read_string(gb_main, AWAR_SPECIES_NAME);
568    if (name && name[0]) {
569        ED4_get_and_jump_to_species(name);
570        ED4_ROOT->refresh_all_windows(0);
571    }
572    else {
573        aw_message("Please select a species");
574    }
575}
576
577void ED4_get_and_jump_to_actual_from_menu(AW_window *aw, AW_CL cl, AW_CL) {
578    ED4_get_and_jump_to_actual(aw, cl);
579    ED4_ROOT->refresh_all_windows(0);
580}
581
582void ED4_get_marked_from_menu(AW_window *, AW_CL, AW_CL) {
583#define BUFFERSIZE 1000
584    GB_transaction dummy(gb_main);
585    int marked = GBT_count_marked_species(gb_main);
586
587    if (marked) {
588        GBDATA *gb_species = GBT_first_marked_species(gb_main);
589        int count = 0;
590        char *buffer = new char[BUFFERSIZE+1];
591        char *bp = buffer;
592        //      int inbuf = 0; // # of names in buffer
593        ED4_multi_species_manager *insert_into_manager = ED4_new_species_multi_species_manager();
594        ED4_group_manager *group_man = insert_into_manager->get_parent(ED4_L_GROUP)->to_group_manager();
595        int group_depth = insert_into_manager->calc_group_depth();
596        int index = 0;
597        ED4_index y = 0;
598        ED4_index lot = 0;
599        int inserted = 0;
600        char *default_alignment = GBT_get_default_alignment(gb_main);
601
602        aw_openstatus("ARB_EDIT4");
603        aw_status("Loading species...");
604
605        while (gb_species) {
606            count++;
607            GB_status(double(count)/double(marked));
608
609            char *name = GBT_read_name(gb_species);
610            ED4_species_name_terminal *name_term = ED4_find_species_name_terminal(name);
611
612            if (!name_term) { // species not found -> insert
613                {
614                    int namelen = strlen(name);
615                    int buffree = BUFFERSIZE-int(bp-buffer);
616
617                    if ((namelen+2)>buffree) {
618                        *bp++ = 0;
619                        ED4_ROOT->database->fill_species(insert_into_manager,
620                                                         ED4_ROOT->ref_terminals.get_ref_sequence_info(), ED4_ROOT->ref_terminals.get_ref_sequence(),
621                                                         buffer, &index, &y, 0, &lot, group_depth);
622                        bp = buffer;
623                        index = 0;
624                    }
625
626                    *bp++ = 1;
627                    *bp++ = 'L';
628                    memcpy(bp, name, namelen);
629                    bp += namelen;
630                }
631
632                {
633                    GBDATA *gbd = GBT_read_sequence(gb_species, default_alignment);
634
635                    if (gbd) {
636                        char *data = GB_read_string(gbd);
637                        int len = GB_read_string_count(gbd);
638                        group_man->table().add(data, len);
639                    }
640                }
641
642                inserted++;
643            }
644            gb_species = GBT_next_marked_species(gb_species);
645        }
646
647        if (bp>buffer) {
648            *bp++ = 0;
649            ED4_ROOT->database->fill_species(insert_into_manager,
650                                             ED4_ROOT->ref_terminals.get_ref_sequence_info(), ED4_ROOT->ref_terminals.get_ref_sequence(),
651                                             buffer, &index, &y, 0, &lot, group_depth);
652        }
653
654        aw_closestatus();
655        aw_message(GBS_global_string("Loaded %i of %i marked species.", inserted, marked));
656
657        if (inserted) {
658            ED4_ROOT->main_manager->update_info.set_resize(1);
659            ED4_ROOT->main_manager->resize_requested_by_parent();
660        }
661
662        delete buffer;
663        delete default_alignment;
664    }
665    else {
666        aw_message("No species marked.");
667    }
668
669#undef BUFFERSIZE
670
671    ED4_ROOT->refresh_all_windows(0);
672}
673
674ED4_returncode ED4_cursor::HideCursor()
675{
676    if (owner_of_cursor) {
677        if (is_visible()) {
678            delete_cursor(abs_x, owner_of_cursor);
679        }
680        owner_of_cursor = 0;
681    }
682
683    return ED4_R_OK;
684}
685
686void ED4_cursor::changeType(ED4_CursorType typ)
687{
688    if (owner_of_cursor) {
689        ED4_base *old_owner_of_cursor = owner_of_cursor;
690
691        HideCursor();
692        ctype = typ;
693        ED4_ROOT->aw_root->awar(ED4_AWAR_CURSOR_TYPE)->write_int(int(ctype));
694        owner_of_cursor = old_owner_of_cursor;
695        ShowCursor(0, ED4_C_NONE, 0);
696    }
697    else {
698        ctype = typ;
699    }
700}
701
702int ED4_update_global_cursor_awars_allowed = 1;
703
704void ED4_cursor::updateAwars()
705{
706    AW_root     *aw_root = ED4_ROOT->aw_root;
707    ED4_window  *win = ED4_ROOT->temp_ed4w;
708    int         seq_pos = get_sequence_pos();
709
710    if (ED4_update_global_cursor_awars_allowed) {
711        if (owner_of_cursor) {
712            char *species_name  = owner_of_cursor->get_name_of_species();
713            if (species_name) {
714                ignore_selected_species_changes_cb = 1;
715                GBT_write_string(gb_main, AWAR_SPECIES_NAME, species_name);
716            }
717        }
718    }
719
720    // update awars for cursor position:
721
722    aw_root->awar(win->awar_path_for_cursor)->write_int(seq_pos+1);
723    if (ED4_update_global_cursor_awars_allowed) {
724        aw_root->awar(AWAR_CURSOR_POSITION)->write_int(seq_pos+1);      // this supports last cursor position for all applications
725    }
726
727    // look if we have a commented search result under the cursor:
728
729    if (owner_of_cursor && owner_of_cursor->is_sequence_terminal()) {
730        ED4_sequence_terminal *seq_term = owner_of_cursor->to_sequence_terminal();
731        ED4_SearchResults &results = seq_term->results();
732        ED4_SearchPosition *pos = results.get_shown_at(seq_pos);
733
734        if (pos) {
735            GB_CSTR comment = pos->get_comment();
736
737            if (comment) {
738                char *buffer = GB_give_buffer(strlen(comment)+30);
739
740                sprintf(buffer, "%s: %s", ED4_SearchPositionTypeId[pos->get_whatsFound()], comment);
741                aw_message(buffer);
742            }
743        }
744    }
745
746    // update awar for ecoli position:
747
748    {
749        long lseq_pos = seq_pos+1;
750        long ecoli_pos;
751        long dummy;
752
753        ED4_ROOT->ecoli_ref->abs_2_rel(lseq_pos, ecoli_pos, dummy);
754        aw_root->awar(win->awar_path_for_Ecoli)->write_int(ecoli_pos);
755    }
756
757    // update awar for base position:
758
759    int base_pos = base_position.get_base_position(owner_of_cursor, seq_pos+1);
760    aw_root->awar(win->awar_path_for_basePos)->write_int(base_pos); // update awar for base position
761
762    // update awar for IUPAC:
763
764    char iupac[5];
765    strcpy(iupac, IUPAC_EMPTY);
766
767    if (owner_of_cursor) {
768        ED4_species_manager *species_manager =  owner_of_cursor->get_parent(ED4_L_SPECIES)->to_species_manager();
769        int len;
770        int allocated = 0;
771        char *seq;
772
773        if (species_manager->flag.is_consensus) {
774            ED4_group_manager *group_manager = owner_of_cursor->get_parent(ED4_L_GROUP)->to_group_manager();
775
776            seq = group_manager->table().build_consensus_string(seq_pos, seq_pos, 0);
777            len = seq_pos+1; // fake
778            allocated = 1;
779        }
780        else {
781            seq = owner_of_cursor->resolve_pointer_to_string(&len);
782        }
783
784        e4_assert(seq);
785
786        if (seq_pos<len) {
787            char base = seq[seq_pos];
788            const char *i = ED4_decode_iupac(base, ED4_ROOT->alignment_type);
789
790            strcpy(iupac, i);
791        }
792
793        if (allocated) delete seq;
794    }
795
796    aw_root->awar(win->awar_path_for_IUPAC)->write_string(iupac);
797
798    // update awar for helix#:
799
800    {
801        BI_helix *helix = ED4_ROOT->helix;
802        int helixnr = 0;
803
804        if (size_t(seq_pos)<helix->size && helix->entries[seq_pos].pair_type) {
805            helixnr = atoi(helix->entries[seq_pos].helix_nr);
806        }
807        aw_root->awar(win->awar_path_for_helixNr)->write_int(helixnr);
808    }
809}
810
811void ED4_cursor::jump_cursor(AW_window *aww, int new_cursor_screen_pos, bool center_cursor, bool fix_left_border)
812{
813    int old_allowed_to_draw = allowed_to_draw;
814
815    if (!owner_of_cursor) {
816        aw_message("First you have to place the cursor");
817        return;
818    }
819
820    ED4_base *temp_parent = owner_of_cursor;
821    while (temp_parent->parent) {
822        temp_parent = temp_parent->parent;
823        if (temp_parent->flag.hidden) return; // don't move cursor if terminal is flag.hidden
824    }
825
826    AW_pos terminal_x, terminal_y;
827    owner_of_cursor->calc_world_coords(&terminal_x, &terminal_y);
828
829    if (!is_visible()) {
830        ED4_terminal *term = owner_of_cursor->to_terminal();
831
832        allowed_to_draw = 0;
833        int set = term->setCursorTo(this, get_sequence_pos(), 0);
834        allowed_to_draw = old_allowed_to_draw;
835        if (!set) return;
836
837        e4_assert(is_visible());
838    }
839
840    int cursor_diff = new_cursor_screen_pos-screen_position;
841    if ((cursor_diff==0 && !center_cursor) || new_cursor_screen_pos<0) return; // already at new position
842
843    int terminal_pixel_length = aww->get_device(AW_MIDDLE_AREA)->get_string_size(ED4_G_SEQUENCES, 0, owner_of_cursor->to_text_terminal()->get_length());
844    int length_of_char = ED4_ROOT->font_info[ED4_G_SEQUENCES].get_width();
845    int x_pos_cursor_new = abs_x+cursor_diff*length_of_char;
846
847    if (x_pos_cursor_new > terminal_x+terminal_pixel_length+CHARACTEROFFSET ||
848        x_pos_cursor_new < terminal_x+CHARACTEROFFSET) {
849        return; // don`t move out of string
850    }
851
852    ED4_coords *coords = &ED4_ROOT->temp_ed4w->coords;
853    int margin;
854
855    if (center_cursor) {
856        margin = (coords->window_right_clip_point - coords->window_left_clip_point + 1 - 2) / 2;
857    }
858    else {
859        margin = length_of_char * MARGIN;
860    }
861
862    bool inside_right_margin = x_pos_cursor_new<=coords->window_right_clip_point && x_pos_cursor_new > coords->window_right_clip_point - margin; // we are in the right margin
863    bool inside_left_margin  = x_pos_cursor_new> coords->window_left_clip_point  && x_pos_cursor_new < coords->window_left_clip_point + margin; // we are in the left margin
864    bool scroll_horizontal = x_pos_cursor_new<coords->window_left_clip_point+margin || x_pos_cursor_new>coords->window_right_clip_point-margin; // we have to scroll
865
866    if (cursor_diff >= 0) { // move cursor to the right
867        if (!scroll_horizontal || inside_left_margin) { // move cursor without scrolling or enter margin
868            delete_cursor( abs_x , owner_of_cursor);
869            allowed_to_draw = 1;
870            ShowCursor( cursor_diff*length_of_char, ED4_C_RIGHT, ABS(cursor_diff));
871            allowed_to_draw = old_allowed_to_draw;
872        }
873        else  { // we have to scroll to the right
874            int diff_cursor_margin = (ED4_ROOT->temp_ed4w->coords.window_right_clip_point - margin) - abs_x; // difference between old cursor position & right margin
875
876            delete_cursor(abs_x, owner_of_cursor);
877            abs_x += cursor_diff*length_of_char;
878            aww->set_horizontal_scrollbar_position(aww->slider_pos_horizontal + length_of_char*cursor_diff - diff_cursor_margin);
879
880            allowed_to_draw = 0;
881            ED4_horizontal_change_cb(aww, 0, 0);
882            allowed_to_draw = old_allowed_to_draw;
883
884            ShowCursor(0, ED4_C_RIGHT, ABS( cursor_diff ));
885        }
886    }
887    else if (cursor_diff < 0) // move cursor to the left
888    {
889        if (!scroll_horizontal || inside_right_margin) // move cursor without scrolling or enter margin
890        {
891            delete_cursor(abs_x, owner_of_cursor);
892            allowed_to_draw = 1;
893            ShowCursor( cursor_diff * length_of_char, ED4_C_LEFT, ABS( cursor_diff ) );
894            allowed_to_draw = old_allowed_to_draw;
895        }
896        else // we have to scroll to the left
897        {
898            int diff_cursor_margin = abs_x - (ED4_ROOT->temp_ed4w->coords.window_left_clip_point + margin);
899
900            delete_cursor(abs_x, owner_of_cursor);
901            abs_x -= ABS(cursor_diff) * length_of_char;
902            if ( aww->slider_pos_horizontal - length_of_char*ABS(cursor_diff) < 0) {
903                aww->slider_pos_horizontal = 0;
904            }
905            else {
906                aww->set_horizontal_scrollbar_position(aww->slider_pos_horizontal - length_of_char*ABS(cursor_diff) + diff_cursor_margin);
907            }
908
909            allowed_to_draw = 0;
910            ED4_horizontal_change_cb(aww, 0, 0);
911            allowed_to_draw = old_allowed_to_draw;
912
913            ShowCursor(0, ED4_C_LEFT, ABS( cursor_diff ));
914        }
915    }
916
917    last_seq_position = -1;
918}
919
920void ED4_cursor::jump_left_right_cursor(AW_window *aww, int new_cursor_screen_pos) {
921    jump_cursor(aww, new_cursor_screen_pos, false, false);
922}
923
924void ED4_cursor::jump_centered_cursor(AW_window *aww, int new_cursor_screen_pos) {
925    jump_cursor(aww, new_cursor_screen_pos, true, false);
926}
927
928void ED4_cursor::jump_left_right_cursor_to_seq_pos(AW_window *aww, int new_cursor_seq_pos) {
929    int screen_pos = ED4_ROOT->root_group_man->remap()->sequence_to_screen_clipped(new_cursor_seq_pos);
930
931    jump_left_right_cursor(aww,screen_pos);
932    last_seq_position = new_cursor_seq_pos;
933}
934
935void ED4_cursor::jump_centered_cursor_to_seq_pos(AW_window *aww, int new_cursor_seq_pos) {
936    int screen_pos = ED4_ROOT->root_group_man->remap()->sequence_to_screen_clipped(new_cursor_seq_pos);
937
938    jump_centered_cursor(aww,screen_pos);
939    last_seq_position = new_cursor_seq_pos;
940}
941
942static int current_position = -1;
943
944static bool terminal_has_gap_or_base_at_current_position(ED4_base *terminal, bool test_for_base) {
945    bool test_succeeded = false;
946   
947    if (terminal->is_sequence_terminal()) {
948        ED4_sequence_terminal *seqTerm = terminal->to_sequence_terminal();
949        int len;
950        char *seq = seqTerm->resolve_pointer_to_string(&len);
951        if (seq) {
952            test_succeeded =
953                len>current_position &&
954                bool(ADPP_IS_ALIGN_CHARACTER(seq[current_position])) != test_for_base;
955        }
956    }
957   
958#if defined(DEBUG) && 0
959    printf("test_for_base=%i test_succeeded=%i\n", int(test_for_base), int(test_succeeded));
960#endif // DEBUG
961    return test_succeeded;
962}
963
964static bool terminal_has_base_at_current_position(ED4_base *terminal) { return terminal_has_gap_or_base_at_current_position(terminal, 1); }
965static bool terminal_has_gap_at_current_position(ED4_base *terminal) { return terminal_has_gap_or_base_at_current_position(terminal, 0); }
966
967ED4_returncode ED4_cursor::move_cursor( AW_event *event )       /* up down */
968{
969    AW_pos x, y, x_screen, y_screen, target_x, target_y, scroll_diff;
970    ED4_base *temp_parent, *target_terminal = NULL;
971    AW_event target_event;
972    ED4_AREA_LEVEL area_level;
973
974    temp_parent = owner_of_cursor->parent;
975    while (temp_parent->parent) {
976        temp_parent = temp_parent->parent;
977
978        if (temp_parent->flag.hidden) {
979            return ED4_R_IMPOSSIBLE; // don't move cursor if terminal is flag.hidden
980        }
981    }
982
983    owner_of_cursor->calc_world_coords( &x, &y );
984    x_screen = abs_x;
985    y_screen = y;
986    ED4_ROOT->world_to_win_coords( ED4_ROOT->temp_aww, &x_screen, &y_screen );
987    area_level = owner_of_cursor->get_area_level();
988    if (! is_visible()) return ED4_R_BREAK;
989
990    switch (event->keycode) {
991        case AW_KEY_UP: {
992            if (event->keymodifier & AW_KEY_CONTROL) {
993                current_position = last_seq_position;               
994                bool has_base = terminal_has_base_at_current_position(owner_of_cursor);
995               
996                get_upper_lower_cursor_pos( ED4_ROOT->main_manager, &target_terminal, ED4_C_UP, y,
997                                            has_base ? terminal_has_gap_at_current_position : terminal_has_base_at_current_position);
998                if (!has_base && ED4_ROOT->aw_root->awar(ED4_AWAR_FAST_CURSOR_JUMP)->read_int())  { // if jump_over group
999                    get_upper_lower_cursor_pos( ED4_ROOT->main_manager, &target_terminal, ED4_C_DOWN, y_screen, terminal_has_gap_at_current_position);         
1000                }
1001            }
1002            else {
1003                get_upper_lower_cursor_pos( ED4_ROOT->main_manager, &target_terminal, ED4_C_UP, y, 0);
1004            }
1005
1006            if (target_terminal) {
1007                target_terminal->calc_world_coords( &target_x, &target_y );
1008                scroll_diff = target_y - y;
1009                target_event.x = (int) abs_x;
1010                target_event.y = (int) target_y;
1011
1012                if (! (target_terminal->is_visible( 0, target_y, ED4_D_VERTICAL )) && ED4_ROOT->temp_aww->slider_pos_vertical > 0) {
1013                    if (ED4_ROOT->temp_aww->slider_pos_vertical + scroll_diff < 0) {
1014                        ED4_ROOT->temp_aww->set_vertical_scrollbar_position (0);
1015                    }
1016                    else {
1017                        ED4_ROOT->temp_aww->set_vertical_scrollbar_position ((int)(ED4_ROOT->temp_aww->slider_pos_vertical + scroll_diff));
1018                    }
1019                    ED4_vertical_change_cb( ED4_ROOT->temp_aww, 0, 0 );
1020                    DRAW = 0;
1021                }
1022                show_clicked_cursor( &target_event, target_terminal );
1023            }
1024            break;
1025        }
1026
1027        case AW_KEY_DOWN: {
1028            if (event->keymodifier & AW_KEY_CONTROL) {
1029                current_position = last_seq_position;               
1030                bool has_base = terminal_has_base_at_current_position(owner_of_cursor);
1031               
1032                get_upper_lower_cursor_pos( ED4_ROOT->main_manager, &target_terminal, ED4_C_DOWN, y_screen,
1033                                            has_base ? terminal_has_gap_at_current_position : terminal_has_base_at_current_position);
1034                if (!has_base && ED4_ROOT->aw_root->awar(ED4_AWAR_FAST_CURSOR_JUMP)->read_int())  { // if jump_over group
1035                    get_upper_lower_cursor_pos( ED4_ROOT->main_manager, &target_terminal, ED4_C_DOWN, y_screen, terminal_has_gap_at_current_position);         
1036                }
1037            }
1038            else {
1039                get_upper_lower_cursor_pos( ED4_ROOT->main_manager, &target_terminal, ED4_C_DOWN, y_screen, 0);
1040            }
1041
1042            if (target_terminal) {
1043                target_terminal->calc_world_coords( &target_x, &target_y );
1044                scroll_diff = target_y - y;
1045                target_event.x = (int)ED4_ROOT->temp_ed4w->cursor.abs_x;
1046                target_event.y = (int)target_y;
1047
1048                if (! target_terminal->is_visible( 0, target_y, ED4_D_VERTICAL_ALL ) && area_level == ED4_A_MIDDLE_AREA) {
1049                    ED4_ROOT->temp_aww->set_vertical_scrollbar_position ((int)(ED4_ROOT->temp_aww->slider_pos_vertical + scroll_diff));
1050                    ED4_vertical_change_cb( ED4_ROOT->temp_aww, 0, 0 );
1051                    DRAW = 0;
1052                }
1053
1054                show_clicked_cursor( &target_event, target_terminal );
1055            }
1056            break;
1057        }
1058
1059        default: {
1060            break;
1061        }
1062    }
1063
1064    return ED4_R_OK;
1065}
1066
1067void ED4_cursor::set_abs_x()
1068{
1069    AW_pos x, y;
1070    owner_of_cursor->calc_world_coords( &x, &y );
1071    abs_x = int(get_sequence_pos()*ED4_ROOT->font_info[ED4_G_SEQUENCES].get_width() + CHARACTEROFFSET + x);
1072}
1073
1074void ED4_cursor::calc_cursor_position(AW_pos x, AW_pos *corrected_x_Ptr, ED4_index *scr_pos_Ptr) // x is pixelposition in terminal (relative to start of terminal)
1075{
1076    int length_of_char = ED4_ROOT->font_info[ED4_G_SEQUENCES].get_width();
1077    ED4_index scr_pos = (int)((x-CHARACTEROFFSET)/length_of_char);
1078    int max_scrpos = ED4_ROOT->root_group_man->remap()->get_max_screen_pos();
1079    int sub = 0;
1080
1081    if (scr_pos>max_scrpos) {
1082        sub = (scr_pos-max_scrpos)*length_of_char;
1083        scr_pos = max_scrpos;
1084    }
1085
1086    AW_pos corrected_x = (AW_pos) ((((int)((x-sub-CHARACTEROFFSET)/length_of_char)) * length_of_char) + CHARACTEROFFSET); //CHARACTEROFFSET is drawing offset of text
1087
1088    if (corrected_x_Ptr) *corrected_x_Ptr = corrected_x;
1089    if (scr_pos_Ptr) *scr_pos_Ptr = scr_pos;
1090}
1091
1092
1093ED4_returncode ED4_cursor::ShowCursor(ED4_index offset_x, ED4_cursor_move move, int move_pos)
1094{
1095    AW_pos x=0, y=0, x_help = 0, y_help;
1096
1097    owner_of_cursor->calc_world_coords( &x, &y );
1098
1099    switch (move)
1100    {
1101        case ED4_C_RIGHT:
1102            screen_position += move_pos;
1103            break;
1104        case ED4_C_LEFT:
1105            screen_position -= move_pos;
1106            break;
1107        case ED4_C_NONE:
1108            break;
1109        default:
1110            e4_assert(0);
1111            break;
1112    }
1113
1114    updateAwars();
1115
1116    if (! is_visible()) {
1117        return ED4_R_BREAK;
1118    }
1119
1120    x_help =  abs_x + offset_x;
1121    y_help = y;
1122
1123    ED4_ROOT->world_to_win_coords( ED4_ROOT->temp_aww, &x_help, &y_help );
1124
1125    if (allowed_to_draw) {
1126        draw_cursor(x_help, y_help, owner_of_cursor);
1127    }
1128
1129    abs_x += offset_x;
1130
1131    return ( ED4_R_OK );
1132}
1133
1134
1135bool ED4_cursor::is_visible() const
1136{
1137    ED4_AREA_LEVEL      area_level;
1138    AW_pos              x,y;
1139    int                 cursor_offset = 0;                      // maximum HALFCURSORWIDTH
1140
1141    owner_of_cursor->calc_world_coords( &x, &y );
1142    area_level = owner_of_cursor->get_area_level(0);
1143
1144    switch (area_level)
1145    {
1146        case ED4_A_TOP_AREA:
1147            if (!owner_of_cursor->is_visible(abs_x+cursor_offset, 0, ED4_D_HORIZONTAL)) return 0;
1148            if (!owner_of_cursor->is_visible(abs_x-cursor_offset, 0, ED4_D_HORIZONTAL)) return 0;
1149            break;
1150        case ED4_A_MIDDLE_AREA:
1151            if (!owner_of_cursor->is_visible(abs_x+cursor_offset, y, ED4_D_ALL_DIRECTION)) return 0; // right border
1152            if (!owner_of_cursor->is_visible(abs_x-cursor_offset, y, ED4_D_ALL_DIRECTION)) return 0; // left border
1153            break;
1154        default:
1155            return 0;
1156    }
1157
1158    return 1;
1159}
1160
1161// static void scrollWindowToCenterPos(AW_window *aww, AW_pos world_x, AW_pos world_y, int win_xsize, int win_ysize)
1162// {
1163//     AW_pos wanted_world_x = world_x - win_xsize/2;           // world coords which should be displayed in the upper-left corner
1164//     AW_pos wanted_world_y = world_y - win_ysize/2;
1165
1166//     if (wanted_world_x<0) wanted_world_x = 0;
1167//     if (wanted_world_y<0) wanted_world_y = 0;
1168
1169//     int pic_xsize = aww->get_scrolled_picture_width();               // size of scrolled picture = size of sliderrange
1170//     int pic_ysize = aww->get_scrolled_picture_height();
1171
1172//     int slider_xsize = win_xsize;
1173//     int slider_ysize = win_ysize;
1174
1175//     int slider_pos_xrange = pic_xsize - slider_xsize;        // allowed positions for slider
1176//     int slider_pos_yrange = pic_ysize - slider_ysize;
1177
1178//     int slider_pos_x = wanted_world_x;
1179//     int slider_pos_y = wanted_world_y;
1180
1181//     if (slider_pos_x>slider_pos_xrange) slider_pos_x = slider_pos_xrange;    // new slider positions
1182//     if (slider_pos_y>slider_pos_yrange) slider_pos_y = slider_pos_yrange;
1183
1184//     aww->set_vertical_scrollbar_position(slider_pos_y);
1185//     ED4_vertical_change_cb(aww, 0, 0);
1186
1187//     aww->set_horizontal_scrollbar_position(slider_pos_x);
1188//     ED4_horizontal_change_cb(aww, 0, 0);
1189// }
1190
1191ED4_returncode ED4_cursor::set_to_terminal(AW_window *aww, ED4_terminal *terminal, int seq_pos)
1192{
1193    if (owner_of_cursor) {
1194        if (is_visible()) {
1195            delete_cursor(abs_x, owner_of_cursor);
1196        }
1197
1198        owner_of_cursor->set_refresh(); // we have to refresh old owner of cursor
1199        owner_of_cursor->parent->refresh_requested_by_child();
1200        owner_of_cursor = NULL;
1201        ED4_ROOT->refresh_window(0);
1202        DRAW = 1;
1203    }
1204
1205    AW_pos termw_x, termw_y;
1206    terminal->calc_world_coords(&termw_x, &termw_y);
1207
1208    screen_position = ED4_ROOT->root_group_man->remap()->sequence_to_screen_clipped(seq_pos);
1209    last_seq_position = seq_pos;
1210    owner_of_cursor = terminal;
1211
1212    //    AW_device *device = aww->get_device(AW_MIDDLE_AREA);
1213    int length_of_char = ED4_ROOT->font_info[ED4_G_SEQUENCES].get_width();
1214    AW_pos seq_relx = AW_pos(screen_position*length_of_char + CHARACTEROFFSET); // position relative to start of terminal
1215
1216    AW_pos world_x = seq_relx+termw_x;          // world position of cursor
1217    AW_pos world_y = termw_y;
1218
1219    ED4_coords *coords = &ED4_ROOT->temp_ed4w->coords;
1220    int win_x_size = coords->window_right_clip_point - coords->window_left_clip_point + 1;      // size of scroll window
1221    int win_y_size = coords->window_lower_clip_point - coords->window_upper_clip_point + 1;
1222
1223    ED4_folding_line *foldLine = ED4_ROOT->temp_ed4w->vertical_fl;
1224    int left_area_width = 0;
1225
1226    if (foldLine) {
1227        left_area_width = int(foldLine->world_pos[X_POS]);
1228    }
1229
1230    int win_left = int(world_x - left_area_width - win_x_size/2);               if (win_left<0) win_left = 0;   // position
1231    int win_top = int(world_y - coords->top_area_height - win_y_size/2);        if (win_top<0) win_top = 0;
1232
1233    int pic_xsize = int(aww->get_scrolled_picture_width());             // size of scrolled picture = size of sliderrange
1234    int pic_ysize = int(aww->get_scrolled_picture_height());
1235
1236    int slider_xsize = win_x_size;
1237    int slider_ysize = win_y_size;
1238
1239    int slider_pos_xrange = pic_xsize - slider_xsize;   // allowed positions for slider
1240    int slider_pos_yrange = pic_ysize - slider_ysize;
1241
1242    int slider_pos_x = win_left;        // new slider positions
1243    int slider_pos_y = win_top;
1244
1245    if (slider_pos_x>slider_pos_xrange) slider_pos_x = slider_pos_xrange;
1246    if (slider_pos_y>slider_pos_yrange) slider_pos_y = slider_pos_yrange;
1247
1248    if (slider_pos_x<0) slider_pos_x = 0;
1249    if (slider_pos_y<0) slider_pos_y = 0;
1250
1251    aww->set_horizontal_scrollbar_position(slider_pos_x);
1252    aww->set_vertical_scrollbar_position(slider_pos_y);
1253    ED4_scrollbar_change_cb(aww, 0, 0);
1254
1255    AW_pos win_x = world_x;     // recalc coords cause window scrolled!
1256    AW_pos win_y = world_y;
1257    ED4_ROOT->world_to_win_coords( ED4_ROOT->temp_aww, &win_x, &win_y );
1258
1259    abs_x = (long int)world_x;
1260    owner_of_cursor = terminal;
1261
1262    draw_cursor(win_x, win_y, terminal);
1263
1264    GB_transaction gb_dummy(gb_main);
1265    updateAwars();
1266
1267    return ED4_R_OK;
1268}
1269
1270ED4_returncode ED4_cursor::show_clicked_cursor( AW_event *event, ED4_base *target_terminal )
1271{
1272    if (owner_of_cursor) {
1273        if (is_visible()) {
1274            delete_cursor(abs_x, owner_of_cursor);
1275        }
1276
1277        owner_of_cursor->set_refresh(); // we have to refresh old owner of cursor
1278        owner_of_cursor->parent->refresh_requested_by_child();
1279        owner_of_cursor = NULL;
1280        ED4_ROOT->refresh_window(0);
1281        DRAW = 1;
1282    }
1283
1284    AW_pos termw_x, termw_y;
1285    target_terminal->calc_world_coords( &termw_x, &termw_y );
1286
1287    AW_pos seqrel_x;
1288    ED4_index scr_pos;
1289    calc_cursor_position(event->x-termw_x, &seqrel_x, &scr_pos);
1290    screen_position = scr_pos;
1291    last_seq_position = ED4_ROOT->root_group_man->remap()->screen_to_sequence(screen_position);
1292
1293    AW_pos world_x  = seqrel_x + termw_x;
1294    AW_pos world_y  = termw_y;
1295
1296    AW_pos win_x = world_x;
1297    AW_pos win_y = world_y;
1298    ED4_ROOT->world_to_win_coords( ED4_ROOT->temp_aww, &win_x, &win_y );
1299
1300    abs_x = (long int)world_x;
1301    owner_of_cursor = target_terminal;
1302
1303    draw_cursor(win_x, win_y, target_terminal);
1304
1305    GB_transaction gb_dummy(gb_main);
1306    updateAwars();
1307
1308    return ED4_R_OK;
1309}
1310
1311ED4_returncode  ED4_cursor::get_upper_lower_cursor_pos( ED4_manager *starting_point, ED4_base **terminal, ED4_cursor_move cursor_move, AW_pos actual_y, bool (*terminal_is_appropriate)(ED4_base *terminal) )
1312{
1313    AW_pos              x, y, y_area;
1314    int                 i;
1315    ED4_AREA_LEVEL      level;
1316    ED4_multi_species_manager   *middle_area_mult_spec = NULL;
1317
1318    for (i=0; i < starting_point->children->members(); i++) {
1319        ED4_base *member = starting_point->children->member(i);
1320
1321        member->calc_world_coords( &x, &y );
1322
1323        switch (cursor_move) {
1324            case ED4_C_UP: {
1325                if (y < actual_y) {
1326                    if ((member->is_manager()) && !member->flag.hidden) {
1327                        get_upper_lower_cursor_pos( member->to_manager(), terminal, cursor_move, actual_y, terminal_is_appropriate);
1328                    }
1329
1330                    if ((member->dynamic_prop & ED4_P_CURSOR_ALLOWED)) {
1331                        if (terminal_is_appropriate==0 || terminal_is_appropriate(member)) {
1332                            *terminal = member;
1333                        }
1334                    }
1335                }
1336                break;
1337            }
1338            case ED4_C_DOWN: {
1339                if (!(*terminal)) {
1340                    if ((member->is_manager()) && !member->flag.hidden) {
1341                        get_upper_lower_cursor_pos(member->to_manager() ,terminal, cursor_move, actual_y, terminal_is_appropriate);
1342                    }
1343                    ED4_ROOT->world_to_win_coords(ED4_ROOT->temp_aww, &x, &y);
1344                    if ((member->dynamic_prop & ED4_P_CURSOR_ALLOWED) && y > actual_y) {
1345                        level = member->get_area_level(&middle_area_mult_spec);         //probably multi_species_manager of middle_area, otherwise just a dummy
1346                        if (level != ED4_A_MIDDLE_AREA) {
1347                            if (terminal_is_appropriate==0 || terminal_is_appropriate(member)) {
1348                                *terminal = member;
1349                            }
1350                        }
1351                        else if (level == ED4_A_MIDDLE_AREA) {
1352                            y_area = middle_area_mult_spec->parent->extension.position[Y_POS];
1353                            if (y > y_area) {
1354                                member = starting_point->children->member(i);
1355                                if (terminal_is_appropriate==0 || terminal_is_appropriate(member)) {
1356                                    *terminal = member;
1357                                }
1358                            }
1359                        }
1360                    }
1361                }
1362                break;
1363            }
1364            default: {
1365                e4_assert(0);
1366                break;
1367            }
1368        }
1369    }
1370    return ED4_R_OK;
1371}
1372
1373/* --------------------------------------------------------------------------------
1374   ED4_base_position
1375   -------------------------------------------------------------------------------- */
1376
1377void ED4_base_position::calc4base(ED4_base *base)
1378{
1379    e4_assert(base);
1380
1381    ED4_species_manager *species_manager =  base->get_parent(ED4_L_SPECIES)->to_species_manager();
1382    int len;
1383    int allocated = 0;
1384    char *seq;
1385
1386    if (species_manager->flag.is_consensus) {
1387        ED4_group_manager *group_manager = base->get_parent(ED4_L_GROUP)->to_group_manager();
1388
1389        seq = group_manager->table().build_consensus_string();
1390        len = strlen(seq);
1391        allocated = 1;
1392    }
1393    else {
1394        seq = base->resolve_pointer_to_string(&len);
1395    }
1396
1397    e4_assert(seq);
1398
1399    delete seq_pos;
1400    calced4base = base;
1401
1402    {
1403        int *pos = new int[len];
1404        int p;
1405
1406        count = 0;
1407        for (p=0; p<len; p++) {
1408            if (!ADPP_IS_ALIGN_CHARACTER(seq[p])) {
1409                pos[count++] = p;
1410            }
1411        }
1412
1413        seq_pos = new int[count];
1414        for (p=0; p<count; p++) {
1415            seq_pos[p] = pos[p];
1416        }
1417
1418        delete[] pos;
1419    }
1420
1421    if (allocated) delete seq;
1422}
1423int ED4_base_position::get_base_position(ED4_base *base, int sequence_position)
1424{
1425    if (!base) return 0;
1426    if (base!=calced4base) calc4base(base);
1427    if (sequence_position>seq_pos[count-1]) return count;
1428
1429    int h = count-1,
1430        l = 0;
1431
1432    while (1)
1433    {
1434        int m = (l+h)/2;
1435
1436        if (seq_pos[m]==sequence_position) {
1437            return m;
1438        }
1439        else {
1440            if (l==h) break;
1441
1442            if (sequence_position<seq_pos[m])   h = m;
1443            else                                l = m+1;
1444        }
1445    }
1446
1447    return l;
1448}
1449int ED4_base_position::get_sequence_position(ED4_base *base, int base_position)
1450{
1451    if (!base) return 0;
1452    if (base!=calced4base) calc4base(base);
1453    return base_position<count ? seq_pos[base_position] : seq_pos[count-1]+1;
1454}
1455
1456/* --------------------------------------------------------------------------------
1457             Store/Restore Cursorpositions
1458   -------------------------------------------------------------------------------- */
1459
1460class CursorPos
1461{
1462    ED4_terminal *terminal;
1463    int seq_pos;
1464
1465    CursorPos *next;
1466
1467    static CursorPos *head;
1468
1469public:
1470
1471    static void clear()
1472        {
1473            while (head) {
1474                CursorPos *p = head->next;
1475
1476                delete head;
1477                head = p;
1478            }
1479        }
1480    static CursorPos *get_head() { return head; }
1481
1482    CursorPos(ED4_terminal *t, int p)
1483        {
1484            terminal = t;
1485            seq_pos = p;
1486            next = head;
1487            head = this;
1488        }
1489    ~CursorPos() {}
1490
1491    ED4_terminal *get_terminal() const { return terminal; }
1492    int get_seq_pos() const { return seq_pos; }
1493
1494    void moveToEnd()
1495        {
1496            e4_assert(this==head);
1497
1498            if (next) {
1499                CursorPos *p = head = next;
1500
1501                while (p->next) {
1502                    p = p->next;
1503                }
1504
1505                p->next = this;
1506                this->next = 0;
1507            }
1508        }
1509};
1510
1511CursorPos *CursorPos::head = 0;
1512
1513void ED4_store_curpos(AW_window *aww, AW_CL /*cd1*/, AW_CL /*cd2*/)
1514{
1515    GB_transaction dummy(gb_main);
1516    ED4_ROOT->temp_aww  = aww;
1517    ED4_ROOT->temp_device = aww->get_device(AW_MIDDLE_AREA);
1518    ED4_ROOT->temp_ed4w = ED4_ROOT->first_window->get_matching_ed4w( aww );
1519    ED4_cursor *cursor = &ED4_ROOT->temp_ed4w->cursor;
1520    if (!cursor->owner_of_cursor) {
1521        aw_message("First you have to place the cursor.");
1522        return;
1523    }
1524
1525    new CursorPos(cursor->owner_of_cursor->to_terminal(), cursor->get_sequence_pos());
1526}
1527
1528void ED4_restore_curpos(AW_window *aww, AW_CL /*cd1*/, AW_CL /*cd2*/)
1529{
1530    GB_transaction dummy(gb_main);
1531    ED4_ROOT->temp_aww  = aww;
1532    ED4_ROOT->temp_device = aww->get_device(AW_MIDDLE_AREA);
1533    ED4_ROOT->temp_ed4w = ED4_ROOT->first_window->get_matching_ed4w( aww );
1534    ED4_cursor *cursor = &ED4_ROOT->temp_ed4w->cursor;
1535
1536    CursorPos *pos = CursorPos::get_head();
1537    if (!pos) {
1538        aw_message("No cursor position stored.");
1539        return;
1540    }
1541
1542    pos->get_terminal()->setCursorTo(cursor, pos->get_seq_pos(), 1);
1543    pos->moveToEnd();
1544}
1545
1546void ED4_clear_stored_curpos(AW_window */*aww*/, AW_CL /*cd1*/, AW_CL /*cd2*/)
1547{
1548    CursorPos::clear();
1549}
1550
1551/* --------------------------------------------------------------------------------
1552   Other stuff
1553   -------------------------------------------------------------------------------- */
1554
1555void ED4_helix_jump_opposite(AW_window *aww, AW_CL /*cd1*/, AW_CL /*cd2*/)
1556{
1557    GB_transaction dummy(gb_main);
1558    ED4_ROOT->temp_aww  = aww;
1559    ED4_ROOT->temp_device = aww->get_device(AW_MIDDLE_AREA);
1560    ED4_ROOT->temp_ed4w = ED4_ROOT->first_window->get_matching_ed4w( aww );
1561    ED4_cursor *cursor = &ED4_ROOT->temp_ed4w->cursor;
1562
1563    if (!cursor->owner_of_cursor) {
1564        aw_message("First you have to place the cursor.");
1565        return;
1566    }
1567
1568    int seq_pos = cursor->get_sequence_pos();
1569    BI_helix *helix = ED4_ROOT->helix;
1570
1571    if (size_t(seq_pos)<helix->size && helix->entries[seq_pos].pair_type) {
1572        int pairing_pos = helix->entries[seq_pos].pair_pos;
1573        e4_assert(helix->entries[pairing_pos].pair_pos==seq_pos);
1574        cursor->jump_centered_cursor_to_seq_pos(aww, pairing_pos);
1575        return;
1576    }
1577
1578    aw_message("No helix position");
1579}
1580
1581void ED4_change_cursor(AW_window */*aww*/, AW_CL /*cd1*/, AW_CL /*cd2*/) {
1582    ED4_cursor *cursor = &ED4_ROOT->temp_ed4w->cursor;
1583    ED4_CursorType typ = cursor->getType();
1584
1585    cursor->changeType((ED4_CursorType)((typ+1)%ED4_CURSOR_TYPES));
1586}
1587
Note: See TracBrowser for help on using the repository browser.