source: tags/arb_5.3/EDIT4/ED4_no_class.cxx

Last change on this file was 6358, checked in by westram, 14 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 85.2 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <math.h>
6
7#include <arbdb.h>
8#include <arbdbt.h>
9#include <ad_config.h>
10
11#include <aw_root.hxx>
12#include <aw_keysym.hxx>
13#include <aw_window.hxx>
14#include <aw_awars.hxx>
15#include <AW_helix.hxx>
16#include <awt.hxx>
17#include <awt_item_sel_list.hxx>
18#include <awt_sel_boxes.hxx>
19#include <awt_seq_colors.hxx>
20#include <AW_rename.hxx>
21
22#include <st_window.hxx>
23
24#include <ed4_extern.hxx>
25
26#include "ed4_awars.hxx"
27#include "ed4_class.hxx"
28#include "ed4_edit_string.hxx"
29#include "ed4_tools.hxx"
30#include "ed4_nds.hxx"
31
32//*************************************************
33//* functions concerning no class   beginning *
34//* Most functions are callback functions     *
35  //*************************************************
36
37void ED4_calc_terminal_extentions(){
38    const AW_font_information *seq_font_info  = ED4_ROOT->get_device()->get_font_information( ED4_G_SEQUENCES, '=' );
39    const AW_font_information *info_font_info = ED4_ROOT->get_device()->get_font_information( ED4_G_STANDARD, '.' );
40
41    int info_char_width = info_font_info->max_letter.width;
42    int seq_term_descent;
43
44    if (ED4_ROOT->helix->is_enabled() || ED4_ROOT->protstruct) { // display helix ?
45        ED4_ROOT->helix_spacing =
46            seq_font_info->this_letter.ascent // the ascent of '='
47            + ED4_ROOT->helix_add_spacing; // xtra user-defined spacing
48
49        seq_term_descent = ED4_ROOT->helix_spacing;
50    }
51    else {
52        ED4_ROOT->helix_spacing = 0;
53        seq_term_descent  = seq_font_info->max_letter.descent;
54    }
55
56    // for wanted_seq_term_height ignore descent, because it additionally allocates 'ED4_ROOT->helix_spacing' space:
57    int wanted_seq_term_height = seq_font_info->max_letter.ascent + seq_term_descent + ED4_ROOT->terminal_add_spacing;
58    int wanted_seq_info_height = info_font_info->max_letter.height + ED4_ROOT->terminal_add_spacing;
59
60    TERMINALHEIGHT = (wanted_seq_term_height>wanted_seq_info_height) ? wanted_seq_term_height : wanted_seq_info_height;
61
62    {
63        int maxchars;
64        int maxbrackets;
65
66        ED4_get_NDS_sizes(&maxchars, &maxbrackets);
67        MAXSPECIESWIDTH =
68            (maxchars+1)*info_char_width + // width defined in NDS window plus 1 char for marked-box
69            maxbrackets*BRACKETWIDTH; // brackets defined in NDS window
70    }
71    MAXINFOWIDTH = CHARACTEROFFSET + info_char_width*ED4_ROOT->aw_root->awar(ED4_AWAR_NDS_INFO_WIDTH)->read_int() + 1;
72
73    INFO_TERM_TEXT_YOFFSET = info_font_info->max_letter.ascent - 1;
74    SEQ_TERM_TEXT_YOFFSET  = seq_font_info->max_letter.ascent - 1;
75
76    if (INFO_TERM_TEXT_YOFFSET<SEQ_TERM_TEXT_YOFFSET) INFO_TERM_TEXT_YOFFSET = SEQ_TERM_TEXT_YOFFSET;
77
78#if defined(DEBUG) && 0
79    printf("seq_term_descent= %i\n", seq_term_descent);
80    printf("TERMINALHEIGHT  = %i\n", TERMINALHEIGHT);
81    printf("MAXSPECIESWIDTH = %i\n", MAXSPECIESWIDTH);
82    printf("MAXINFOWIDTH    = %i\n", MAXINFOWIDTH);
83    printf("INFO_TERM_TEXT_YOFFSET= %i\n", INFO_TERM_TEXT_YOFFSET);
84    printf("SEQ_TERM_TEXT_YOFFSET= %i\n", SEQ_TERM_TEXT_YOFFSET);
85#endif // DEBUG
86}
87
88void ED4_expose_recalculations() {
89    ED4_ROOT->recalc_font_group();
90    ED4_calc_terminal_extentions();
91
92#if defined(DEBUG)
93#warning below calculations have to be done at startup as well - maybe call expose_cb once after create_hierarchy.
94#endif // DEBUG
95
96    ED4_ROOT->ref_terminals.get_ref_sequence_info()->extension.size[HEIGHT] = TERMINALHEIGHT;
97    ED4_ROOT->ref_terminals.get_ref_sequence()->extension.size[HEIGHT]      = TERMINALHEIGHT;
98    ED4_ROOT->ref_terminals.get_ref_sequence_info()->extension.size[WIDTH]  = MAXINFOWIDTH;
99
100    int screenwidth = ED4_ROOT->root_group_man->remap()->sequence_to_screen(MAXSEQUENCECHARACTERLENGTH);
101    while (1) {
102        ED4_ROOT->ref_terminals.get_ref_sequence()->extension.size[WIDTH] =
103            ED4_ROOT->font_group.get_width(ED4_G_SEQUENCES) *
104            (screenwidth+3);
105
106        ED4_terminal *top_middle_line_terminal = ED4_ROOT->main_manager->get_top_middle_line_terminal();
107
108        ED4_ROOT->main_manager->get_top_middle_spacer_terminal()->extension.size[HEIGHT] = TERMINALHEIGHT - top_middle_line_terminal->extension.size[HEIGHT];
109
110        ED4_ROOT->main_manager->route_down_hierarchy(NULL, NULL, &update_terminal_extension );
111        ED4_ROOT->resize_all(); // may change mapping
112
113        int new_screenwidth = ED4_ROOT->root_group_man->remap()->sequence_to_screen(MAXSEQUENCECHARACTERLENGTH);
114        if (new_screenwidth == screenwidth) { // mapping did not change
115            break;
116        }
117        screenwidth = new_screenwidth;
118    }
119
120    ED4_ROOT->get_ed4w()->update_scrolled_rectangle();
121}
122
123void ED4_expose_cb( AW_window *aww, AW_CL cd1, AW_CL cd2 )
124{
125    static bool dummy = 0;
126
127    AWUSE(aww);
128    AWUSE(cd1);
129    AWUSE(cd2);
130
131    ED4_ROOT->use_window(aww);
132
133    GB_push_transaction(GLOBAL_gb_main);
134
135    if (!dummy) {
136        dummy = 1;
137    }
138    else {
139        ED4_expose_recalculations(); // this case is needed every time, except the first
140    }
141
142    ED4_ROOT->get_ed4w()->update_window_coords();
143
144    ED4_ROOT->get_device()->reset();
145    ED4_ROOT->refresh_window(1);
146
147    GB_pop_transaction(GLOBAL_gb_main);
148}
149
150void ED4_resize_cb( AW_window *aww, AW_CL cd1, AW_CL cd2 )
151{
152    AWUSE(aww);
153    AWUSE(cd1);
154    AWUSE(cd2);
155
156    ED4_ROOT->use_window(aww);
157
158    GB_push_transaction(GLOBAL_gb_main);
159
160    ED4_ROOT->get_device()->reset();
161    //  ED4_ROOT->deselect_all();
162
163    ED4_ROOT->get_ed4w()->update_scrolled_rectangle();
164
165    ED4_ROOT->get_ed4w()->slider_pos_horizontal= aww->slider_pos_horizontal;
166    ED4_ROOT->get_ed4w()->slider_pos_vertical  = aww->slider_pos_vertical;
167
168    GB_pop_transaction(GLOBAL_gb_main);
169}
170
171ED4_returncode call_edit( void **error, void **work_info_ptr, ED4_base *object )    // called after editing consensus to edit single sequences
172{
173    ED4_work_info *work_info = (ED4_work_info*)(*work_info_ptr);
174    ED4_work_info new_work_info;
175    ED4_base    *species_manager = NULL;
176//     ED4_manager  *temp_parent;
177    GB_TYPES    gb_type;
178
179    if (((char **) error)[0] || !object->is_terminal())
180        return ED4_R_BREAK;
181
182    if (object->get_species_pointer()) {
183        gb_type = GB_read_type(object->get_species_pointer());
184    }
185    else {
186        gb_type = GB_NONE;
187    }
188
189    species_manager = object->get_parent( ED4_L_SPECIES );
190
191    if (!species_manager || species_manager->flag.is_SAI) { // don't edit SAI's if editing the consensus
192        return ED4_R_BREAK;
193    }
194
195    if ((object->dynamic_prop & ED4_P_CURSOR_ALLOWED) &&
196        !species_manager->flag.is_consensus &&
197        (object->dynamic_prop & ED4_P_ALIGNMENT_DATA)) // edit all aligned data - even if not consensus relevant
198    {
199        new_work_info.event            = work_info->event;
200        new_work_info.char_position    = work_info->char_position;
201        new_work_info.out_seq_position = work_info->out_seq_position;
202        new_work_info.refresh_needed   = false;
203        new_work_info.cursor_jump      = ED4_JUMP_KEEP_VISIBLE;
204        new_work_info.out_string       = NULL;
205        new_work_info.error            = NULL;
206        new_work_info.mode             = work_info->mode;
207        new_work_info.direction        = work_info->direction;
208        new_work_info.cannot_handle    = false;
209        new_work_info.is_sequence      = work_info->is_sequence;
210        new_work_info.working_terminal = object->to_terminal();
211
212        if (object->get_species_pointer()) {
213            new_work_info.gb_data   = object->get_species_pointer();
214            new_work_info.string    = NULL;
215        }
216        else {
217            new_work_info.gb_data   = NULL;
218            new_work_info.string    = object->id;
219        }
220
221        new_work_info.repeat_count = 1;
222
223        ED4_ROOT->edit_string->init_edit(  );
224        ED4_ROOT->edit_string->edit( &new_work_info );
225
226//         if (ED4_ROOT->edit_string->old_seq)
227//         {
228//             temp_parent = species_manager->get_parent( ED4_L_MULTI_SPECIES )->to_manager();
229
230//             ((ED4_terminal *)object)->actual_timestamp = GB_read_clock(gb_main);
231
232//             char *seq = ED4_ROOT->edit_string->old_seq;
233//             int seq_len = ED4_ROOT->edit_string->old_seq_len;
234
235//             temp_parent->check_bases(seq, seq_len, species_manager);
236//         }
237
238        if (new_work_info.error) {
239            ((char **) (error))[0] = new_work_info.error;
240        }
241        else if (new_work_info.out_string) {
242            e4_assert(species_manager->flag.is_consensus);
243            object->id = new_work_info.out_string;
244        }
245
246        if (new_work_info.refresh_needed) {
247            object->set_refresh();
248            object->parent->refresh_requested_by_child();
249
250            if (object->is_sequence_terminal()) {
251                ED4_sequence_terminal *seq_term = object->to_sequence_terminal();
252                seq_term->results().searchAgain();
253            }
254        }
255
256        if (move_cursor) {
257            ED4_ROOT->get_ed4w()->cursor.jump_sequence_pos(ED4_ROOT->get_aww(), new_work_info.out_seq_position, ED4_JUMP_KEEP_VISIBLE);
258            move_cursor = 0;
259        }
260    }
261
262    return ED4_R_OK;
263}
264
265static void executeKeystroke(AW_window *aww, AW_event *event, int repeatCount) {
266    ED4_work_info *work_info = new ED4_work_info;
267    ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
268
269    if (event->keycode==AW_KEY_NONE) return;
270
271    e4_assert(repeatCount>0);
272
273    if (!cursor->owner_of_cursor || cursor->owner_of_cursor->flag.hidden) {
274        return;
275    }
276
277    if (event->keycode == AW_KEY_UP || event->keycode == AW_KEY_DOWN ||
278        ((event->keymodifier & AW_KEYMODE_CONTROL) &&
279         (event->keycode == AW_KEY_HOME || event->keycode == AW_KEY_END)))
280    {
281        GB_transaction dummy(GLOBAL_gb_main);
282        while (repeatCount--) {
283            cursor->move_cursor(event);
284        }
285        return;
286    }
287
288    work_info->cannot_handle    = false;
289    work_info->event            = *event;
290    work_info->char_position    = cursor->get_screen_pos();
291    work_info->out_seq_position = cursor->get_sequence_pos();
292    work_info->refresh_needed   = false;
293    work_info->cursor_jump      = ED4_JUMP_KEEP_VISIBLE;
294    work_info->out_string       = NULL; // nur falls new malloc
295    work_info->error            = NULL;
296    work_info->repeat_count     = repeatCount;
297
298    ED4_terminal *terminal = cursor->owner_of_cursor->to_terminal();
299    e4_assert(terminal->is_text_terminal());
300
301    work_info->working_terminal = terminal;
302
303    if (terminal->is_sequence_terminal()) {
304        work_info->mode        = awar_edit_modus;
305        work_info->direction   = awar_edit_direction;
306        work_info->is_sequence = 1;
307    }
308    else {
309        work_info->direction   = 1;
310        work_info->is_sequence = 0;
311
312        if (terminal->is_pure_text_terminal()) {
313            work_info->mode = awar_edit_modus;  // AD_INSERT; // why is AD_INSERT forced here ?
314        }
315        else if (terminal->is_columnStat_terminal()) {
316            work_info->mode = AD_NOWRITE;
317        }
318        else {
319            e4_assert(0);
320        }
321    }
322
323    work_info->string  = NULL;
324    work_info->gb_data = NULL;
325
326    if (terminal->get_species_pointer()) {
327        work_info->gb_data = terminal->get_species_pointer();
328    }
329    else if (terminal->is_columnStat_terminal()) {
330        work_info->gb_data = terminal->to_columnStat_terminal()->corresponding_sequence_terminal()->get_species_pointer();
331    }
332    else {
333        work_info->string = terminal->id;
334    }
335
336    ED4_Edit_String     *edit_string     = new ED4_Edit_String;
337    ED4_species_manager *species_manager = terminal->get_parent(ED4_L_SPECIES)->to_species_manager();
338    char                *error           = NULL;
339
340    GB_push_transaction(GLOBAL_gb_main);
341
342    if (species_manager->flag.is_consensus) {
343        ED4_group_manager *group_manager = terminal->get_parent(ED4_L_GROUP)->to_group_manager();
344
345        work_info->string = terminal->id = group_manager->table().build_consensus_string();
346
347        edit_string->edit(work_info);
348        cursor->jump_sequence_pos(aww, work_info->out_seq_position, ED4_JUMP_KEEP_VISIBLE);
349
350        work_info->string = 0;
351
352        if (work_info->cannot_handle) {
353            // group_manager = terminal->get_parent( ED4_L_GROUP )->to_group_manager();
354            move_cursor = 1;
355            if (!ED4_ROOT->edit_string) {
356                ED4_ROOT->edit_string = new ED4_Edit_String();
357            }
358            group_manager->route_down_hierarchy((void **) &error, (void **) &work_info, call_edit);
359            group_manager->rebuild_consensi( group_manager, ED4_U_UP_DOWN);
360        }
361
362        delete terminal->id;
363        terminal->id = 0;
364    }
365    else {
366        edit_string->edit( work_info );
367
368        // ED4_ROOT->main_manager->Show(); // original version
369        ED4_ROOT->main_manager->Show(1, 0); // temporary fix for worst-refresh problems
370        cursor->jump_sequence_pos(aww, work_info->out_seq_position, work_info->cursor_jump);
371    }
372
373    edit_string->finish_edit();
374
375    if (work_info->error || (error && *error == 1)) {
376        // hier evtl. nochmal route_down_hierarchy aufrufen ?!!
377        aw_message(work_info->error);
378        GB_abort_transaction(GLOBAL_gb_main);
379        ED4_ROOT->refresh_all_windows(0);
380    }
381    else {
382        GB_pop_transaction( GLOBAL_gb_main );
383
384        if (work_info->refresh_needed) {
385            GB_transaction dummy(GLOBAL_gb_main);
386
387            terminal->set_refresh();
388            terminal->parent->refresh_requested_by_child();
389            if (terminal->is_sequence_terminal()) {
390                ED4_sequence_terminal *seq_term = terminal->to_sequence_terminal();
391                seq_term->results().searchAgain();
392            }
393            ED4_ROOT->refresh_all_windows(0);
394        }
395    }
396
397    delete edit_string;
398    delete work_info;
399}
400
401void ED4_remote_event(AW_event *faked_event) { // keystrokes forwarded from SECEDIT
402    executeKeystroke(ED4_ROOT->get_aww(), faked_event, 1);
403}
404
405void ED4_input_cb(AW_window *aww,AW_CL /*cd1*/, AW_CL /*cd2*/)
406{
407    AW_event event;
408    static AW_event lastEvent;
409    static int repeatCount;
410
411    ED4_ROOT->use_window(aww);
412
413    aww->get_event(&event);
414
415#if defined(DEBUG) && 0
416    printf("event.type=%i event.keycode=%i event.character='%c' event.keymodifier=%i\n", event.type, event.keycode, event.character, event.keymodifier);
417#endif
418
419    switch(event.type) {
420        case AW_Keyboard_Press: {
421            if (repeatCount==0) { // first key event?
422                lastEvent = event;
423                repeatCount = 1;
424            }
425            else {
426                if (lastEvent.keycode==event.keycode &&
427                    lastEvent.character==event.character &&
428                    lastEvent.keymodifier==event.keymodifier) { // same key as last?
429                    repeatCount++;
430                }
431                else { // other key => execute now
432                    executeKeystroke(aww, &lastEvent, repeatCount);
433                    lastEvent = event;
434                    repeatCount = 1;
435                }
436            }
437
438            if (repeatCount) {
439#if defined(DARWIN) || 1
440                // sth goes wrong with OSX -> always execute keystroke
441                // Xfree 4.3 has problems as well, so repeat counting is disabled completely
442                executeKeystroke(aww, &lastEvent, repeatCount);
443                repeatCount                       = 0;
444#else
445                AW_ProcessEventType nextEventType = ED4_ROOT->aw_root->peek_key_event(aww);
446
447                if (nextEventType!=KEY_RELEASED) { // no key waiting => execute now
448                    executeKeystroke(aww, &lastEvent, repeatCount);
449                    repeatCount = 0;
450                }
451#endif
452            }
453            break;
454        }
455        case AW_Keyboard_Release: {
456            AW_ProcessEventType nextEventType = ED4_ROOT->aw_root->peek_key_event(aww);
457
458            if (nextEventType!=KEY_PRESSED && repeatCount) { // no key follows => execute keystrokes (if any)
459                executeKeystroke(aww, &lastEvent, repeatCount);
460                repeatCount = 0;
461            }
462
463            break;
464        }
465        default: {
466            if (event.type == AW_Mouse_Release && event.button == ED4_B_MIDDLE_BUTTON) {
467                ED4_ROOT->scroll_picture.scroll = 0;
468                return;
469            }
470            else if (event.type == AW_Mouse_Press && event.button == ED4_B_MIDDLE_BUTTON) {
471                ED4_ROOT->scroll_picture.scroll = 1;
472                ED4_ROOT->scroll_picture.old_y = event.y;
473                ED4_ROOT->scroll_picture.old_x = event.x;
474                return;
475            }
476
477#if defined(DEBUG) && 0
478            if (event.button==ED4_B_LEFT_BUTTON) {
479                printf("[ED4_input_cb]  type=%i x=%i y=%i ", (int)event.type, (int)event.x, (int)event.y);
480            }
481#endif
482
483            AW_pos win_x = event.x;
484            AW_pos win_y = event.y;
485            ED4_ROOT->win_to_world_coords( aww, &(win_x), &(win_y) );
486            event.x = (int) win_x;
487            event.y = (int) win_y;
488
489#if defined(DEBUG) && 0
490            if (event.button==ED4_B_LEFT_BUTTON) {
491                printf("-> x=%i y=%i\n", (int)event.type, (int)event.x, (int)event.y);
492            }
493#endif
494
495            GB_transaction dummy(GLOBAL_gb_main);
496            ED4_ROOT->main_manager->event_sent_by_parent( &event, aww );
497            break;
498        }
499    }
500}
501
502static int get_max_slider_xpos() {
503    AW_rectangle rect;
504    ED4_ROOT->get_device()->get_area_size(&rect); // screensize
505
506    AW_pos x, y;
507    ED4_base *horizontal_link = ED4_ROOT->scroll_links.link_for_hor_slider;
508    horizontal_link->calc_world_coords(&x, &y);
509
510    AW_pos max_xpos = horizontal_link->extension.size[WIDTH] // overall width of virtual scrolling area
511        - (rect.r - x); // minus width of visible scroll-area (== relative width of horizontal scrollbar)
512
513    if (max_xpos<0) max_xpos = 0; // happens when window-content is smaller then window (e.g. if ARB_EDIT4 is not filled)
514    return int(max_xpos+0.5);
515}
516
517static int get_max_slider_ypos() {
518    AW_rectangle rect;
519    ED4_ROOT->get_device()->get_area_size(&rect); // screensize
520
521    AW_pos x, y;
522    ED4_base *vertical_link = ED4_ROOT->scroll_links.link_for_ver_slider;
523    vertical_link->calc_world_coords(&x, &y);
524
525    AW_pos max_ypos = vertical_link->extension.size[HEIGHT] // overall width of virtual scrolling area
526        - (rect.b - y); // minus width of visible scroll-area (== relative width of horizontal scrollbar)
527
528    if (max_ypos<0) max_ypos = 0; // happens when window-content is smaller then window (e.g. if ARB_EDIT4 is not filled)
529    return int(max_ypos+0.5);
530}
531
532void ED4_vertical_change_cb( AW_window *aww, AW_CL cd1, AW_CL cd2 )
533{
534    AWUSE(cd1);
535    AWUSE(cd2);
536
537    ED4_ROOT->use_window(aww);
538
539    GB_push_transaction(GLOBAL_gb_main);
540
541    ED4_window *win = ED4_ROOT->get_ed4w();
542    int old_slider_pos = win->slider_pos_vertical;
543
544    { // correct slider_pos if neccessary
545        int max_slider_ypos = get_max_slider_ypos();
546
547        if (aww->slider_pos_vertical>max_slider_ypos) aww->set_vertical_scrollbar_position(max_slider_ypos);
548        if (aww->slider_pos_vertical<0)               aww->set_vertical_scrollbar_position(0);
549    }
550
551    int slider_diff = aww->slider_pos_vertical - old_slider_pos;
552
553    win->coords.window_upper_clip_point += slider_diff;
554    win->coords.window_lower_clip_point += slider_diff;
555
556    win->scroll_rectangle(0, -slider_diff);
557    win->slider_pos_vertical = aww->slider_pos_vertical;
558
559    GB_pop_transaction(GLOBAL_gb_main);
560    win->update_window_coords();
561}
562
563void ED4_horizontal_change_cb( AW_window *aww, AW_CL cd1, AW_CL cd2 )
564{
565    AWUSE(cd1);
566    AWUSE(cd2);
567
568    ED4_ROOT->use_window(aww);
569
570    GB_push_transaction(GLOBAL_gb_main);
571
572    ED4_window *win = ED4_ROOT->get_ed4w();
573    int old_slider_pos = win->slider_pos_horizontal;
574
575    { // correct slider_pos if neccessary
576        int max_slider_xpos = get_max_slider_xpos();
577
578        if (aww->slider_pos_horizontal>max_slider_xpos) aww->set_horizontal_scrollbar_position(max_slider_xpos);
579        if (aww->slider_pos_horizontal<0)               aww->set_horizontal_scrollbar_position(0);
580    }
581
582    int slider_diff = aww->slider_pos_horizontal - old_slider_pos;
583
584    win->coords.window_left_clip_point  += slider_diff;
585    win->coords.window_right_clip_point += slider_diff;
586
587    win->scroll_rectangle(-slider_diff, 0);
588    win->slider_pos_horizontal = aww->slider_pos_horizontal;
589
590    GB_pop_transaction(GLOBAL_gb_main);
591    win->update_window_coords();
592}
593
594void ED4_scrollbar_change_cb(AW_window *aww, AW_CL cd1, AW_CL cd2)
595{
596    AWUSE(cd1);
597    AWUSE(cd2);
598
599    ED4_ROOT->use_window(aww);
600
601    GB_push_transaction(GLOBAL_gb_main);
602
603    ED4_window *win = ED4_ROOT->get_ed4w();
604
605    int old_hslider_pos = win->slider_pos_horizontal;
606    int old_vslider_pos = win->slider_pos_vertical;
607
608    { // correct slider_pos if neccessary
609        int max_slider_xpos = get_max_slider_xpos();
610        int max_slider_ypos = get_max_slider_ypos();
611
612        if (aww->slider_pos_horizontal>max_slider_xpos) aww->set_horizontal_scrollbar_position(max_slider_xpos);
613        if (aww->slider_pos_horizontal<0)               aww->set_horizontal_scrollbar_position(0);
614
615        if (aww->slider_pos_vertical>max_slider_ypos) aww->set_vertical_scrollbar_position(max_slider_ypos);
616        if (aww->slider_pos_vertical<0)               aww->set_vertical_scrollbar_position(0);
617    }
618
619    int slider_hdiff = aww->slider_pos_horizontal - old_hslider_pos;
620    int slider_vdiff = aww->slider_pos_vertical   - old_vslider_pos;
621
622    ED4_coords *coords = &win->coords;
623    coords->window_left_clip_point  += slider_hdiff;
624    coords->window_right_clip_point += slider_hdiff;
625    coords->window_upper_clip_point += slider_vdiff;
626    coords->window_lower_clip_point += slider_vdiff;
627
628    win->scroll_rectangle( -slider_hdiff, -slider_vdiff);
629
630    win->slider_pos_vertical   = aww->slider_pos_vertical;
631    win->slider_pos_horizontal = aww->slider_pos_horizontal;
632
633    GB_pop_transaction(GLOBAL_gb_main);
634    win->update_window_coords();
635    //    paintMarksOfSelectedObjects();
636}
637
638void ED4_motion_cb( AW_window *aww, AW_CL cd1, AW_CL cd2 )
639{
640    AWUSE(cd1);
641    AWUSE(cd2);
642    AW_event event;
643
644    ED4_ROOT->use_window(aww);
645
646    aww->get_event(&event);
647
648    if (event.type == AW_Mouse_Drag && event.button == ED4_B_MIDDLE_BUTTON) {
649        if (ED4_ROOT->scroll_picture.scroll) {
650            int xdiff    = ED4_ROOT->scroll_picture.old_x - event.x;
651            int ydiff    = ED4_ROOT->scroll_picture.old_y - event.y;
652            int new_xpos = aww->slider_pos_horizontal + (xdiff*ED4_ROOT->aw_root->awar(ED4_AWAR_SCROLL_SPEED_X)->read_int())/10;
653            int new_ypos = aww->slider_pos_vertical   + (ydiff*ED4_ROOT->aw_root->awar(ED4_AWAR_SCROLL_SPEED_Y)->read_int())/10;
654
655            if (xdiff<0) { // scroll left
656                if (new_xpos<0) new_xpos = 0;
657            }
658            else if (xdiff>0) { // scroll right
659                int max_xpos = get_max_slider_xpos();
660                if (max_xpos<0) max_xpos = 0;
661                if (new_xpos>max_xpos) new_xpos = max_xpos;
662            }
663
664            if (ydiff<0) { // scroll left
665                if (new_ypos<0) new_ypos = 0;
666            }
667            else if (ydiff>0) { // scroll right
668                int max_ypos = get_max_slider_ypos();
669                if (max_ypos<0) max_ypos = 0;
670                if (new_ypos>max_ypos) new_ypos = max_ypos;
671            }
672
673            if (new_xpos!=aww->slider_pos_horizontal) {
674                aww->set_horizontal_scrollbar_position(new_xpos);
675                ED4_horizontal_change_cb(aww, cd1, cd2 );
676                ED4_ROOT->scroll_picture.old_x = event.x;
677            }
678
679            if (new_ypos!=aww->slider_pos_vertical) {
680                aww->set_vertical_scrollbar_position(new_ypos);
681                ED4_vertical_change_cb(aww, cd1, cd2 );
682                ED4_ROOT->scroll_picture.old_y = event.y;
683            }
684        }
685    }
686    else {
687
688#if defined(DEBUG) && 0
689        if (event.button==ED4_B_LEFT_BUTTON) {
690            printf("[ED4_motion_cb] type=%i x=%i y=%i ", (int)event.type, (int)event.x, (int)event.y);
691        }
692#endif
693
694        AW_pos win_x = event.x;
695        AW_pos win_y = event.y;
696        ED4_ROOT->win_to_world_coords( aww, &win_x, &win_y);
697        event.x = (int) win_x;
698        event.y = (int) win_y;
699
700#if defined(DEBUG) && 0
701        if (event.button==ED4_B_LEFT_BUTTON) {
702            printf("-> x=%i y=%i\n", (int)event.type, (int)event.x, (int)event.y);
703        }
704#endif
705
706        GB_transaction dummy(GLOBAL_gb_main);
707        ED4_ROOT->main_manager->event_sent_by_parent( &event, aww );
708    }
709}
710
711void ED4_remote_set_cursor_cb(AW_root *awr, AW_CL /*cd1*/, AW_CL /*cd2*/)
712{
713    AW_awar *awar = awr->awar(AWAR_SET_CURSOR_POSITION);
714    long     pos  = awar->read_int();
715
716    if (pos != -1) {
717        ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
718        cursor->jump_sequence_pos(ED4_ROOT->get_aww(), pos, ED4_JUMP_CENTERED);
719        awar->write_int(-1);
720    }
721}
722
723void ED4_jump_to_cursor_position(AW_window *aww, char *awar_name, bool /*callback_flag*/)           // callback function
724{
725    ED4_ROOT->use_window(aww);
726
727    ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
728    GB_ERROR    error  = 0;
729
730    long pos = aww->get_root()->awar(awar_name)->read_int();
731    if (pos>0) pos--;                               // user->real position (userpos is 1..n)
732
733    ED4_remap *remap  = ED4_ROOT->root_group_man->remap();
734    long       max    = remap->screen_to_sequence(remap->get_max_screen_pos());
735    if(pos > max) pos = max;
736
737    if (strcmp(awar_name, ED4_ROOT->get_ed4w()->awar_path_for_Ecoli)==0) { // callback from ecoli
738        BI_ecoli_ref *ecoli = ED4_ROOT->ecoli_ref;
739
740        if (ecoli->gotData()) pos = ecoli->rel_2_abs(pos);
741        else error = "No ecoli reference";
742    }
743    else if (strcmp(awar_name, ED4_ROOT->get_ed4w()->awar_path_for_basePos)==0) { // callback from basePos
744        pos = cursor->base2sequence_position(pos);
745    }
746
747    if (error) {
748        aw_message(error);
749    }
750    else {
751        cursor->jump_sequence_pos(aww, pos, ED4_JUMP_CENTERED);
752    }
753}
754
755void ED4_set_helixnr(AW_window *aww, char *awar_name, bool /*callback_flag*/)
756{
757    ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
758
759    if (cursor->owner_of_cursor) {
760        AW_root    *root     = aww->get_root();
761        const char *helix_nr = root->awar(awar_name)->read_string();
762        BI_helix   *helix    = ED4_ROOT->helix;
763
764        if (helix->has_entries()) {
765            long pos = helix->first_position(helix_nr);
766
767            if (pos == -1) {
768                aw_message(GBS_global_string("No helix '%s' found", helix_nr));
769            }
770            else {
771                cursor->jump_sequence_pos(aww, pos, ED4_JUMP_CENTERED);
772            }
773        }
774        else {
775            aw_message("Got no helix information");
776        }
777    }
778}
779
780void ED4_set_iupac(AW_window */*aww*/, char *awar_name, bool /*callback_flag*/)
781{
782    ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
783
784    if (cursor->owner_of_cursor) {
785        ED4_species_manager *species_manager =  cursor->owner_of_cursor->get_parent(ED4_L_SPECIES)->to_species_manager();
786
787        if (species_manager->flag.is_consensus) {
788            aw_message("You cannot change the consensus");
789            return;
790        }
791        int len;
792        char *seq = cursor->owner_of_cursor->resolve_pointer_to_string_copy(&len);
793        int seq_pos = cursor->get_sequence_pos();
794
795        e4_assert(seq);
796
797        if (seq_pos<len) {
798            const char *iupac = ED4_ROOT->aw_root->awar(awar_name)->read_string();
799            char new_char = ED4_encode_iupac(iupac, ED4_ROOT->alignment_type);
800
801            seq[seq_pos] = new_char;
802            cursor->owner_of_cursor->write_sequence(seq, len);
803        }
804
805        free(seq);
806    }
807}
808
809void ED4_gc_is_modified(AW_window *aww,AW_CL cd1, AW_CL cd2)                        // callback if gc is modified
810{
811    ED4_ROOT->use_window(aww);
812
813    ED4_resize_cb(aww,cd1,cd2);
814    ED4_expose_cb(aww,cd1,cd2);
815}
816
817void ED4_exit() {
818    ED4_ROOT->aw_root->unlink_awars_from_DB(GLOBAL_gb_main);
819
820    ED4_window *ed4w = ED4_ROOT->first_window;
821
822    while (ed4w) {
823        ed4w->aww->hide();
824        ed4w->cursor.invalidate_base_position();
825        ed4w = ed4w->next;
826    }
827
828    delete ED4_ROOT->main_manager;
829
830    while (ED4_ROOT->first_window)
831        ED4_ROOT->first_window->delete_window(ED4_ROOT->first_window);
832
833    GBDATA *gb_main = GLOBAL_gb_main;
834    GLOBAL_gb_main  = NULL;
835#if defined(DEBUG)
836    AWT_browser_forget_db(gb_main);
837#endif // DEBUG
838    GB_close(gb_main);
839
840    ::exit(0);
841}
842
843void ED4_quit_editor(AW_window *aww, AW_CL /*cd1*/, AW_CL /*cd2*/) {
844    ED4_ROOT->use_window(aww);
845
846    if (ED4_ROOT->first_window == ED4_ROOT->get_ed4w()) { // quit button has been pressed in first window
847        ED4_exit();
848    }
849    // case : in another window close has been pressed
850    ED4_ROOT->get_aww()->hide();
851    ED4_ROOT->get_ed4w()->is_hidden = true;
852}
853
854void ED4_load_data( AW_window *aww, AW_CL cd1, AW_CL cd2 )
855{
856    ED4_ROOT->use_window(aww);
857
858    AWUSE(aww);
859    AWUSE(cd1);
860    AWUSE(cd2);
861}
862
863void ED4_save_data( AW_window *aww, AW_CL cd1, AW_CL cd2 )
864{
865    ED4_ROOT->use_window(aww);
866
867    AWUSE(aww);
868    AWUSE(cd1);
869    AWUSE(cd2);
870}
871
872void ED4_timer_refresh()
873{
874    GB_begin_transaction(GLOBAL_gb_main);                  // for callbacks from database
875    //    ED4_ROOT->refresh_all_windows(0);
876    GB_tell_server_dont_wait(GLOBAL_gb_main);
877    GB_commit_transaction(GLOBAL_gb_main);
878}
879
880void ED4_timer(AW_root *, AW_CL cd1, AW_CL cd2 )
881{
882    //    last_used_timestamp = GB_read_clock(gb_main);
883    ED4_timer_refresh();
884    ED4_ROOT->aw_root->add_timed_callback(200,ED4_timer,cd1,cd2);
885}
886
887void ED4_refresh_window( AW_window *aww, AW_CL cd_called_from_menu, AW_CL /*cd2*/ )
888{
889    GB_transaction dummy(GLOBAL_gb_main);
890
891    if (int(cd_called_from_menu)) {
892        ED4_ROOT->use_window(aww);
893    }
894
895    ED4_main_manager *mainman = ED4_ROOT->main_manager;
896    if (mainman) { // avoids a crash durin startup
897        if (mainman->update_info.delete_requested) {
898            mainman->delete_requested_childs();
899        }
900
901        //    ED4_ROOT->deselect_all();
902        mainman->update_info.set_clear_at_refresh(1);
903        mainman->Show(1);
904    }
905}
906
907void ED4_set_reference_species( AW_window *aww, AW_CL disable, AW_CL cd2 ){
908    GB_transaction dummy(GLOBAL_gb_main);
909
910    if (disable) {
911        ED4_ROOT->reference->init();
912    }
913    else {
914        ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
915
916        if (cursor->owner_of_cursor) {
917            ED4_terminal *terminal = cursor->owner_of_cursor->to_terminal();
918            ED4_manager *manager = terminal->parent->parent->to_manager();
919
920            if (manager->flag.is_consensus) {
921                ED4_char_table *table = &terminal->get_parent(ED4_L_GROUP)->to_group_manager()->table();
922                char *consensus = table->build_consensus_string();
923
924                ED4_ROOT->reference->init("CONSENSUS", consensus, table->size());
925            }
926            else if (manager->parent->flag.is_SAI) {
927                char *name = GBT_read_string(GLOBAL_gb_main,AWAR_SPECIES_NAME);
928                int   datalen;
929                char *data = terminal->resolve_pointer_to_string_copy(&datalen);
930
931                ED4_ROOT->reference->init(name, data, datalen);
932
933                free(data);
934                free(name);
935            }
936            else {
937                char *name = GBT_read_string(GLOBAL_gb_main,AWAR_SPECIES_NAME);
938
939                ED4_ROOT->reference->init(name, ED4_ROOT->alignment_name);
940                delete name;
941            }
942        }
943        else {
944            aw_message("First you have to place your cursor");
945        }
946    }
947
948    ED4_refresh_window(aww,0,cd2);
949}
950
951static void show_detailed_column_stats_activated(AW_window *aww) {
952    ED4_ROOT->column_stat_initialized = 1;
953    ED4_show_detailed_column_stats(aww, 0, 0);
954}
955
956double ED4_columnStat_terminal::threshold = -1;
957int ED4_columnStat_terminal::threshold_is_set() {
958    return threshold>=0 && threshold<=100;
959}
960void ED4_columnStat_terminal::set_threshold(double aThreshold) {
961    threshold = aThreshold;
962    e4_assert(threshold_is_set());
963}
964
965void ED4_set_col_stat_threshold(AW_window */*aww*/, AW_CL cl_do_refresh, AW_CL) {
966    double default_threshold = 90.0;
967    if (ED4_columnStat_terminal::threshold_is_set()) {
968        default_threshold = ED4_columnStat_terminal::get_threshold();
969    }
970    char default_input[40];
971    sprintf(default_input, "%6.2f", default_threshold);
972
973    char *input = aw_input("Please insert threshold value for marking:", default_input);
974    if (input) {
975        double input_threshold = atof(input);
976
977        if (input_threshold<0 || input_threshold>100) {
978            aw_message("Illegal threshold value (allowed: 0..100)");
979        }
980        else {
981            ED4_columnStat_terminal::set_threshold(input_threshold);
982            if (int(cl_do_refresh)) {
983                ED4_ROOT->refresh_all_windows(1);
984            }
985        }
986        free(input);
987    }
988}
989
990void ED4_show_detailed_column_stats(AW_window *aww, AW_CL, AW_CL)
991{
992    while (!ED4_columnStat_terminal::threshold_is_set()) {
993        ED4_set_col_stat_threshold(aww, 0, 0);
994    }
995
996    ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
997    if (!cursor->owner_of_cursor) {
998        aw_message("First you have to place your cursor");
999        return;
1000    }
1001
1002    ED4_terminal *cursor_terminal = cursor->owner_of_cursor->to_terminal();
1003    ED4_manager *cursor_manager = cursor_terminal->parent->parent->to_manager();
1004    if (!cursor_terminal->is_sequence_terminal() || cursor_manager->flag.is_consensus || cursor_manager->parent->flag.is_SAI) {
1005        aw_message("Display of column-statistic-details is only possible for species!");
1006        return;
1007    }
1008
1009    ED4_sequence_terminal *seq_term = cursor_terminal->to_sequence_terminal();
1010    if (!seq_term->st_ml_node && !(seq_term->st_ml_node=st_ml_convert_species_name_to_node(ED4_ROOT->st_ml, seq_term->species_name))) {
1011        if (ED4_ROOT->column_stat_initialized) {
1012            aw_message("Cannot display column statistics for this species (internal error?)");
1013            return;
1014        }
1015        AW_window *aww_st = st_create_main_window(ED4_ROOT->aw_root,ED4_ROOT->st_ml,(AW_CB0)show_detailed_column_stats_activated,(AW_window *)aww);
1016        aww_st->show();
1017        return;
1018    }
1019
1020    ED4_multi_sequence_manager *multi_seq_man = cursor_manager->to_multi_sequence_manager();
1021    char buffer[35];
1022    int count = 1;
1023    sprintf( buffer, "Sequence_Manager.%ld.%d", ED4_counter, count++);
1024
1025    ED4_sequence_manager *new_seq_man = new ED4_sequence_manager(buffer, 0, 0, 0, 0, multi_seq_man);
1026    new_seq_man->set_properties(ED4_P_MOVABLE);
1027    multi_seq_man->children->append_member(new_seq_man);
1028
1029    int pixel_length = max_seq_terminal_length;
1030#if defined(DEBUG) && 1
1031    printf("max_seq_terminal_length=%li\n", max_seq_terminal_length);
1032#endif
1033
1034    AW_pos font_height = ED4_ROOT->font_group.get_height(ED4_G_SEQUENCES);
1035    AW_pos columnStatHeight = ceil((COLUMN_STAT_ROWS+0.5/* reserve a bit more space*/)*COLUMN_STAT_ROW_HEIGHT(font_height));
1036    ED4_columnStat_terminal *ref_colStat_terminal = ED4_ROOT->ref_terminals.get_ref_column_stat();
1037    ref_colStat_terminal->extension.size[HEIGHT] = columnStatHeight;
1038    ref_colStat_terminal->extension.size[WIDTH] = pixel_length;
1039
1040    ED4_sequence_info_terminal *ref_colStat_info_terminal = ED4_ROOT->ref_terminals.get_ref_column_stat_info();
1041    ED4_sequence_info_terminal *new_colStat_info_term = new ED4_sequence_info_terminal("CStat", /*0,*/ 0, 0, SEQUENCEINFOSIZE, columnStatHeight, new_seq_man);
1042    new_colStat_info_term->set_properties( (ED4_properties) (ED4_P_SELECTABLE | ED4_P_DRAGABLE | ED4_P_IS_HANDLE) );
1043    new_colStat_info_term->set_links(ref_colStat_info_terminal, ref_colStat_terminal);
1044    new_seq_man->children->append_member(new_colStat_info_term);
1045
1046    sprintf( buffer, "Column_Statistic_Terminal.%ld.%d", ED4_counter, count++);
1047    ED4_columnStat_terminal *new_colStat_term = new ED4_columnStat_terminal(buffer, SEQUENCEINFOSIZE, 0, 0, columnStatHeight, new_seq_man);
1048    new_colStat_term->set_properties(ED4_P_CURSOR_ALLOWED);
1049    new_colStat_term->set_links(ref_colStat_terminal, ref_colStat_terminal);
1050    //    new_colStat_term->extension.size[WIDTH] = pixel_length;
1051    new_seq_man->children->append_member(new_colStat_term);
1052
1053    ED4_counter++;
1054
1055    new_seq_man->resize_requested_by_child();
1056    ED4_ROOT->refresh_all_windows(0);
1057}
1058
1059ED4_returncode update_terminal_extension( void **/*arg1*/, void **/*arg2*/, ED4_base *this_object )
1060{
1061    if (this_object->is_terminal()){
1062        if (this_object->is_spacer_terminal()){
1063            if (this_object->parent->is_device_manager()) { // the rest is managed by reference links
1064                ;
1065                //      this_object->extension.size[HEIGHT] = TERMINALHEIGHT / 2;   // @@@ Zeilenabstand verringern hier?
1066            }
1067        }
1068        else if (this_object->is_species_name_terminal()) {
1069            this_object->extension.size[WIDTH] = MAXSPECIESWIDTH - BRACKETWIDTH * this_object->calc_group_depth();
1070        }
1071        else if (this_object->is_sequence_info_terminal()) {
1072            this_object->extension.size[WIDTH] = MAXINFOWIDTH;
1073        }
1074        else if (this_object->is_line_terminal()) { // thought for line terminals which are direct children of the device manager
1075            this_object->extension.size[WIDTH] =
1076                TREETERMINALSIZE + MAXSPECIESWIDTH +
1077                ED4_ROOT->ref_terminals.get_ref_sequence_info()->extension.size[WIDTH] +
1078                ED4_ROOT->ref_terminals.get_ref_sequence()->extension.size[WIDTH];
1079        }
1080    }
1081
1082    if (this_object->parent) {
1083        this_object->parent->resize_requested_by_child();
1084    }
1085
1086    return ED4_R_OK;
1087}
1088
1089#define SIGNIFICANT_FIELD_CHARS 30 // length used to compare field contents (in createGroupFromSelected)
1090
1091static void createGroupFromSelected(GB_CSTR group_name, GB_CSTR field_name, GB_CSTR field_content)
1092    // creates a new group named group_name
1093    // if field_name==0 -> all selected species & subgroups are moved to this new group
1094    // if field_name!=0 -> all selected species containing field_content in field field_name are moved to this new group
1095{
1096    ED4_group_manager *group_manager = NULL;
1097    ED4_ROOT->main_manager->create_group(&group_manager, group_name);
1098    ED4_manager *top_area = ED4_ROOT->main_manager->search_spec_child_rek(ED4_L_AREA)->to_manager();
1099    ED4_multi_species_manager *multi_species_manager = top_area->search_spec_child_rek( ED4_L_MULTI_SPECIES )->to_multi_species_manager();
1100
1101    group_manager->extension.position[Y_POS] = 2;
1102    ED4_base::touch_world_cache();
1103    multi_species_manager->children->append_member( group_manager );
1104    group_manager->parent = (ED4_manager *) multi_species_manager;
1105
1106    multi_species_manager = group_manager->get_defined_level( ED4_L_MULTI_SPECIES )->to_multi_species_manager();
1107
1108    ED4_list_elem *list_elem = ED4_ROOT->selected_objects.first();
1109    while (list_elem) {
1110        ED4_base *object = ((ED4_selection_entry *) list_elem->elem())->object;
1111        object = object->get_parent( ED4_L_SPECIES );
1112        int move_object = 1;
1113
1114        if (object->flag.is_consensus) {
1115            object = object->get_parent( ED4_L_GROUP );
1116            if (field_name) move_object = 0; // don't move groups if moving by field_name
1117        }
1118        else {
1119            e4_assert(object->is_species_manager());
1120            if (field_name) {
1121                GBDATA *gb_species = object->get_species_pointer();
1122                GBDATA *gb_field = GB_search(gb_species, field_name, GB_FIND);
1123
1124                if (gb_field) { // field was found
1125                    int type = gb_field->flags.type;
1126                    if (type==GB_STRING) {
1127                        char *found_content = GB_read_as_string(gb_field);
1128                        move_object = strncmp(found_content, field_content, SIGNIFICANT_FIELD_CHARS)==0;
1129                        free(found_content);
1130                    }
1131                    else {
1132                        e4_assert(0); // field has to be string field
1133                    }
1134                }
1135                else { // field was NOT found
1136                    move_object = field_content==0 || field_content[0]==0; // move object if we search for no content
1137                }
1138            }
1139        }
1140
1141        if (move_object) {
1142            object->parent->children->delete_member(object);
1143
1144            ED4_base *base = object->get_parent(ED4_L_MULTI_SPECIES);
1145            if (base && base->is_multi_species_manager()) {
1146                ED4_multi_species_manager *old_multi = base->to_multi_species_manager();
1147                old_multi->invalidate_species_counters();
1148            }
1149            multi_species_manager->children->append_member( object );
1150
1151            object->parent = ( ED4_manager * )multi_species_manager;
1152            object->set_width();
1153        }
1154
1155        list_elem = list_elem->next();
1156    }
1157
1158    group_manager->create_consensus(group_manager);
1159    group_manager->get_defined_level(ED4_L_MULTI_SPECIES)->to_multi_species_manager()->count_all_children_and_set_group_id();
1160
1161    {
1162        ED4_bracket_terminal *bracket = group_manager->get_defined_level(ED4_L_BRACKET)->to_bracket_terminal();
1163
1164        if (bracket) {
1165            group_manager->fold_group(bracket->id);
1166        }
1167    }
1168
1169    multi_species_manager->resize_requested_by_child();
1170
1171    ED4_ROOT->get_ed4w()->update_scrolled_rectangle();
1172    ED4_ROOT->get_device()->reset();
1173    ED4_ROOT->refresh_all_windows(1);
1174}
1175
1176static void group_species(int use_field, AW_window *use_as_main_window) {
1177    GB_ERROR error = 0;
1178    GB_push_transaction(GLOBAL_gb_main);
1179
1180    ED4_ROOT->use_window(use_as_main_window);
1181
1182    if (!use_field) {
1183        char *group_name = aw_input("Enter name for new group:");
1184
1185        if (group_name) {
1186            if (strlen(group_name)>GB_GROUP_NAME_MAX) {
1187                group_name[GB_GROUP_NAME_MAX] = 0;
1188                aw_message("Truncated too long group name");
1189            }
1190            createGroupFromSelected(group_name, 0, 0);
1191            free(group_name);
1192        }
1193    }
1194    else {
1195        const char *field_name   = ED4_ROOT->aw_root->awar(AWAR_FIELD_CHOSEN)->read_string();
1196        char       *doneContents = strdup(";");
1197        size_t      doneLen      = 1;
1198
1199        int tryAgain     = 1;
1200        int foundField   = 0;
1201        int foundSpecies = 0;
1202
1203        while (tryAgain && !error) {
1204            tryAgain = 0;
1205            ED4_list_elem *list_elem = ED4_ROOT->selected_objects.first();
1206            while (list_elem && !error) {
1207                ED4_base *object = ((ED4_selection_entry *) list_elem->elem())->object;
1208                object = object->get_parent( ED4_L_SPECIES );
1209                if (!object->flag.is_consensus) {
1210                    GBDATA *gb_species = object->get_species_pointer();
1211                    GBDATA *gb_field = GB_search(gb_species, field_name, GB_FIND);
1212
1213                    if (gb_species) {
1214                        foundSpecies = 1;
1215                    }
1216
1217                    if (gb_field) {
1218                        int type = gb_field->flags.type;
1219
1220                        if (type==GB_STRING) {
1221                            char   *field_content     = GB_read_as_string(gb_field);
1222                            size_t  field_content_len = strlen(field_content);
1223
1224                            foundField = 1;
1225                            if (field_content_len>SIGNIFICANT_FIELD_CHARS) {
1226                                field_content[SIGNIFICANT_FIELD_CHARS] = 0;
1227                                field_content_len                      = SIGNIFICANT_FIELD_CHARS;
1228                            }
1229
1230                            char with_semi[SIGNIFICANT_FIELD_CHARS+2+1];
1231                            sprintf(with_semi, ";%s;", field_content);
1232
1233                            if (strstr(doneContents, with_semi)==0) { // field_content was not used yet
1234                                createGroupFromSelected(field_content, field_name, field_content);
1235                                tryAgain = 1;
1236
1237                                int newlen = doneLen + field_content_len + 1;
1238                                char *newDone = (char*)malloc(newlen+1);
1239                                GBS_global_string_to_buffer(newDone, newlen, "%s%s;", doneContents, field_content);
1240                                freeset(doneContents, newDone);
1241                                doneLen = newlen;
1242                            }
1243                            free(field_content);
1244                        }
1245                        else {
1246                            error = "You have to use a string type field";
1247                        }
1248                    }
1249                }
1250                list_elem = list_elem->next();
1251            }
1252        }
1253
1254        if (!foundSpecies) {
1255            error = "Please select some species in order to insert them into new groups";
1256        }
1257        else if (!foundField) {
1258            error = GB_export_errorf("Field not found: '%s'", field_name);
1259        }
1260    }
1261
1262    GB_end_transaction_show_error(GLOBAL_gb_main, error, aw_message);
1263}
1264
1265static void group_species2_cb(AW_window*, AW_CL cl_use_as_main_window, AW_CL cl_window_to_hide) {
1266    group_species(1, (AW_window*)cl_use_as_main_window);
1267    ((AW_window*)cl_window_to_hide)->hide();
1268}
1269
1270static AW_window *create_group_species_by_field_window(AW_root *aw_root, AW_window *use_as_main_window) {
1271    AW_window_simple *aws = new AW_window_simple;
1272
1273    aws->init(aw_root, "CREATE_GROUP_USING_FIELD", "Create group using field");
1274    aws->load_xfig("edit4/choose_field.fig");
1275
1276    aws->button_length(20);
1277    aws->at("doit");
1278    aws->callback(group_species2_cb, (AW_CL)use_as_main_window, (AW_CL)aws);
1279    aws->create_button("USE_FIELD","Use selected field","");
1280
1281    aws->button_length(10);
1282    aws->at("close");
1283    aws->callback( (AW_CB0)AW_POPDOWN);
1284    aws->create_button("CLOSE", "CLOSE","C");
1285
1286    awt_create_selection_list_on_scandb(GLOBAL_gb_main, (AW_window*)aws, AWAR_FIELD_CHOSEN, -1, "source",0, &AWT_species_selector, 20, 10);
1287
1288    return aws;
1289}
1290
1291void group_species_cb(AW_window *aww, AW_CL cl_use_fields, AW_CL) {
1292
1293    int use_fields = int(cl_use_fields);
1294
1295    if (!use_fields) {
1296        group_species(0, aww);
1297    }
1298    else {
1299        static AW_window *ask_field_window;
1300
1301        if (!ask_field_window) ask_field_window = create_group_species_by_field_window(ED4_ROOT->aw_root, aww);
1302        ask_field_window->activate();
1303    }
1304}
1305
1306void ED4_load_new_config(char *string)
1307{
1308    char *config_data_top    = NULL;
1309    char *config_data_middle = NULL;
1310
1311    ED4_window     *window;
1312    GB_transaction  dummy(GLOBAL_gb_main);
1313
1314
1315    ED4_ROOT->main_manager->clear_whole_background();
1316    ED4_calc_terminal_extentions();
1317
1318    max_seq_terminal_length = 0;
1319   
1320    ED4_init_notFoundMessage();
1321
1322
1323    if ( ED4_ROOT->selected_objects.no_of_entries() > 0 ) {
1324        ED4_ROOT->deselect_all();
1325    }
1326
1327    ED4_ROOT->scroll_picture.scroll         = 0;
1328    ED4_ROOT->scroll_picture.old_x          = 0;
1329    ED4_ROOT->scroll_picture.old_y          = 0;
1330
1331    ED4_ROOT->ref_terminals.clear();
1332
1333    for (window=ED4_ROOT->first_window; window; window=window->next) {
1334        window->cursor.init();
1335        window->aww->set_horizontal_scrollbar_position ( 0 );
1336        window->aww->set_vertical_scrollbar_position ( 0 );
1337    }
1338
1339    ED4_ROOT->scroll_links.link_for_hor_slider  = NULL;
1340    ED4_ROOT->scroll_links.link_for_ver_slider  = NULL;
1341    ED4_ROOT->middle_area_man           = NULL;
1342    ED4_ROOT->top_area_man              = NULL;
1343
1344    delete ED4_ROOT->main_manager;
1345    ED4_ROOT->main_manager              = NULL;
1346    delete ED4_ROOT->ecoli_ref;
1347    {
1348        GB_push_transaction(GLOBAL_gb_main);
1349        GBDATA *gb_configuration = GBT_find_configuration(GLOBAL_gb_main, string);
1350        GBDATA *gb_middle_area = GB_search(gb_configuration, "middle_area", GB_FIND);
1351        GBDATA *gb_top_area = GB_search(gb_configuration, "top_area", GB_FIND);
1352        config_data_middle = GB_read_as_string(gb_middle_area);
1353        config_data_top = GB_read_as_string(gb_top_area);
1354        GB_pop_transaction(GLOBAL_gb_main);
1355    }
1356
1357    ED4_ROOT->first_window->reset_all_for_new_config();
1358
1359    ED4_ROOT->create_hierarchy( config_data_middle, config_data_top );
1360    ED4_ROOT->refresh_all_windows(1);
1361
1362    free(config_data_middle);
1363    free(config_data_top);
1364}
1365
1366static long ED4_get_edit_modus(AW_root *root)
1367{
1368    if (!root->awar(AWAR_EDIT_MODE)->read_int()) {
1369        return AD_ALIGN;
1370    }
1371    return root->awar(AWAR_INSERT_MODE)->read_int() ? AD_INSERT : AD_REPLACE;
1372}
1373
1374void ed4_changesecurity(AW_root *root, AW_CL /*cd1*/)
1375{
1376    long mode = ED4_get_edit_modus(root);
1377    long level;
1378    const char *awar_name = 0;
1379
1380    switch (mode){
1381        case AD_ALIGN:
1382            awar_name = AWAR_EDIT_SECURITY_LEVEL_ALIGN;
1383            break;
1384        default:
1385            awar_name = AWAR_EDIT_SECURITY_LEVEL_CHANGE;
1386    }
1387
1388    ED4_ROOT->aw_root->awar(AWAR_EDIT_SECURITY_LEVEL)->map(awar_name);
1389    level = ED4_ROOT->aw_root->awar(awar_name)->read_int();
1390    GB_change_my_security (GLOBAL_gb_main, level, "");
1391}
1392
1393void ed4_change_edit_mode(AW_root *root, AW_CL cd1)
1394{
1395    awar_edit_modus = (ad_edit_modus)ED4_get_edit_modus(root);
1396    ed4_changesecurity(root, cd1);
1397}
1398
1399ED4_returncode rebuild_consensus(void **/*arg1*/, void **/*arg2*/, ED4_base *object)                // arg1 and arg2 are NULL-values !!!
1400{
1401    if ( object->flag.is_consensus) {
1402        ED4_species_manager *spec_man = object->to_species_manager();
1403        spec_man->do_callbacks();
1404
1405        ED4_base *sequence_data_terminal = object->search_spec_child_rek( ED4_L_SEQUENCE_STRING );
1406
1407        sequence_data_terminal->set_refresh();
1408        sequence_data_terminal->parent->refresh_requested_by_child();
1409    }
1410    return ED4_R_OK;
1411}
1412
1413void ED4_new_editor_window( AW_window *aww, AW_CL /*cd1*/, AW_CL /*cd2*/ )
1414{
1415    ED4_ROOT->use_window(aww);
1416
1417    AW_device  *device;
1418    ED4_window *new_window = 0;
1419   
1420    if (ED4_ROOT->generate_window( &device, &new_window) == ED4_R_BREAK) // don't open more then five windows
1421        return;
1422
1423    ED4_ROOT->use_window(new_window);
1424
1425    new_window->set_scrolled_rectangle( 0, 0, 0, 0, ED4_ROOT->scroll_links.link_for_hor_slider,
1426                                        ED4_ROOT->scroll_links.link_for_ver_slider,
1427                                        ED4_ROOT->scroll_links.link_for_hor_slider,
1428                                        ED4_ROOT->scroll_links.link_for_ver_slider );
1429
1430    new_window->aww->show();
1431    new_window->update_scrolled_rectangle();
1432
1433    ED4_ROOT->use_window(aww);
1434}
1435
1436
1437
1438void ED4_start_editor_on_configuration(AW_window *aww){
1439    aww->hide();
1440    char *cn = aww->get_root()->awar(AWAR_EDIT_CONFIGURATION)->read_string();
1441
1442    ED4_load_new_config(cn);
1443    free(cn);
1444}
1445
1446void ED4_compression_changed_cb(AW_root *awr){
1447    ED4_remap_mode mode = (ED4_remap_mode)awr->awar(ED4_AWAR_COMPRESS_SEQUENCE_TYPE)->read_int();
1448    int percent = awr->awar(ED4_AWAR_COMPRESS_SEQUENCE_PERCENT)->read_int();
1449    GB_transaction transaction_var(GLOBAL_gb_main);
1450
1451    if (ED4_ROOT->root_group_man) {
1452        ED4_cursor& cursor  = ED4_ROOT->get_ed4w()->cursor;
1453        int         rel_pos = cursor.get_screen_relative_pos();
1454        int         seq_pos = cursor.get_sequence_pos();
1455
1456        AW_window *aww    = ED4_ROOT->get_aww();
1457        AW_device *device = ED4_ROOT->get_device();
1458
1459        ED4_remap *remap = ED4_ROOT->root_group_man->remap();
1460        remap->set_mode(mode, percent);
1461
1462        device->push_clip_scale();
1463        device->set_clipall();     // draw nothing
1464
1465        ED4_expose_recalculations();
1466
1467        cursor.jump_sequence_pos(aww, seq_pos, ED4_JUMP_KEEP_POSITION);
1468        cursor.set_screen_relative_pos(aww, rel_pos);
1469
1470        ED4_expose_cb(aww, 0, 0); // does pop_clip_scale + refresh
1471    }
1472}
1473
1474void ED4_compression_toggle_changed_cb(AW_root *root, AW_CL cd1, AW_CL /*cd2*/)
1475{
1476    //    static int cst_change_denied;
1477
1478    int gaps = root->awar(ED4_AWAR_COMPRESS_SEQUENCE_GAPS)->read_int();
1479    int hide = root->awar(ED4_AWAR_COMPRESS_SEQUENCE_HIDE)->read_int();
1480    ED4_remap_mode mode = ED4_remap_mode(root->awar(ED4_AWAR_COMPRESS_SEQUENCE_TYPE)->read_int());
1481
1482    switch(int(cd1)) {
1483        case 0: { // ED4_AWAR_COMPRESS_SEQUENCE_GAPS changed
1484            if (gaps!=2 && hide!=0) {
1485                root->awar(ED4_AWAR_COMPRESS_SEQUENCE_HIDE)->write_int(0);
1486                return;
1487            }
1488            break;
1489        }
1490        case 1: { // ED4_AWAR_COMPRESS_SEQUENCE_HIDE changed
1491            if (hide!=0 && gaps!=2) {
1492                root->awar(ED4_AWAR_COMPRESS_SEQUENCE_GAPS)->write_int(2);
1493                return;
1494            }
1495            break;
1496        }
1497        default: {
1498            e4_assert(0);
1499            break;
1500        }
1501    }
1502
1503    mode = ED4_RM_NONE;
1504    switch (gaps) {
1505        case 0: mode = ED4_RM_NONE; break;
1506        case 1: mode = ED4_RM_DYNAMIC_GAPS; break;
1507        case 2: {
1508            switch(hide) {
1509                case 0: mode = ED4_RM_MAX_ALIGN; break;
1510                case 1: mode = ED4_RM_SHOW_ABOVE; break;
1511                default: e4_assert(0); break;
1512            }
1513            break;
1514        }
1515        default: e4_assert(0); break;
1516    }
1517
1518    root->awar(ED4_AWAR_COMPRESS_SEQUENCE_TYPE)->write_int(int(mode));
1519}
1520
1521//  -------------------------------------------------------------------
1522//      AW_window *ED4_create_level_1_options_window(AW_root *root)
1523//  -------------------------------------------------------------------
1524AW_window *ED4_create_level_1_options_window(AW_root *root){
1525    AW_window_simple *aws = new AW_window_simple;
1526
1527    aws->init( root, "EDIT4_PROPS","EDIT4 Options");
1528    aws->load_xfig("edit4/options.fig");
1529
1530    aws->callback( (AW_CB0)AW_POPDOWN);
1531    aws->at("close");
1532    aws->create_button("CLOSE", "CLOSE","C");
1533
1534    aws->callback( AW_POPUP_HELP,(AW_CL)"e4_options.hlp");
1535    aws->at("help");
1536    aws->create_button("HELP","HELP","H");
1537
1538    //  -----------------------------------
1539    //      Online Sequence Compression
1540
1541    aws->at("gaps");
1542    aws->create_toggle_field(ED4_AWAR_COMPRESS_SEQUENCE_GAPS);
1543    aws->insert_default_toggle("Show all gaps", "A", 0);
1544    aws->insert_toggle("Show some gaps", "S", 1);
1545    aws->insert_toggle("Hide all gaps", "H", 2);
1546    aws->update_toggle_field();
1547
1548    aws->at("hide");
1549    aws->create_toggle_field(ED4_AWAR_COMPRESS_SEQUENCE_HIDE);
1550    aws->insert_default_toggle("Hide no Nucleotides", "0", 0);
1551    aws->insert_toggle("Hide columns with less than...", "1", 1);
1552    aws->update_toggle_field();
1553
1554    aws->at("percent");
1555    aws->create_input_field(ED4_AWAR_COMPRESS_SEQUENCE_PERCENT);
1556
1557    //  --------------
1558    //      Layout
1559
1560    aws->at("seq_helix");
1561    aws->create_input_field(AWAR_EDIT_HELIX_SPACING);
1562
1563    aws->at("seq_seq");
1564    aws->create_input_field(AWAR_EDIT_TERMINAL_SPACING);
1565
1566    //  --------------------
1567    //      Scroll-Speed
1568
1569    aws->at("scroll_x");
1570    aws->create_input_field(ED4_AWAR_SCROLL_SPEED_X);
1571
1572    aws->at("scroll_y");
1573    aws->create_input_field(ED4_AWAR_SCROLL_SPEED_Y);
1574
1575    aws->at("margin");
1576    aws->create_input_field(ED4_AWAR_SCROLL_MARGIN);
1577
1578    //  ---------------
1579    //      Editing
1580
1581    aws->at("gapchars");
1582    aws->create_input_field(ED4_AWAR_GAP_CHARS);
1583
1584    aws->at("repeat");
1585    aws->label("Use digits to repeat edit commands?");
1586    aws->create_toggle(ED4_AWAR_DIGITS_AS_REPEAT);
1587
1588    aws->at("fast");
1589    aws->label("Should Ctrl-Cursor jump over next group?");
1590    aws->create_toggle(ED4_AWAR_FAST_CURSOR_JUMP);
1591
1592    aws->at("checksum");
1593    aws->label("Announce all checksum changes\ncaused by editing commands.");
1594    aws->create_toggle(ED4_AWAR_ANNOUNCE_CHECKSUM_CHANGES);
1595
1596    return aws;
1597}
1598
1599/* Open window to show IUPAC tables */
1600static AW_window * CON_showgroupswin_cb( AW_root *aw_root)
1601{
1602    AW_window_simple *aws = new AW_window_simple;
1603    aws->init( aw_root, "SHOW_IUPAC", "Show IUPAC");
1604    aws->load_xfig("consensus/groups.fig");
1605    aws->button_length( 7 );
1606
1607    aws->at("ok");aws->callback((AW_CB0)AW_POPDOWN);
1608    aws->create_button("CLOSE","CLOSE","O");
1609
1610    return aws;
1611}
1612
1613
1614AW_window *ED4_create_consensus_definition_window(AW_root *root) {
1615    static AW_window_simple *aws = 0;
1616
1617    if (!aws) {
1618        aws = new AW_window_simple;
1619
1620        aws->init(root, "EDIT4_CONSENSUS", "EDIT4 Consensus Definition");
1621        aws->load_xfig("edit4/consensus.fig");
1622
1623        aws->callback((AW_CB0)AW_POPDOWN);
1624        aws->at("close");
1625        aws->create_button("CLOSE", "CLOSE","C");
1626
1627        aws->callback( AW_POPUP_HELP,(AW_CL)"e4_consensus.hlp");
1628        aws->at("help");
1629        aws->create_button("HELP","HELP","H");
1630
1631        aws->button_length(10);
1632        aws->at("showgroups");aws->callback(AW_POPUP,(AW_CL)CON_showgroupswin_cb,0);
1633        aws->create_button("SHOW_IUPAC", "show\nIUPAC...","s");
1634
1635        aws->at("countgaps");
1636        aws->create_toggle_field(ED4_AWAR_CONSENSUS_COUNTGAPS);
1637        aws->insert_toggle("on","1", 1);
1638        aws->insert_default_toggle("off","0", 0);
1639        aws->update_toggle_field();
1640
1641        aws->at("gapbound");
1642        aws->create_input_field(ED4_AWAR_CONSENSUS_GAPBOUND, 4);
1643
1644        aws->at("group");
1645        aws->create_toggle_field(ED4_AWAR_CONSENSUS_GROUP);
1646        aws->insert_toggle("on", "1", 1);
1647        aws->insert_default_toggle("off", "0", 0);
1648        aws->update_toggle_field();
1649
1650        aws->at("considbound");
1651        aws->create_input_field(ED4_AWAR_CONSENSUS_CONSIDBOUND, 4);
1652
1653        aws->at("upper");
1654        aws->create_input_field(ED4_AWAR_CONSENSUS_UPPER, 4);
1655
1656        aws->at("lower");
1657        aws->create_input_field(ED4_AWAR_CONSENSUS_LOWER, 4);
1658
1659        aws->at("show");
1660        aws->label("Display consensus?");
1661        aws->create_toggle(ED4_AWAR_CONSENSUS_SHOW);
1662    }
1663
1664    return aws;
1665}
1666
1667void ED4_create_consensus_awars(AW_root *aw_root)
1668{
1669    GB_transaction dummy(GLOBAL_gb_main);
1670
1671    aw_root->awar_int(ED4_AWAR_CONSENSUS_COUNTGAPS, 1)->add_callback(ED4_consensus_definition_changed, 0, 0);
1672    aw_root->awar_int(ED4_AWAR_CONSENSUS_GAPBOUND, 60)->add_callback(ED4_consensus_definition_changed, 0, 0);
1673    aw_root->awar_int(ED4_AWAR_CONSENSUS_GROUP, 1)->add_callback(ED4_consensus_definition_changed, 0, 0);
1674    aw_root->awar_int(ED4_AWAR_CONSENSUS_CONSIDBOUND, 30)->add_callback(ED4_consensus_definition_changed, 0, 0);
1675    aw_root->awar_int(ED4_AWAR_CONSENSUS_UPPER, 95)->add_callback(ED4_consensus_definition_changed, 0, 0);
1676    aw_root->awar_int(ED4_AWAR_CONSENSUS_LOWER, 70)->add_callback(ED4_consensus_definition_changed, 0, 0);
1677
1678    AW_awar *cons_show = aw_root->awar_int(ED4_AWAR_CONSENSUS_SHOW, 1);
1679
1680    cons_show->write_int(1);
1681    cons_show->add_callback(ED4_consensus_display_changed, 0, 0);
1682}
1683
1684void ED4_restart_editor(AW_window *aww, AW_CL, AW_CL)
1685{
1686    ED4_start_editor_on_configuration(aww);
1687}
1688
1689AW_window *ED4_start_editor_on_old_configuration(AW_root *awr)
1690{
1691    static AW_window_simple *aws = 0;
1692
1693    if (aws) return (AW_window *)aws;
1694    aws = new AW_window_simple;
1695    aws->init( awr, "LOAD_OLD_CONFIGURATION", "SELECT A CONFIGURATION");
1696    aws->at(10,10);
1697    aws->auto_space(0,0);
1698    awt_create_selection_list_on_configurations(GLOBAL_gb_main,(AW_window *)aws,AWAR_EDIT_CONFIGURATION);
1699    aws->at_newline();
1700
1701    aws->callback((AW_CB0)ED4_start_editor_on_configuration);
1702    aws->create_button("LOAD","LOAD");
1703
1704    aws->callback(AW_POPDOWN);
1705    aws->create_button("CLOSE","CLOSE","C");
1706
1707    aws->window_fit();
1708    return (AW_window *)aws;
1709}
1710
1711void ED4_save_configuration(AW_window *aww,AW_CL close_flag){
1712    char *cn = aww->get_root()->awar(AWAR_EDIT_CONFIGURATION)->read_string();
1713    if (close_flag) aww->hide();
1714
1715    ED4_ROOT->database->generate_config_string( cn );
1716
1717    free(cn);
1718}
1719
1720AW_window *ED4_save_configuration_as_open_window(AW_root *awr){
1721    static AW_window_simple *aws = 0;
1722    if (aws) return (AW_window *)aws;
1723    aws = new AW_window_simple;
1724    aws->init( awr, "SAVE_CONFIGURATION", "SAVE A CONFIGURATION");
1725    aws->load_xfig("edit4/save_config.fig");
1726
1727    aws->at("close");
1728    aws->callback(AW_POPDOWN);
1729    aws->create_button("CLOSE","CLOSE");
1730
1731    aws->at("help");
1732    aws->callback(AW_POPUP_HELP,(AW_CL)"configuration.hlp");
1733    aws->create_button("HELP","HELP");
1734
1735    aws->at("save");
1736    aws->create_input_field(AWAR_EDIT_CONFIGURATION);
1737
1738    aws->at("confs");
1739    awt_create_selection_list_on_configurations(GLOBAL_gb_main,aws,AWAR_EDIT_CONFIGURATION);
1740
1741    aws->at("go");
1742    aws->callback(ED4_save_configuration, 1);
1743    aws->create_button("SAVE","SAVE");
1744
1745    return aws;
1746}
1747
1748static GB_ERROR createDataFromConsensus(GBDATA *gb_species, ED4_group_manager *group_man)
1749{
1750    GB_ERROR error = 0;
1751    ED4_char_table *table = &group_man->table();
1752    char *consensus = table->build_consensus_string();
1753    int len = table->size();
1754    int p;
1755    char *equal_to = ED4_ROOT->aw_root->awar(ED4_AWAR_CREATE_FROM_CONS_REPL_EQUAL)->read_string();
1756    char *point_to = ED4_ROOT->aw_root->awar(ED4_AWAR_CREATE_FROM_CONS_REPL_POINT)->read_string();
1757    int allUpper = ED4_ROOT->aw_root->awar(ED4_AWAR_CREATE_FROM_CONS_ALL_UPPER)->read_int();
1758
1759    for (p=0; p<len; p++) {
1760        switch (consensus[p]) {
1761            case '=': consensus[p] = equal_to[0]; break;
1762            case '.': consensus[p] = point_to[0]; break;
1763            default: {
1764                if (allUpper) {
1765                    consensus[p] = toupper(consensus[p]);
1766                }
1767                break;
1768            }
1769        }
1770    }
1771
1772    if (ED4_ROOT->aw_root->awar(ED4_AWAR_CREATE_FROM_CONS_CREATE_POINTS)) { // points at start & end of sequence?
1773        for (p=0; p<len; p++) {
1774            if (!ADPP_IS_ALIGN_CHARACTER(consensus[p])) break;
1775            consensus[p] = '.';
1776        }
1777        for (p=len-1; p>=0; p--) {
1778            if (!ADPP_IS_ALIGN_CHARACTER(consensus[p])) break;
1779            consensus[p] = '.';
1780        }
1781    }
1782
1783    GB_CSTR ali = GBT_get_default_alignment(GLOBAL_gb_main);
1784    GBDATA *gb_ali = GB_search(gb_species, ali, GB_DB);
1785    if (gb_ali) {
1786        GBDATA *gb_data = GB_search(gb_ali, "data", GB_STRING);
1787        error = GB_write_pntr(gb_data, consensus, len+1, len);
1788    }
1789    else {
1790        error = GB_export_errorf("Can't find alignment '%s'", ali);
1791    }
1792    free(consensus);
1793    return error;
1794}
1795
1796// --------------------------------------------------------------------------------
1797
1798struct S_SpeciesMergeList {
1799    GBDATA *species;
1800    char *species_name;
1801    struct S_SpeciesMergeList *next;
1802
1803};
1804typedef struct S_SpeciesMergeList *SpeciesMergeList;
1805
1806static ED4_returncode add_species_to_merge_list(void **SpeciesMergeListPtr, void **GBDATAPtr, ED4_base *base)
1807{
1808    if (base->is_species_name_terminal()) {
1809        ED4_species_name_terminal *name_term       = base->to_species_name_terminal();
1810        char                      *species_name    = name_term->resolve_pointer_to_string_copy();
1811        GBDATA                    *gb_species_data = (GBDATA*)GBDATAPtr;
1812        GBDATA                    *gb_species      = GBT_find_species_rel_species_data(gb_species_data, species_name);
1813
1814        if (gb_species) {
1815            SpeciesMergeList *smlp = (SpeciesMergeList*)SpeciesMergeListPtr;
1816            SpeciesMergeList sml = new S_SpeciesMergeList;
1817            sml->species = gb_species;
1818            sml->species_name = strdup(species_name);
1819            sml->next = *smlp;
1820            *smlp = sml;
1821        }
1822
1823        free(species_name);
1824    }
1825    return ED4_R_OK;
1826}
1827static int SpeciesMergeListLength(SpeciesMergeList sml)
1828{
1829    int length = 0;
1830
1831    while (sml) {
1832        length++;
1833        sml = sml->next;
1834    }
1835
1836    return length;
1837}
1838static void freeSpeciesMergeList(SpeciesMergeList sml) {
1839    while (sml) {
1840        free(sml->species_name);
1841        freeset(sml, sml->next);
1842    }
1843}
1844
1845// --------------------------------------------------------------------------------
1846
1847inline bool nameIsUnique(const char *short_name, GBDATA *gb_species_data) {
1848    return GBT_find_species_rel_species_data(gb_species_data, short_name)==0;
1849}
1850
1851static void create_new_species(AW_window */*aww*/, AW_CL cl_creation_mode)
1852    // creation_mode ==     0 -> create new species
1853    //                      1 -> create new species from group konsensus
1854    //                      2 -> copy current species
1855{
1856    enum e_creation_mode { CREATE_NEW_SPECIES, CREATE_FROM_CONSENSUS, COPY_SPECIES } creation_mode = (enum e_creation_mode)(cl_creation_mode);
1857    GB_CSTR new_species_full_name = ED4_ROOT->aw_root->awar(ED4_AWAR_SPECIES_TO_CREATE)->read_string(); // this contains the full_name now!
1858    GB_CSTR error = 0;
1859
1860    e4_assert(creation_mode>=0 && creation_mode<=2);
1861
1862    if (!new_species_full_name || new_species_full_name[0]==0) {
1863        error = GB_export_error("Please enter a full_name for the new species");
1864    }
1865    else {
1866        error                    = GB_begin_transaction(GLOBAL_gb_main);
1867        GBDATA *gb_species_data  = GB_search(GLOBAL_gb_main, "species_data",  GB_CREATE_CONTAINER);
1868        char   *new_species_name = 0;
1869        char   *acc              = 0;
1870        char   *addid            = 0;
1871
1872        enum e_dataSource { MERGE_FIELDS, COPY_FIELDS } dataSource = (enum e_dataSource)ED4_ROOT->aw_root ->awar(ED4_AWAR_CREATE_FROM_CONS_DATA_SOURCE)->read_int();
1873        enum { NOWHERE, ON_SPECIES, ON_KONSENSUS } where_we_are = NOWHERE;
1874        ED4_terminal *cursor_terminal = 0;
1875
1876        if (!error) {
1877            if (creation_mode==CREATE_FROM_CONSENSUS || creation_mode==COPY_SPECIES) {
1878                ED4_cursor *cursor = &ED4_ROOT->get_ed4w()->cursor;
1879
1880                if (cursor->owner_of_cursor) {
1881                    cursor_terminal = cursor->owner_of_cursor->to_terminal();
1882
1883                    if (cursor_terminal->parent->parent->flag.is_consensus) {
1884                        where_we_are = ON_KONSENSUS;
1885                    }
1886                    else {
1887                        where_we_are = ON_SPECIES;
1888                    }
1889                }
1890            }
1891
1892            if (creation_mode==COPY_SPECIES || (creation_mode==CREATE_FROM_CONSENSUS && dataSource==COPY_FIELDS)) {
1893                if (where_we_are==ON_SPECIES) {
1894                    ED4_species_name_terminal *spec_name   = cursor_terminal->to_sequence_terminal()->corresponding_species_name_terminal();
1895                    const char                *source_name = spec_name->resolve_pointer_to_char_pntr();
1896                    GBDATA                    *gb_source   = GBT_find_species_rel_species_data(gb_species_data, source_name);
1897
1898                    GBDATA *gb_acc  = GB_search(gb_source, "acc", GB_FIND);
1899                    if (gb_acc) acc = GB_read_string(gb_acc); // if has accession
1900
1901                    const char *add_field = AW_get_nameserver_addid(GLOBAL_gb_main);
1902                    GBDATA     *gb_addid  = add_field[0] ? GB_search(gb_source, add_field, GB_FIND) : 0;
1903                    if (gb_addid) addid   = GB_read_as_string(gb_addid);
1904                }
1905                else {
1906                    error = "Please place cursor on a species";
1907                }
1908            }
1909        }
1910
1911        if (!error) {
1912            UniqueNameDetector *existingNames = 0;
1913
1914            if (creation_mode==0) {
1915                error = "It's no good idea to create the short-name for a new species using the nameserver! (has no acc yet)";
1916            }
1917            else {
1918                error = AWTC_generate_one_name(GLOBAL_gb_main, new_species_full_name, acc, addid, new_species_name, true, true);
1919                if (!error) {   // name was created
1920                    if (!nameIsUnique(new_species_name, gb_species_data)) {
1921                        if (!existingNames) existingNames = new UniqueNameDetector(gb_species_data);
1922                        freeset(new_species_name, AWTC_makeUniqueShortName(new_species_name, *existingNames));
1923                        if (!new_species_name) error = GB_await_error();
1924                    }
1925                }
1926            }
1927
1928            if (error) {        // try to make a random name
1929                const char *msg = GBS_global_string("%s\nGenerating a random name instead.", error);
1930                aw_message(msg);
1931                error           = 0;
1932
1933                if (!existingNames) existingNames = new UniqueNameDetector(gb_species_data);
1934                new_species_name = AWTC_generate_random_name(*existingNames);
1935
1936                if (!new_species_name) {
1937                    error = GBS_global_string("Failed to create a new name for '%s'", new_species_full_name);
1938                }
1939            }
1940
1941            if (existingNames) delete existingNames;
1942        }
1943
1944        if (!error) {
1945            GBDATA *gb_new_species = 0;
1946
1947            if (!error) {
1948                if (creation_mode==CREATE_NEW_SPECIES) {
1949                    GBDATA *gb_created_species = GBT_find_or_create_species(GLOBAL_gb_main, new_species_name);
1950                    if (!gb_created_species) {
1951                        error = GBS_global_string("Failed to create new species '%s'", new_species_name);
1952                    }
1953                    else {
1954                        GB_CSTR  ali    = GBT_get_default_alignment(GLOBAL_gb_main);
1955                        GBDATA  *gb_ali = GB_search(gb_created_species, ali, GB_DB);
1956
1957                        if (gb_ali) error = GBT_write_string(gb_ali, "data", ".......");
1958                        else error        = GBS_global_string("Can't create alignment '%s' (Reason: %s)", ali, GB_await_error());
1959                    }
1960                    if (!error) error = GBT_write_string(gb_created_species, "full_name", new_species_full_name);
1961                }
1962                else if (creation_mode==CREATE_FROM_CONSENSUS && dataSource==MERGE_FIELDS)
1963                { // create from consensus (merge fields from all species in container)
1964                    if (where_we_are==NOWHERE) {
1965                        error = "Please place cursor on any sequence/consensus of group";
1966                    }
1967                    else {
1968                        ED4_group_manager *group_man = cursor_terminal->get_parent(ED4_L_GROUP)->to_group_manager();
1969                        SpeciesMergeList sml = 0; // list of species in group
1970
1971                        group_man->route_down_hierarchy((void**)&sml, (void**)gb_species_data, add_species_to_merge_list);
1972                        if (sml==0) {
1973                            error = "Please choose a none empty group!";
1974                        }
1975
1976                        if (!error) {
1977                            GBDATA *gb_source = sml->species;
1978                            gb_new_species = GB_create_container(gb_species_data, "species");
1979                            error = GB_copy(gb_new_species, gb_source); // copy first found species to create a new species
1980                        }
1981                        if (!error) error = GBT_write_string(gb_new_species, "name", new_species_name); // insert new 'name'
1982                        if (!error) error = GBT_write_string(gb_new_species, "full_name", new_species_full_name); // insert new 'full_name'
1983                        if (!error) error = createDataFromConsensus(gb_new_species, group_man); // insert consensus as 'data'
1984
1985                        if (!error) {
1986                            char *doneFields = strdup(";name;"); // all fields which are already merged
1987                            int doneLen = strlen(doneFields);
1988                            SpeciesMergeList sl = sml;
1989                            int sl_length = SpeciesMergeListLength(sml);
1990                            int *fieldStat = new int[sl_length]; // 0 = not used yet ; -1 = don't has field ;
1991                            // 1..n = field content (same number means same content)
1992
1993                            while (sl && !error) { // with all species do..
1994                                char *newFields = GB_get_subfields(sl->species);
1995                                char *fieldStart = newFields; // points to ; before next field
1996
1997                                while (fieldStart[1] && !error) { // with all subfields of the species do..
1998                                    char *fieldEnd = strchr(fieldStart+1, ';');
1999
2000                                    e4_assert(fieldEnd);
2001                                    char behind = fieldEnd[1];
2002                                    fieldEnd[1] = 0;
2003
2004                                    if (strstr(doneFields, fieldStart)==0) { // field is not merged yet
2005                                        char *fieldName = fieldStart+1;
2006                                        int fieldLen = int(fieldEnd-fieldName);
2007
2008                                        e4_assert(fieldEnd[0]==';');
2009                                        fieldEnd[0] = 0;
2010
2011                                        GBDATA *gb_field = GB_search(sl->species, fieldName, GB_FIND);
2012                                        e4_assert(gb_field); // field has to exist, cause it was found before
2013                                        int type = gb_field->flags.type; //GB_TYPE(gb_field);
2014                                        if (type==GB_STRING) { // we only merge string fields
2015                                            int i;
2016                                            int doneSpecies = 0;
2017                                            int nextStat = 1;
2018
2019                                            for (i=0; i<sl_length; i++) { // clear field status
2020                                                fieldStat[i] = 0;
2021                                            }
2022
2023                                            while (doneSpecies<sl_length) { // since all species in list were handled
2024                                                SpeciesMergeList sl2 = sml;
2025                                                i = 0;
2026
2027                                                while (sl2) {
2028                                                    if (fieldStat[i]==0) {
2029                                                        gb_field = GB_search(sl2->species, fieldName, GB_FIND);
2030                                                        if (gb_field) {
2031                                                            char *content = GB_read_as_string(gb_field);
2032                                                            SpeciesMergeList sl3 = sl2->next;
2033
2034                                                            fieldStat[i] = nextStat;
2035                                                            doneSpecies++;
2036                                                            int j = i+1;
2037                                                            while (sl3) {
2038                                                                if (fieldStat[j]==0) {
2039                                                                    gb_field = GB_search(sl3->species, fieldName, GB_FIND);
2040                                                                    if (gb_field) {
2041                                                                        char *content2 = GB_read_as_string(gb_field);
2042
2043                                                                        if (strcmp(content, content2)==0) { // if contents are the same, they get the same status
2044                                                                            fieldStat[j] = nextStat;
2045                                                                            doneSpecies++;
2046                                                                        }
2047                                                                        free(content2);
2048                                                                    }
2049                                                                    else {
2050                                                                        fieldStat[j] = -1;
2051                                                                        doneSpecies++;
2052                                                                    }
2053                                                                }
2054                                                                sl3 = sl3->next;
2055                                                                j++;
2056                                                            }
2057
2058                                                            free(content);
2059                                                            nextStat++;
2060                                                        }
2061                                                        else {
2062                                                            fieldStat[i] = -1; // field does not exist here
2063                                                            doneSpecies++;
2064                                                        }
2065                                                    }
2066                                                    sl2 = sl2->next;
2067                                                    i++;
2068                                                }
2069                                            }
2070
2071                                            e4_assert(nextStat!=1); // this would mean that none of the species contained the field
2072
2073                                            {
2074                                                char *new_content = 0;
2075                                                int new_content_len = 0;
2076
2077                                                if (nextStat==2) { // all species contain same field content or do not have the field
2078                                                    SpeciesMergeList sl2 = sml;
2079
2080                                                    while (sl2) {
2081                                                        gb_field = GB_search(sl2->species, fieldName, GB_FIND);
2082                                                        if (gb_field) {
2083                                                            new_content = GB_read_as_string(gb_field);
2084                                                            new_content_len = strlen(new_content);
2085                                                            break;
2086                                                        }
2087                                                        sl2 = sl2->next;
2088                                                    }
2089                                                }
2090                                                else { // different field contents
2091                                                    int actualStat;
2092                                                    for (actualStat=1; actualStat<nextStat; actualStat++) {
2093                                                        int names_len = 1; // open bracket
2094                                                        SpeciesMergeList sl2 = sml;
2095                                                        i = 0;
2096                                                        char *content = 0;
2097
2098                                                        while (sl2) {
2099                                                            if (fieldStat[i]==actualStat) {
2100                                                                names_len += strlen(sl2->species_name)+1;
2101                                                                if (!content) {
2102                                                                    gb_field = GB_search(sl2->species, fieldName, GB_FIND);
2103                                                                    e4_assert(gb_field);
2104                                                                    content = GB_read_as_string(gb_field);
2105                                                                }
2106                                                            }
2107                                                            sl2 = sl2->next;
2108                                                            i++;
2109                                                        }
2110
2111                                                        e4_assert(content);
2112                                                        int add_len = names_len+1+strlen(content);
2113                                                        char *whole = (char*)malloc(new_content_len+1+add_len+1);
2114                                                        e4_assert(whole);
2115                                                        char *add = new_content ? whole+sprintf(whole, "%s ", new_content) : whole;
2116                                                        sl2 = sml;
2117                                                        i = 0;
2118                                                        int first = 1;
2119                                                        while (sl2) {
2120                                                            if (fieldStat[i]==actualStat) {
2121                                                                add += sprintf(add, "%c%s", first ? '{' : ';', sl2->species_name);
2122                                                                first = 0;
2123                                                            }
2124                                                            sl2 = sl2->next;
2125                                                            i++;
2126                                                        }
2127                                                        add += sprintf(add, "} %s", content);
2128
2129                                                        free(content);
2130
2131                                                        freeset(new_content, whole);
2132                                                        new_content_len = strlen(new_content);
2133                                                    }
2134                                                }
2135
2136                                                if (new_content) {
2137                                                    error = GBT_write_string(gb_new_species, fieldName, new_content);
2138                                                    free(new_content);
2139                                                }
2140                                            }
2141                                        }
2142
2143                                        // mark field as done:
2144                                        char *new_doneFields = (char*)malloc(doneLen+fieldLen+1+1);
2145                                        sprintf(new_doneFields, "%s%s;", doneFields, fieldName);
2146                                        doneLen += fieldLen+1;
2147                                        freeset(doneFields, new_doneFields);
2148
2149                                        fieldEnd[0] = ';';
2150                                    }
2151
2152                                    fieldEnd[1] = behind;
2153                                    fieldStart = fieldEnd;
2154                                }
2155                                free(newFields);
2156                                sl = sl->next;
2157                            }
2158                            free(doneFields);
2159                            free(fieldStat);
2160                        }
2161                        freeSpeciesMergeList(sml); sml = 0;
2162                    }
2163                }
2164                else { // copy species or create from consensus (copy fields from one species)
2165                    e4_assert(where_we_are==ON_SPECIES);
2166
2167                    ED4_species_name_terminal *spec_name   = cursor_terminal->to_sequence_terminal()->corresponding_species_name_terminal();
2168                    const char                *source_name = spec_name->resolve_pointer_to_char_pntr();
2169                    GBDATA                    *gb_source   = GBT_find_species_rel_species_data(gb_species_data, source_name);
2170
2171                    if (gb_source) {
2172                        gb_new_species    = GB_create_container(gb_species_data, "species");
2173                        error             = GB_copy(gb_new_species, gb_source);
2174                        if (!error) error = GBT_write_string(gb_new_species, "name", new_species_name);
2175                        if (!error) error = GBT_write_string(gb_new_species, "full_name", new_species_full_name); // insert new 'full_name'
2176                        if (!error && creation_mode==CREATE_FROM_CONSENSUS) {
2177                            ED4_group_manager *group_man = cursor_terminal->get_parent(ED4_L_GROUP)->to_group_manager();
2178                            error = createDataFromConsensus(gb_new_species, group_man);
2179                        }
2180                    }
2181                    else {
2182                        error = GBS_global_string("Can't find species '%s'", source_name);
2183                    }
2184                }
2185            }
2186
2187            if (error) {
2188                GB_abort_transaction(GLOBAL_gb_main);
2189            }
2190            else {
2191                GB_pop_transaction(GLOBAL_gb_main);
2192
2193                ED4_get_and_jump_to_species(new_species_name);
2194                ED4_ROOT->refresh_all_windows(1);
2195            }
2196        }
2197
2198        free(addid);
2199        free(acc);
2200        free(new_species_name);
2201    }
2202
2203    if (error) aw_popup_ok(error);
2204}
2205
2206AW_window *ED4_create_new_seq_window(AW_root *root, AW_CL cl_creation_mode)
2207    // creation_mode ==     0 -> create new species
2208    //                      1 -> create new species from group konsensus
2209    //                      2 -> copy current species
2210{
2211    AW_window_simple *aws = new AW_window_simple;
2212    int creation_mode = int(cl_creation_mode);
2213    switch (creation_mode) {
2214        case 0:
2215            aws->init( root, "create_species","Create species");
2216            break;
2217        case 1:
2218            aws->init( root, "create_species_from_consensus","Create species from consensus");
2219            break;
2220        case 2:
2221            aws->init( root, "copy_species","Copy current species");
2222            break;
2223        default:
2224            e4_assert(0);
2225            return 0;
2226    }
2227    if (creation_mode==1) { // create from consensus
2228        aws->load_xfig("edit4/create_seq_fc.fig");
2229    }
2230    else {
2231        aws->load_xfig("edit4/create_seq.fig");
2232    }
2233
2234    aws->callback( (AW_CB0)AW_POPDOWN);
2235    aws->at("close");
2236    aws->create_button("CLOSE", "CLOSE","C");
2237
2238    aws->at("label");
2239    aws->create_autosize_button(0,"Please enter the FULL_NAME\nof the new species");
2240
2241    aws->at("input");
2242    aws->create_input_field(ED4_AWAR_SPECIES_TO_CREATE, 30);
2243
2244    aws->at("ok");
2245    aws->callback(create_new_species, cl_creation_mode);
2246    aws->create_button("GO","GO","g");
2247
2248    if (creation_mode==1) { // create from consensus
2249        aws->at("replace_equal");
2250        aws->label("Replace '=' by ");
2251        aws->create_input_field(ED4_AWAR_CREATE_FROM_CONS_REPL_EQUAL, 1);
2252
2253        aws->at("replace_point");
2254        aws->label("Replace '.' by ");
2255        aws->create_input_field(ED4_AWAR_CREATE_FROM_CONS_REPL_POINT, 1);
2256
2257        aws->at("replace_start_end");
2258        aws->label("Create ... at ends of sequence?");
2259        aws->create_toggle(ED4_AWAR_CREATE_FROM_CONS_CREATE_POINTS);
2260
2261        aws->at("upper");
2262        aws->label("Convert all chars to upper?");
2263        aws->create_toggle(ED4_AWAR_CREATE_FROM_CONS_ALL_UPPER);
2264
2265        aws->at("data");
2266        aws->create_option_menu(ED4_AWAR_CREATE_FROM_CONS_DATA_SOURCE, "Other fields", "");
2267        aws->insert_default_option("Merge from all in group", "", 0);
2268        aws->insert_option("Copy from current species", "", 1);
2269        aws->update_option_menu();
2270    }
2271
2272    return (AW_window *)aws;
2273}
2274
Note: See TracBrowser for help on using the repository browser.