source: tags/initial/EDIT4/ED4_block.cxx

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

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.3 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <limits.h>
5#include <ctype.h>
6
7#include <arbdb.h>
8#include <arbdbt.h>
9#include <aw_root.hxx>
10#include <aw_keysym.hxx>
11#include <aw_window.hxx>
12#include <aw_awars.hxx>
13#include <awtc_fast_aligner.hxx>
14
15#include "ed4_awars.hxx"
16#include "ed4_class.hxx"
17#include "ed4_tools.hxx"
18#include "ed4_block.hxx"
19#include "ed4_edit_string.hxx"
20
21// --------------------------------------------------------------------------------
22
23static ED4_blocktype blocktype = ED4_BT_NOBLOCK;
24
25// linerange for COLUMNBLOCK is stored in EDIT4 marks,
26// columnrange for COLUMNBLOCK is stored here:
27
28static int range_col1, range_col2;
29static int columnBlockUsed = 0;
30
31// --------------------------------------------------------------------------------
32
33static void col_block_refresh_on_seq_term(ED4_sequence_terminal *seq_term) {
34    seq_term->set_refresh(1);
35    seq_term->parent->refresh_requested_by_child();
36               
37    ED4_columnStat_terminal *colStatTerm = seq_term->corresponding_columnStat_terminal();
38    if (colStatTerm) {
39        const char *probe_match_pattern = colStatTerm->build_probe_match_string(range_col1, range_col2);
40        int len = strlen(probe_match_pattern);
41       
42        if (len>=4) {
43            colStatTerm->set_refresh(1);
44            colStatTerm->parent->refresh_requested_by_child();
45       
46            // automatically set probe-match awars to appropriate values:
47       
48            ED4_ROOT->aw_root->awar(ED4_AWAR_PROBE_SEARCH_MAX_MISMATCHES)->write_int(0); // no mismatches
49            ED4_ROOT->aw_root->awar(ED4_AWAR_PROBE_SEARCH_AUTO_JUMP)->write_int(0); // disable auto jump
50            ED4_ROOT->aw_root->awar(AWAR_MAX_MISMATCHES)->write_int(0); // probe search w/o mismatches
51            ED4_ROOT->aw_root->awar(AWAR_ITARGET_STRING)->write_string(probe_match_pattern); // set probe search string
52        }
53    }
54}
55// --------------------------------------------------------------------------------
56
57// if block_operation() returns NULL => no changes will be made to database
58// otherwise the changed sequence(part) will be written to the database
59
60static GB_ERROR perform_block_operation_on_whole_sequence(ED4_blockoperation block_operation, ED4_sequence_terminal *term, int repeat) {
61    GBDATA *gbd = term->get_species_pointer();
62    GB_ERROR error = 0;
63                   
64    if (gbd) {
65        char *seq = GB_read_string(gbd);
66        int len = GB_read_string_count(gbd);
67                       
68        int new_len;
69        char *new_seq = block_operation(seq, len, repeat, &new_len, &error);
70           
71        if (new_seq) {
72            if (new_len<len) {
73                memcpy(seq, new_seq, new_len);
74                char gap = ADPP_IS_ALIGN_CHARACTER(seq[len-1]) ? seq[len-1] : '.';
75                int l;
76                for (l=new_len; l<len; l++) {
77                    seq[l] = gap;
78                }
79                seq[l] = 0;
80            }
81            else if (new_len>len) {
82                for (int l=new_len-1; l>=len; l--) {
83                    if (!ADPP_IS_ALIGN_CHARACTER(new_seq[l])) {
84                        error = "Result of block-operation to large (not enough gaps at end of sequence data)";
85                        break;
86                    }
87                }
88                               
89                if (!error) { // there are enough gaps at end of sequence
90                    memcpy(seq, new_seq, len); 
91                }
92            }
93            else {
94                memcpy(seq, new_seq, len);
95            }
96            delete new_seq;
97               
98            if (!error) {
99                error = GB_write_string(gbd, seq);
100                if (!error) {
101                    term->set_refresh();
102                    term->parent->refresh_requested_by_child();
103                }
104            }
105        }
106                       
107        delete seq;
108    }
109   
110    return error;
111}
112
113// uses range_col1 till range_col2 as range
114static GB_ERROR perform_block_operation_on_part_of_sequence(ED4_blockoperation block_operation, ED4_sequence_terminal *term, int repeat) {
115    GBDATA *gbd = term->get_species_pointer();
116    GB_ERROR error = 0;
117                   
118    if (gbd) {
119        char *seq = GB_read_string(gbd);
120        int len = GB_read_string_count(gbd);
121       
122        if (range_col1>=len || range_col2>=len) {
123            error = "Column-range exceeds sequence length";
124        }
125        else {
126            int len_part = range_col2-range_col1+1;
127            char *seq_part = seq+range_col1;
128            int new_len;
129            char *new_seq_part = block_operation(seq_part, len_part, repeat, &new_len, &error);
130           
131            if (new_seq_part) {
132                if (new_len<len_part) {
133                    memcpy(seq_part, new_seq_part, new_len);
134                    char gap = ADPP_IS_ALIGN_CHARACTER(seq_part[len_part-1]) ? seq_part[len_part-1] : '.';
135                    for (int l=new_len; l<len_part; l++) {
136                        seq_part[l] = gap;
137                    }
138                }
139                else if (new_len>len_part) {
140                    for (int l=new_len-1; l>=len_part; l--) {
141                        if (!ADPP_IS_ALIGN_CHARACTER(new_seq_part[l])) {
142                            error = "Result of block-operation to large (not enough gaps at end of marked columnblock)";
143                            break;
144                        }
145                    }
146                               
147                    if (!error) { // there are enough gaps at end of sequence
148                        memcpy(seq_part, new_seq_part, len_part); 
149                    }
150                }
151                else {
152                    memcpy(seq_part, new_seq_part, len_part);
153                }
154                delete new_seq_part;
155               
156                if (!error) {
157                    error = GB_write_string(gbd, seq);
158                    if (!error) {
159                        term->set_refresh();
160                        term->parent->refresh_requested_by_child();
161                    }
162                }
163            }
164        }
165                       
166        delete seq;
167    }
168   
169    return error;
170}
171
172void ED4_with_whole_block(ED4_blockoperation block_operation, int repeat) { 
173    GB_ERROR error = GB_begin_transaction(gb_main);
174    ED4_sequence_terminal *err_term = 0;
175    //    ED4_terminal *term = ED4_ROOT->root_group_man->get_first_terminal();
176   
177    switch (blocktype) {
178        case ED4_BT_NOBLOCK: {
179            aw_message("No block marked -- use middle mouse button");
180            break;
181        }
182        case ED4_BT_LINEBLOCK: {
183            ED4_list_elem *listElem = ED4_ROOT->selected_objects.first();
184            while (listElem && !error) {
185                ED4_selection_entry *selectionEntry = (ED4_selection_entry*)listElem->elem();
186                ED4_sequence_terminal *seqTerm = selectionEntry->object->get_parent(ED4_L_SPECIES)->search_spec_child_rek(ED4_L_SEQUENCE_STRING)->to_sequence_terminal();
187               
188                error = perform_block_operation_on_whole_sequence(block_operation, seqTerm, repeat);
189                if (error) err_term = seqTerm;
190               
191                listElem = listElem->next();
192            }
193            break;
194        }
195        case ED4_BT_MODIFIED_COLUMNBLOCK:
196        case ED4_BT_COLUMNBLOCK: {
197            ED4_list_elem *listElem = ED4_ROOT->selected_objects.first();
198            while (listElem && !error) {
199                ED4_selection_entry *selectionEntry = (ED4_selection_entry*)listElem->elem();
200                ED4_sequence_terminal *seqTerm = selectionEntry->object->get_parent(ED4_L_SPECIES)->search_spec_child_rek(ED4_L_SEQUENCE_STRING)->to_sequence_terminal();
201               
202                error = perform_block_operation_on_part_of_sequence(block_operation, seqTerm, repeat);
203                if (error) err_term = seqTerm;
204               
205                listElem = listElem->next();
206            }
207            break;
208        }
209        default: {
210            error = "Illegal blocktype";
211            break;
212        }
213    }
214   
215    if (error) {
216        char buffer[500];
217        sprintf(buffer, "Error in blockoperation: %s", error);
218        aw_message(buffer);
219       
220        GB_abort_transaction(gb_main);
221    }
222    else {
223        GB_commit_transaction(gb_main);
224    }
225}
226
227int ED4_get_selected_range(ED4_terminal *term, int *first_column, int *last_column) {
228    if (blocktype==ED4_BT_NOBLOCK) return 0;
229   
230    if (blocktype==ED4_BT_COLUMNBLOCK || blocktype==ED4_BT_MODIFIED_COLUMNBLOCK) {
231        *first_column = range_col1;
232        *last_column = range_col2;
233    }
234    else {
235        e4_assert(blocktype==ED4_BT_LINEBLOCK);
236        *first_column = 0;
237        *last_column = -1; 
238    }
239   
240    ED4_species_name_terminal *name_term = term->to_sequence_terminal()->corresponding_species_name_terminal();
241    return name_term->flag.selected;
242}
243
244ED4_blocktype ED4_getBlocktype() {
245    return blocktype;
246}
247void ED4_setBlocktype(ED4_blocktype bt) {
248    if (blocktype!=bt) {
249        blocktype = bt;
250       
251        ED4_list_elem *listElem = ED4_ROOT->selected_objects.first();
252        while (listElem) {
253            ED4_selection_entry *selected = (ED4_selection_entry*)listElem->elem();
254            ED4_species_name_terminal *name_term = selected->object->to_species_name_terminal();
255            ED4_sequence_terminal *seq_term = name_term->corresponding_sequence_terminal();
256           
257            name_term->set_refresh(1);
258            name_term->parent->refresh_requested_by_child();
259            if (seq_term) col_block_refresh_on_seq_term(seq_term);
260           
261            listElem = listElem->next();
262        }
263               
264        if (blocktype==ED4_BT_COLUMNBLOCK || blocktype==ED4_BT_MODIFIED_COLUMNBLOCK) {
265            columnBlockUsed = 1;
266        }
267    }
268}
269
270void ED4_toggle_block_type(void) {
271    switch (blocktype) {
272        case ED4_BT_NOBLOCK: {
273            aw_message("No block selected.");
274            break;
275        }
276        case ED4_BT_LINEBLOCK: {
277            if (columnBlockUsed) {
278                ED4_setBlocktype(ED4_BT_MODIFIED_COLUMNBLOCK);
279            }
280            else {
281                aw_message("No columnblock marked so far  - I can't guess the column range");
282            }
283            break;
284        }
285        case ED4_BT_MODIFIED_COLUMNBLOCK:
286        case ED4_BT_COLUMNBLOCK: {
287            ED4_setBlocktype(ED4_BT_LINEBLOCK);
288            break;
289        }
290        default: {
291            e4_assert(0);
292            break;
293        }
294    }
295}
296
297void ED4_correctBlocktypeAfterSelection() { // this has to be called every time the selection has changed
298
299    if (ED4_ROOT->selected_objects.first()==0) { // no objects are selected
300        ED4_setBlocktype(ED4_BT_NOBLOCK);
301    }
302    else {
303        switch (ED4_getBlocktype()) {
304            case ED4_BT_NOBLOCK: {
305                ED4_setBlocktype(ED4_BT_LINEBLOCK);
306                break;
307            }
308            case ED4_BT_COLUMNBLOCK: {
309                ED4_setBlocktype(ED4_BT_MODIFIED_COLUMNBLOCK);
310                break;
311            }
312            case ED4_BT_LINEBLOCK:
313            case ED4_BT_MODIFIED_COLUMNBLOCK: {
314                break;
315            }
316            default: {
317                e4_assert(0);
318                break;
319            }
320        }
321    }
322}
323
324static void select_and_update(ED4_sequence_terminal *term1, ED4_sequence_terminal *term2, ED4_index pos1, ED4_index pos2, int initial_call) {
325    static ED4_sequence_terminal *last_term1, *last_term2;
326    static ED4_index last_pos1, last_pos2;
327   
328    if (pos1>pos2) {
329        range_col1 = pos2;
330        range_col2 = pos1;
331    }
332    else {
333        range_col1 = pos1;
334        range_col2 = pos2;
335    }
336   
337    if (blocktype==ED4_BT_MODIFIED_COLUMNBLOCK) {
338        ED4_list_elem *listElem = ED4_ROOT->selected_objects.first();
339        while (listElem) {
340            ED4_selection_entry *selectionEntry = (ED4_selection_entry*)listElem->elem();
341            ED4_species_name_terminal *name_term = selectionEntry->object->to_species_name_terminal();
342            ED4_sequence_terminal *seq_term = name_term->corresponding_sequence_terminal();
343           
344            if (seq_term) col_block_refresh_on_seq_term(seq_term);
345               
346            listElem = listElem->next();
347        }
348    }
349    else {
350        { // ensure term1 is the upper terminal
351            AW_pos dummy, y1, y2;
352       
353            term1->calc_world_coords(&dummy, &y1);
354            term2->calc_world_coords(&dummy, &y2);
355       
356            if (y1>y2) {
357                ED4_sequence_terminal *t = term1; term1 = term2; term2 = t;
358                AW_pos y = y1; y1 = y2; y2 = y;
359            }
360        }
361   
362        int do_above = 1; // we have to update terminals between last_term1 and term1
363        int do_below = 1; // we have to update terminals between term2 and last_term2
364   
365        ED4_terminal *term = term1;
366        //      ED4_terminal *start_term = term1;
367        int xRangeChanged = last_pos1!=range_col1 || last_pos2!=range_col2;
368   
369        while (term) {
370            if (term->is_sequence_terminal()) {
371                ED4_sequence_terminal *seq_term = term->to_sequence_terminal();
372           
373                if (seq_term==last_term1) { 
374                    do_above = 0;
375                }
376                if (seq_term==last_term2) {
377                    do_below = 0;
378                }
379           
380                ED4_species_name_terminal *name_term = seq_term->corresponding_species_name_terminal();
381                if (name_term->flag.selected) { // already selected
382                    if (xRangeChanged) { 
383                        col_block_refresh_on_seq_term(seq_term);
384                    }
385                }
386                else { // select it
387                    ED4_species_manager *species_man = name_term->get_parent(ED4_L_SPECIES)->to_species_manager();
388                   
389                    if (!species_man->flag.is_consensus) {
390                        ED4_ROOT->add_to_selected(name_term);
391                    }
392                }
393            }
394            if (term==term2) {
395                break;
396            }
397            term = term->get_next_terminal();
398        }
399   
400        if (!initial_call) {
401            if (do_below) {
402                while (term) {
403                    if (term->is_species_name_terminal() && term->flag.selected) {
404                        ED4_species_manager *species_man = term->get_parent(ED4_L_SPECIES)->to_species_manager();
405                       
406                        if (!species_man->flag.is_consensus) {
407                            ED4_ROOT->remove_from_selected(term);
408                        }
409                    }
410                    if (term==last_term2) break;
411                    term = term->get_next_terminal();
412                }
413            }
414   
415            if (do_above) {
416                term = last_term1->corresponding_species_name_terminal();
417                while (term && term!=term1) {
418                    if (term->is_species_name_terminal() && term->flag.selected) {
419                        ED4_species_manager *species_man = term->get_parent(ED4_L_SPECIES)->to_species_manager();
420                       
421                        if (!species_man->flag.is_consensus) {
422                            ED4_ROOT->remove_from_selected(term);
423                        }
424                    }
425                    term = term->get_next_terminal();
426                }
427            }
428        }
429    }
430   
431    last_term1 = term1;
432    last_term2 = term2;
433    last_pos1 = range_col1;
434    last_pos2 = range_col2;
435}
436
437static inline double fabs(double d) {
438    return d<0 ? -d : d;
439}
440
441void ED4_setColumnblockCorner(AW_event *event, ED4_sequence_terminal *seq_term) { 
442    static ED4_sequence_terminal *fix_term = 0;
443    static ED4_index fix_pos = 0;
444   
445    ED4_index seq_pos;
446    {
447        AW_pos termw_x, termw_y;
448        seq_term->calc_world_coords(&termw_x, &termw_y);
449   
450        AW_pos seq_relx;
451        ED4_index scr_pos; 
452        ED4_cursor::calc_cursor_position(event->x-termw_x, &seq_relx, &scr_pos);
453   
454        ED4_remap *remap = ED4_ROOT->root_group_man->remap();
455        seq_pos = remap->screen_to_sequence(scr_pos);
456    }
457   
458    switch (event->type) {
459        case AW_Mouse_Press: { 
460            if (blocktype==ED4_BT_NOBLOCK) { // initial columnblock
461                ED4_setBlocktype(ED4_BT_COLUMNBLOCK);
462               
463                fix_term = seq_term;
464                fix_pos = seq_pos;
465               
466                select_and_update(fix_term, seq_term, fix_pos, seq_pos, 1);
467            }
468            else if (blocktype==ED4_BT_LINEBLOCK) { // change lineblock to columnblock
469                ED4_setBlocktype(ED4_BT_MODIFIED_COLUMNBLOCK);
470               
471                fix_term = seq_term;
472                if (seq_pos<(MAXSEQUENCECHARACTERLENGTH/2)) { // in first half of sequence
473                    fix_pos = MAXSEQUENCECHARACTERLENGTH;
474                }
475                else {
476                    fix_pos = 0;
477                }
478               
479                select_and_update(fix_term, seq_term, fix_pos, seq_pos, 1);
480            }
481            else { // expand columnblock (search nearest corner/border -> fix opposite corner/border)
482                e4_assert(blocktype==ED4_BT_COLUMNBLOCK || blocktype==ED4_BT_MODIFIED_COLUMNBLOCK);
483               
484                ED4_list_elem *listElem = ED4_ROOT->selected_objects.first();
485                e4_assert(listElem);
486               
487                if (blocktype==ED4_BT_COLUMNBLOCK) {
488                    AW_pos min_term_y = LONG_MAX;
489                    AW_pos max_term_y = LONG_MIN;
490                    ED4_species_name_terminal *min_term = 0;
491                    ED4_species_name_terminal *max_term = 0;
492                    AW_pos xpos, ypos;
493               
494                    while (listElem) {
495                        ED4_selection_entry *selected = (ED4_selection_entry*)listElem->elem();
496                        ED4_species_name_terminal *name_term = selected->object->to_species_name_terminal();
497                   
498                        name_term->calc_world_coords(&xpos, &ypos);
499                   
500                        if (ypos<min_term_y) {
501                            min_term_y = ypos;
502                            min_term = name_term;
503                        }
504                        if (ypos>max_term_y) {
505                            max_term_y = ypos;
506                            max_term = name_term;
507                        }
508                       
509                        listElem = listElem->next();
510                    }
511               
512                    seq_term->calc_world_coords(&xpos, &ypos);
513                    ED4_species_name_terminal *fix_name_term;
514                    if (fabs(ypos-min_term_y)<fabs(ypos-max_term_y)) { // seq_term is closer to min_term
515                        fix_name_term = max_term; // select max_term as fixed corner
516                    }
517                    else {
518                        fix_name_term = min_term;
519                    }
520                    fix_term = fix_name_term->corresponding_sequence_terminal();
521                }
522               
523                long scr_col1, scr_col2;
524                AW_rectangle area_rect;
525                {
526                    AW_pos ex = event->x;
527                    AW_pos ey = event->y;
528                    ED4_ROOT->world_to_win_coords(ED4_ROOT->temp_ed4w->aww, &ex, &ey);
529               
530                    if (ED4_ROOT->get_area_rectangle(&area_rect, ex, ey)!=ED4_R_OK) {
531                        e4_assert(0);
532                        break;
533                    }
534                }
535               
536               
537                const ED4_remap *rm = ED4_ROOT->root_group_man->remap();
538               
539                seq_term->calc_intervall_displayed_in_rectangle(&area_rect, &scr_col1, &scr_col2);
540                rm->clip_screen_range(&scr_col1, &scr_col2);
541               
542                int range_scr_col1 = rm->sequence_to_screen(range_col1);
543                int range_scr_col2 = rm->sequence_to_screen(range_col2);
544                int scr_pos = rm->sequence_to_screen(seq_pos);
545               
546                int use_scr_col1 = range_scr_col1<scr_col1 ? scr_col1 : range_scr_col1;
547                int use_scr_col2 = range_scr_col2>scr_col2 ? scr_col2 : range_scr_col2;
548               
549                if (abs(scr_pos-use_scr_col1) < abs(scr_pos-use_scr_col2)) { // scr_pos is closer to use_scr_col1
550                    fix_pos = range_col2;
551                }
552                else {
553                    fix_pos = range_col1;
554                }
555               
556                select_and_update(fix_term, seq_term, fix_pos, seq_pos, 0);
557            }
558            break;
559        }
560        case AW_Mouse_Drag: {
561            select_and_update(fix_term, seq_term, fix_pos, seq_pos, 0);
562            break;
563        }
564        case AW_Mouse_Release: { 
565            select_and_update(fix_term, seq_term, fix_pos, seq_pos, 0);
566            break;
567        }
568        default: {
569            e4_assert(0);
570            break;
571        }
572    }
573}
574
575// --------------------------------------------------------------------------------
576//      Replace
577// --------------------------------------------------------------------------------
578
579static int strncmpWithJoker(GB_CSTR s1, GB_CSTR s2, int len) { // s2 contains '?' as joker
580    int cmp = 0;
581   
582    while (len-- && !cmp) {
583        int c1 = *s1++;
584        int c2 = *s2++;
585       
586        if (!c1) {
587            cmp = -1;
588        }
589        else if (!c2) {
590            cmp = 1;
591        }
592        else if (c2!='?') {
593            cmp = c1-c2;
594        }
595    }   
596   
597    return cmp;
598}
599
600static char *oldString, *newString;
601static int oldStringContainsJoker;
602
603static char* replace_in_sequence(const char *sequence, int len, int /*repeat*/, int *new_len, GB_ERROR*) {
604    int maxlen;
605    int olen = strlen(oldString);
606    int nlen = strlen(newString);
607   
608    if (nlen<=olen) {
609        maxlen = len;
610    }
611    else  {
612        maxlen = (len/olen+1)*nlen;
613    }
614   
615    char *new_seq = (char*)GB_calloc(maxlen+1, sizeof(*new_seq));
616    int replaced = 0;
617    int o = 0;
618    int n = 0;
619    char ostart = oldString[0];
620   
621    if (oldStringContainsJoker) {
622        while (o<len) {
623            if (strncmpWithJoker(sequence+o, oldString, olen)==0) {
624                memcpy(new_seq+n, newString, nlen);
625                n += nlen;
626                o += olen;
627                replaced++;
628            }
629            else {
630                new_seq[n++] = sequence[o++];
631            }
632        }
633    }
634    else {
635        while (o<len) {
636            if (sequence[o]==ostart && strncmp(sequence+o, oldString, olen)==0) { // occurance of oldString
637                memcpy(new_seq+n, newString, nlen);
638                n += nlen;
639                o += olen;
640                replaced++;
641            }
642            else {
643                new_seq[n++] = sequence[o++];
644            }
645        }
646    }
647    new_seq[n] = 0;
648   
649    if (replaced) {
650        if (new_len) {
651            *new_len = n;
652        }
653    }
654    else {
655        delete new_seq;
656        new_seq = 0;
657    }
658   
659    return new_seq;
660}
661
662static void replace_in_block(AW_window*) {
663    oldString = ED4_ROOT->aw_root->awar(ED4_AWAR_REP_SEARCH_PATTERN)->read_string();
664    newString = ED4_ROOT->aw_root->awar(ED4_AWAR_REP_REPLACE_PATTERN)->read_string();
665   
666    oldStringContainsJoker = strchr(oldString, '?')!=0;
667    ED4_with_whole_block(replace_in_sequence, 1);
668   
669    delete oldString; oldString = 0;
670    delete newString; newString = 0;
671}
672
673AW_window *ED4_create_replace_window(AW_root *root) {
674    AW_window_simple *aws = new AW_window_simple;
675   
676    aws->init(root, "REPLACE", "Search & Replace", 100, 100);
677    aws->load_xfig("edit4/replace.fig");
678   
679    aws->at("close");
680    aws->callback( (AW_CB0)AW_POPDOWN);
681    aws->create_button("CLOSE", "Close","C");
682       
683    aws->at("help");
684    aws->callback( AW_POPUP_HELP,(AW_CL)"e4_replace.hlp");
685    aws->create_button("HELP", "Help","H");
686   
687    aws->at("spattern");
688    aws->create_input_field(ED4_AWAR_REP_SEARCH_PATTERN, 30);
689   
690    aws->at("rpattern");
691    aws->create_input_field(ED4_AWAR_REP_REPLACE_PATTERN, 30);
692   
693    aws->at("go");
694    aws->callback(replace_in_block);
695    aws->create_button("GO", "Go", "G");
696   
697    return aws;
698}
699
700// --------------------------------------------------------------------------------
701//      Other block operations
702// --------------------------------------------------------------------------------
703
704static char *sequence_to_upper_case(const char *seq, int len, int /*repeat*/, int *new_len, GB_ERROR*) {
705    char *new_seq = (char*)GB_calloc(len+1, sizeof(*new_seq));
706    int l;
707   
708    for (l=0; l<len; l++) {
709        new_seq[l] = toupper(seq[l]);
710    }
711   
712    if (new_len) *new_len = len;
713    return new_seq;
714}
715static char *sequence_to_lower_case(const char *seq, int len, int /*repeat*/, int *new_len, GB_ERROR*) {
716    char *new_seq = (char*)GB_calloc(len+1, sizeof(*new_seq));
717    int l;
718   
719    for (l=0; l<len; l++) {
720        new_seq[l] = tolower(seq[l]);
721    }
722   
723    if (new_len) *new_len = len;
724    return new_seq;
725}
726
727#define EVEN_REPEAT "repeat-count is even -> no changes!"
728
729static char *reverse_sequence(const char *seq, int len, int repeat, int *new_len, GB_ERROR *error) {
730    if ((repeat&1)==0) { *error = GBS_global_string(EVEN_REPEAT); return 0; }
731   
732    char *new_seq = AWTC_reverseString(seq, len);
733    if (new_len) *new_len = len;
734    return new_seq;
735}
736static char *complement_sequence(const char *seq, int len, int repeat, int *new_len, GB_ERROR *error) {
737    if (IS_AMINO) {
738        *error = GBS_global_string("Complement not possible for this alignment-type");
739        return 0;
740    } 
741    if ((repeat&1)==0) {
742        *error = GBS_global_string(EVEN_REPEAT);
743        return 0;
744    }
745    char T_or_U = ED4_ROOT->alignment_type==GB_AT_DNA ? 'T' : 'U';   
746    char *new_seq = AWTC_complementString(seq, len, T_or_U);
747    if (new_len) *new_len = len;
748    return new_seq;
749}
750static char *reverse_complement_sequence(const char *seq, int len, int repeat, int *new_len, GB_ERROR *error) {
751    if (IS_AMINO) {
752        *error = GBS_global_string("Complement not possible for this alignment-type");
753        return 0;
754    } 
755    if ((repeat&1)==0) {
756        *error = GBS_global_string(EVEN_REPEAT);
757        return 0;
758    } 
759    char T_or_U = ED4_ROOT->alignment_type==GB_AT_DNA ? 'T' : 'U';   
760    char *new_seq1 = AWTC_complementString(seq, len, T_or_U);
761    char *new_seq2 = AWTC_reverseString(new_seq1, len);
762   
763    delete new_seq1;
764    if (new_len) *new_len = len;
765    return new_seq2;
766}
767static char *unalign_sequence(const char *seq, int len, int /*repeat*/, int *new_len, GB_ERROR *) {
768    char *new_seq = (char*)GB_calloc(len+1, sizeof(*new_seq));
769    int o = 0;
770    int n = 0;
771    char gap = '-';
772   
773    while (o<len) {
774        if (ADPP_IS_ALIGN_CHARACTER(seq[o])) {
775            gap = seq[o];
776        }
777        else {
778            new_seq[n++] = seq[o];
779        }
780        o++;
781    }
782   
783    while (n<len) {
784        new_seq[n++] = gap;
785    }
786   
787    if (new_len) *new_len = len;
788    return new_seq;
789}
790
791static char *shift_left_sequence(const char *seq, int len, int repeat, int *new_len, GB_ERROR *error) {
792    char *new_seq = 0;
793   
794    if (repeat>=len) {
795        *error = "Repeat count exceeds block length";
796    }
797    else
798    {
799        int enough_space = 1;
800        for (int i=0; enough_space && i<repeat; i++) {
801            if (!ADPP_IS_ALIGN_CHARACTER(seq[i])) {
802                enough_space = 0;
803            }
804        }
805   
806        if (enough_space) {
807            char gap = seq[0];
808           
809            new_seq = (char*)GB_calloc(len+1, sizeof(*new_seq));
810            if (new_len) *new_len = len;
811            memcpy(new_seq, seq+repeat, len-repeat);
812            memset(new_seq+len-repeat, ADPP_IS_ALIGN_CHARACTER(seq[len-1]) ? seq[len-1] : gap, repeat);
813        }
814        else {
815            *error = GBS_global_string("Shift left needs %i gap%s at block start", repeat, repeat==1 ? "" : "s");
816        }
817    }
818   
819    return new_seq;
820}
821
822static char *shift_right_sequence(const char *seq, int len, int repeat, int *new_len, GB_ERROR *error) {
823    char *new_seq = 0;
824   
825    if (repeat>=len) {
826        *error = "Repeat count exceeds block length";
827    }
828    else
829    {
830        int enough_space = 1;
831        for (int i=0; enough_space && i<repeat; i++) {
832            if (!ADPP_IS_ALIGN_CHARACTER(seq[len-i-1])) {
833                enough_space = 0;
834            }
835        }
836   
837        if (enough_space) {
838            char gap = seq[len-1];
839           
840            new_seq = (char*)GB_calloc(len+1, sizeof(*new_seq));
841            if (new_len) *new_len = len;
842            memset(new_seq, ADPP_IS_ALIGN_CHARACTER(seq[0]) ? seq[0] : gap, repeat);
843            memcpy(new_seq+repeat, seq, len-repeat);
844        }
845        else {
846            *error = GBS_global_string("Shift right needs %i gap%s at block end", repeat, repeat==1 ? "" : "s");
847        }
848    }
849   
850    return new_seq;
851}
852
853#if 0
854static char *shift_right_sequence(const char *seq, int len, int repeat, int *new_len, GB_ERROR *error) {
855    char *new_seq = 0;
856   
857    if (ADPP_IS_ALIGN_CHARACTER(seq[len-1])) {
858        char gap = seq[len-1];
859        new_seq = (char*)GB_calloc(len+1, sizeof(*new_seq));
860        if (new_len) *new_len = len;
861        memcpy(new_seq+1, seq, len-1);
862        if (ADPP_IS_ALIGN_CHARACTER(seq[0])) {
863            new_seq[0] = seq[0];
864        }
865        else {
866            new_seq[0] = gap;
867        }
868    }
869    else {
870        *error = "Shift right needs a gap as last block character";
871    }
872   
873    return new_seq;
874}
875#endif
876
877void ED4_perform_block_operation(ED4_blockoperation_type operationType) {
878    int nrepeat = ED4_ROOT->edit_string->use_nrepeat();
879   
880    switch (operationType) {
881        case ED4_BO_UPPER_CASE:         ED4_with_whole_block(sequence_to_upper_case, nrepeat);          break;
882        case ED4_BO_LOWER_CASE:         ED4_with_whole_block(sequence_to_lower_case, nrepeat);          break;
883        case ED4_BO_REVERSE:            ED4_with_whole_block(reverse_sequence, nrepeat);                break;
884        case ED4_BO_COMPLEMENT:         ED4_with_whole_block(complement_sequence, nrepeat);             break;
885        case ED4_BO_REVERSE_COMPLEMENT: ED4_with_whole_block(reverse_complement_sequence, nrepeat);     break;
886        case ED4_BO_UNALIGN:            ED4_with_whole_block(unalign_sequence, nrepeat);                break;     
887        case ED4_BO_SHIFT_LEFT:         ED4_with_whole_block(shift_left_sequence, nrepeat);             break;
888        case ED4_BO_SHIFT_RIGHT:        ED4_with_whole_block(shift_right_sequence, nrepeat);            break;
889       
890        default: {
891            e4_assert(0);
892            break;
893        }
894    }
895}
896
897
Note: See TracBrowser for help on using the repository browser.