source: tags/arb_5.0/ARBDBPP/adseq.cxx

Last change on this file was 5839, checked in by westram, 15 years ago
  • followup to [5824] (more to follow)
    • GB_get_error() → GB_await_error() where appropriate (ARBDB mostly)
    • fixed error handling in several functions
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.0 KB
Line 
1/****************
2 sequence.cxx
3enthaelt code fuer      AD_CONT
4                        AD_SEQ
5                        AD_STAT
6*******/
7#include <cstdio>
8#include <cstdlib>
9#include <cstring>
10#include <cctype>
11#include <memory.h>
12
13#include <iostream>
14
15#include <arbdb.h>
16#include <arbdbt.h>
17#include <aw_keysym.hxx>
18
19#include "arbdb++.hxx"
20
21
22/*********************
23AD_STAT
24**********************/
25
26AD_STAT::AD_STAT()
27{
28    c_1 = '1';
29    c_0 = '0';
30    ad_cont = 0;
31    last = 0;
32    marktype = ad_none;
33    gb_mark = 0;
34    GB_INT_mark = 0;
35    gb_char_mark = 0;
36    GB_FLOAT_mark = 0;
37    updated = 0;
38    nmark = 0;
39    markdata = 0;
40    markdatafloat = 0;
41    markdataint = 0;
42}
43
44AD_STAT::~AD_STAT()
45// gibt speicherplatz fuer markierungen frei frei
46{
47    if (inited_object == 1)
48        new AD_ERR("AD_STAT: no exit before ~");
49}
50
51
52AD_ERR * AD_STAT::init(AD_CONT * adptr)
53//
54{
55    ad_cont = adptr;
56    if (ad_cont->gb_ali == NULL)
57        return new AD_ERR("AD_STAT: init without propper inited container",CORE);
58    gb_mark = ad_cont->gb_ali;
59    inited_object = 1;
60    return 0;
61}
62
63
64
65
66AD_ERR * AD_STAT::release() {
67    if (GB_INT_mark != 0) {
68        GB_remove_callback(GB_INT_mark,GB_CB_CHANGED,(GB_CB)AD_STAT_updatecall,(int *)this);
69        if (ad_cont->get_cach_flag() == MINCACH) {
70            GB_release(GB_INT_mark);
71        }
72        if (markdataint != 0) free ((char *)markdataint);
73        nmark = 0;
74        GB_INT_mark = 0;
75    }
76    if (gb_char_mark != 0) {
77        GB_remove_callback(gb_char_mark,GB_CB_CHANGED,(GB_CB)AD_STAT_updatecall,(int *)this);
78        if (markdata  != 0)free ((char *)markdata);
79        nmark = 0;
80        gb_char_mark = 0;
81    }
82    if (GB_FLOAT_mark != 0) {
83        GB_remove_callback(GB_FLOAT_mark,GB_CB_CHANGED,(GB_CB)AD_STAT_updatecall,(int *)this);
84        if (markdatafloat != 0) free ((char *)markdatafloat);
85        nmark = 0;
86        GB_FLOAT_mark = 0;
87    }
88    if (marktype) marktype = ad_none;
89    if (markkey) free ((char *)markkey);
90    return 0;
91}
92
93AD_ERR * AD_STAT::exit()
94{
95    if (inited_object == 0)
96        return new      AD_ERR("AD_STAT: exit() without init()");
97    release();
98    gb_mark = 0;
99    gb_markdata = 0;
100    inited_object = 0;
101    return 0;
102}
103
104AD_ERR * AD_STAT::initpntr() {
105    if (gb_markdata == 0) {
106        release();
107        last = 1;
108        gb_char_mark    =  0;
109        GB_FLOAT_mark = 0;
110        GB_INT_mark = 0;
111        return 0;
112    }
113    release();
114    marktype = (AD_TYPES)GB_read_type(gb_markdata );
115    markkey = GB_read_key(gb_markdata);
116    switch (marktype) {
117        case ad_ints:   /*if (GB_INT_mark) free ((char *)GB_INT_mark);
118                          if (GB_FLOAT_mark) free ((char *)GB_FLOAT_mark);
119                          if (gb_char_mark) free ((char *)gb_char_mark);*/
120            GB_INT_mark =  gb_markdata;
121            GB_FLOAT_mark = 0;
122            gb_char_mark = 0;
123            nmark = GB_read_ints_count(gb_markdata);
124            markdataint = GB_read_ints(gb_markdata);
125            GB_add_callback(gb_char_mark, GB_CB_CHANGED,
126                            (GB_CB) AD_STAT_updatecall, (int *) this);
127            last = 0;
128            break;
129        case ad_floats: GB_FLOAT_mark   = gb_markdata;
130            GB_INT_mark = 0;
131            gb_char_mark = 0;
132
133            nmark = GB_read_floats_count(gb_markdata);
134            markdatafloat = GB_read_floats(gb_markdata);
135            GB_add_callback(GB_FLOAT_mark, GB_CB_CHANGED,
136                            (GB_CB) AD_STAT_updatecall, (int *) this);
137            last = 0;
138            break;
139        case ad_bits:   gb_char_mark    =  gb_markdata;
140            GB_FLOAT_mark = 0;
141            GB_INT_mark = 0;
142            nmark = GB_read_bits_count(gb_markdata);
143            markdata = GB_read_bits(gb_markdata,c_0,c_1);
144            GB_add_callback(GB_INT_mark, GB_CB_CHANGED,
145                            (GB_CB) AD_STAT_updatecall, (int *) this);
146            last = 0;
147            break;
148        default :       gb_char_mark    =  0;
149            GB_FLOAT_mark = 0;
150            GB_INT_mark = 0;
151            last = 1;
152
153    }
154    return 0;
155}
156
157AD_ERR * AD_STAT::first() {
158    char *key = 0;
159    if (gb_mark != 0) {
160        release();
161        gb_markdata = GB_child(gb_mark);
162        if (gb_markdata != 0) {
163            key = GB_read_key(gb_markdata);
164            if (strcmp(key, "data") == 0) {
165                gb_markdata = GB_nextChild(gb_markdata);
166                if (gb_markdata != 0) {
167                    key = GB_read_key(gb_markdata);
168                }
169            }
170        }
171        if (gb_markdata == 0) { // keine markierung vorhanden
172            last = 1;
173            return 0;
174        }
175        markkey = strdup(key);
176        initpntr();
177        return 0;
178    }
179    return new AD_ERR("AD_species first: NO AD_MAIN\n");
180}
181
182
183AD_ERR * AD_STAT::first(AD_TYPES typus) {
184    AD_TYPES adtype;
185    if (gb_mark != 0) {
186        release();
187        gb_markdata = GB_child(gb_mark);
188
189        while (last != 0) {
190            gb_markdata = GB_child(gb_mark);
191            if (gb_markdata != 0) {
192                adtype = (AD_TYPES) GB_read_type(gb_markdata);
193                if (adtype == typus) {
194                    marktype = adtype;
195                    initpntr();
196                    return 0;
197                }
198                else {
199                    gb_markdata = GB_nextChild(gb_markdata);
200                }
201            }
202        }
203        initpntr();
204    }
205    return 0;
206}
207
208AD_ERR * AD_STAT::next() {
209    if (gb_markdata == 0 || last ==  1) {
210        return new AD_ERR("AD_STAT::next() not possible, no first or last!");
211    }
212    release();
213    gb_markdata = GB_nextChild(gb_markdata);
214    initpntr();
215    return 0;
216}
217
218
219AD_ERR * AD_STAT::next(AD_TYPES typus) {
220    if (gb_markdata == 0 || last == 1) {
221        return new AD_ERR("AD_STAT::next() not possible, no first or last!");
222    }
223    release();
224    while (gb_markdata != 0) {
225        gb_markdata = GB_nextChild(gb_markdata);
226        if (gb_markdata != 0) {
227            if ((AD_TYPES)GB_read_type(gb_markdata) == typus) {
228                initpntr();
229                return 0;
230            }
231        }
232    }
233    last = 1;
234    marktype = typus;
235    return 0;
236}
237
238
239
240int AD_STAT_updatecall(GBDATA *gb_char_mark,AD_STAT *ad_mark)
241// behandelt ein update der Markierung in der Datenbank
242// problem -> wenn editiert wird ni
243//
244//
245{
246    if ((gb_char_mark != ad_mark->GB_INT_mark) &&(gb_char_mark != ad_mark->gb_char_mark) && (gb_char_mark != ad_mark->GB_FLOAT_mark)) {
247        new AD_ERR("AD_STAT: WRONG update callback",CORE);
248    }
249    if (gb_char_mark == ad_mark->gb_char_mark) {
250        ad_mark->gb_markdata = gb_char_mark;
251        ad_mark->initpntr();
252
253    }
254    if (gb_char_mark == ad_mark->GB_FLOAT_mark) {
255        ad_mark->gb_markdata = gb_char_mark;
256        ad_mark->initpntr();
257    }
258    if (gb_char_mark == ad_mark->GB_INT_mark) {
259        ad_mark->gb_markdata = gb_char_mark;
260        ad_mark->initpntr();
261    }
262
263    ad_mark->updated = 1;       // flag setzen
264    return 0;
265}
266
267
268char * AD_STAT::getbits() {
269    if (marktype != ad_bits) {
270        new AD_ERR("AD_STAT::getbits()  Wrong Type !");
271        return 0;
272    }
273    return markdata;
274}
275
276float * AD_STAT::getfloat() {
277    if (marktype != ad_floats) {
278        new AD_ERR("AD_STAT::getfloat()  Wrong Type !");
279        return 0;
280    }
281    return markdatafloat;
282}
283
284GB_UINT4 * AD_STAT::getint() {
285    if (marktype != ad_ints) {
286        new AD_ERR("AD_STAT::getint()  Wrong Type !");
287        return 0;
288    }
289    return markdataint;
290}
291
292
293AD_ERR *AD_STAT::put() {
294    char *error;
295    if (gb_char_mark == 0 && GB_FLOAT_mark == 0 && GB_INT_mark == 0)
296        return new AD_ERR("AD_SEQ::write not possible!");
297    if (GB_FLOAT_mark != 0) {
298        error = (char *)GB_write_floats(GB_FLOAT_mark,markdatafloat,nmark);
299        if (error != 0) {
300            return new AD_ERR(error);
301        }
302    }
303    if  (gb_char_mark != 0) {
304        char c_0_buf[] = "x";
305        c_0_buf[0]     = c_0;
306        error          = (char *)GB_write_bits(gb_char_mark,markdata,nmark,c_0_buf);
307        if (error != 0) {
308            return new AD_ERR(error);
309        }
310    }
311    if  (GB_INT_mark != 0) {
312        error = (char *)GB_write_ints(GB_INT_mark,markdataint,nmark);
313        if (error != 0) {
314            return new AD_ERR(error);
315        }
316    }
317    return 0;
318}
319
320AD_ERR *AD_STAT::put(char *markings, int len) {
321    // hier gehoert ein test ob in markings zulaessige
322    // markierungsdaten stehen ... not implemented
323    if (marktype != ad_bits) {
324        return new AD_ERR("*AD_STAT::put(char * ... WRONG TYPE",CORE);
325    }
326    markdata = markings;
327    nmark = len;
328    put();
329    return 0;
330}
331
332int AD_STAT::time_stamp(void)
333{
334    return GB_read_clock(gb_mark);
335}
336
337
338AD_ERR *AD_STAT::put(float *markings, int len) {
339    // hier gehoert ein test ob in markings zulaessige
340    // markierungsdaten stehen ... not implemented
341    if (marktype != ad_floats) {
342        return new AD_ERR("*AD_STAT::put(float *... WRONG TYPE",CORE);
343    }
344    markdatafloat = markings;
345    nmark = len;
346    put();
347    return 0;
348}
349
350AD_ERR *AD_STAT::put(GB_UINT4 *markings, int len) {
351    if (marktype != ad_ints) {
352        return new AD_ERR("*AD_STAT::put(int * ... WRONG TYPE",CORE);
353    }
354    markdataint = markings;
355    nmark = len;
356    put();
357    return 0;
358}
359
360AD_TYPES AD_STAT::type() {
361    return marktype;
362}
363
364
365
366
367/*********************
368AD_SEQ
369**********************/
370void AD_SEQ_delcall(GBDATA *gb_seq,AD_SEQ *ad_seq)
371{
372    gb_seq = gb_seq;
373    ad_seq->exit();
374}
375
376
377int AD_SEQ_updatecall(GBDATA *gb_seq,AD_SEQ *ad_seq)
378// behandelt ein update der sequenz in der Datenbank
379// problem -> wenn editiert wird ni
380//
381//
382{
383    long new_time_stamp;
384    if (gb_seq != ad_seq->gb_seq)
385        new AD_ERR("AD_SEQ: WRONG update callback",CORE);
386    new_time_stamp = GB_read_clock(gb_seq);
387    if (ad_seq->timestamp != new_time_stamp) {
388        ad_seq->timestamp = new_time_stamp;
389        if (ad_seq->seq && ad_seq->gb_seq) {
390            ad_seq->update();
391        }
392    }
393    return 0;
394    GB_CSTR old = (GB_CSTR)GB_read_old_value();
395    if (!old) return 0;
396    printf("old:        %40s\n",old);
397    GB_CSTR n = GB_read_char_pntr(gb_seq);
398    printf("old:        %40s\n",n);
399    return 0;
400}
401
402AD_SEQ::AD_SEQ()
403{
404    memset(this,0,sizeof(AD_SEQ));      // no virtual members !!!
405}
406
407AD_SEQ::~AD_SEQ()
408// gibt speicherplatz fuer sequenz frei
409{
410    if (seq){
411        new AD_ERR("AD_SEQ: no exit() !!");
412        delete seq;
413        seq = 0;
414    }
415}
416
417
418AD_ERR * AD_SEQ::init(AD_CONT * adptr)
419// nur moeglich fals schon eine Sequence existiert
420{
421    ad_cont = adptr;
422    if (ad_cont->gb_ali == NULL)
423        return new AD_ERR("AD_SEQ.init() : not existing sequence\n");
424    this->update();
425    if (gb_seq){
426        GB_add_callback(gb_seq, GB_CB_CHANGED, (GB_CB) AD_SEQ_updatecall, (int *) this);
427        GB_add_callback(gb_seq, GB_CB_DELETE, (GB_CB) AD_SEQ_delcall, (int *) this);
428    }else{
429        timestamp = 10000000;
430    }
431
432    return 0;
433}
434
435
436AD_ERR * AD_SEQ::exit()
437{
438    delete seq;
439    const char *s = "Sequence Deleted";
440    seq_len = strlen(s);
441    seq = new char[seq_len+1];
442    strcpy(seq, s);
443
444    if (gb_seq) {
445        // GB_remove_callback(gb_seq,GB_CB_CHANGED,(GB_CB)AD_SEQ_updatecall,(int *)this);       // already deleted
446        // GB_remove_callback(gb_seq,GB_CB_DELETE,(GB_CB)AD_SEQ_delcall,(int *)this);
447        gb_seq = 0;
448        gbdataptr = gb_seq;
449        return 0;
450    } else
451        return new      AD_ERR("AD_SEQ: exit() without init()");
452}
453
454
455AD_ERR * AD_SEQ::update()
456{
457    // holt die sequenz nocheinmal aus der Datenbank
458    // z.B. nach update_callback notwendig
459    long laenge,i;
460    const char *sequenz = 0;
461
462    seq_len = ad_cont->ad_ali->len();
463    if (!gb_seq){
464        gb_seq = GB_entry(ad_cont->gb_ali,"data");
465        if (gb_seq) nseq_but_filter = 0;
466    }
467    if (!gb_seq) {
468        gb_seq = GB_entry(ad_cont->gb_ali,"bits");
469        if (gb_seq && GB_read_type(gb_seq) == GB_BITS) nseq_but_filter = 1;
470        else    gb_seq = 0;
471    }
472
473    if (gb_seq) {
474        if (!nseq_but_filter) {
475            sequenz = GB_read_char_pntr(gb_seq);
476            laenge = GB_read_string_count(gb_seq);
477#if 0
478            if (laenge>seq_len){
479                seq_len = laenge;
480                long i;
481                for (i= seq_len; i < laenge; i++) {
482                    if (sequenz[i] != SEQ_POINT) break;
483                }
484                if ( i < laenge) {
485                    gb_seq = 0;
486                    sequenz = "Too long sequence: Please increase alignment length";
487                    laenge = strlen(sequenz);
488                }else{
489                    laenge = seq_len;
490                }
491            }
492#endif
493        }else{
494            laenge = GB_read_bits_count(gb_seq);
495            //                  if (laenge>seq_len){
496            //                          seq_len = laenge;
497            //                          gb_seq = 0;
498            //                          sequenz = "Too long filter: Please increase alignment length";
499            //                          laenge = strlen(sequenz);
500            //                  }else{
501            sequenz = GB_read_bits_pntr(gb_seq,'.','x');
502            //                  }
503            nseq_but_filter = 1;
504        }
505    }
506
507    if (!gb_seq) {
508        if (!sequenz) sequenz = "No Sequence available.................";
509        laenge = strlen(sequenz);
510    }
511    gbdataptr = gb_seq;
512    if (laenge>seq_len) seq_len = laenge;                       /* overlong sequence */
513    delete seq;
514    seq = (char *)malloc((size_t)seq_len + 1);
515    strncpy(seq,sequenz,(int)seq_len);
516    for ( i = laenge; i < seq_len; i++) {
517        seq[i] = SEQ_POINT;
518    }
519    seq[seq_len] = '\0';
520    timestamp = time_stamp();
521
522    return 0;
523}
524
525char * AD_SEQ::get()
526{
527    return seq;
528}
529
530int AD_SEQ::len()
531{
532    return seq_len;
533}
534
535AD_ERR * AD_SEQ::put()
536{
537    char *error;
538    if (gb_seq == 0)
539        return new AD_ERR("AD_SEQ::write not possible!");
540    if (nseq_but_filter) {
541        error = (char *)GB_write_bits(gb_seq,seq,seq_len, ".");
542    }else{
543        error = (char *)GB_write_string(gb_seq,seq);
544    }
545
546    if (!error) {
547        timestamp = time_stamp();
548        return 0;
549    } else {
550        this->update();
551        return new AD_ERR(error);
552    }
553}
554
555AD_ERR *AD_SEQ::create(void) {
556    return 0;
557}
558
559
560int AD_SEQ::time_stamp(void)
561{
562    if (!gb_seq) return 0x3fffffff;
563    return GB_read_clock(gb_seq);
564}
565
566
567/*** EDIT Functions *******/
568// dont call put operations !!!!!!!!!!
569
570AD_ERR * AD_SEQ::insert(char *text,long position, int direction) {
571    long i;
572    int text_len = strlen(text);
573    if (text_len ==0) return 0;
574
575    if ( position + text_len > seq_len) {
576        return new AD_ERR("AD_SEQ::insert after end of sequence !");
577    }
578    if (direction>=0){
579        if ( text_len + position >= seq_len) {
580            return new AD_ERR("AD_SEQ::You cannot insert that many characters after cursor !");
581        }
582        for (i = seq_len - text_len; i<seq_len; i++) {
583            if (!ADPP_IS_ALIGN_CHARACTER(seq[i])) {
584                return new AD_ERR("AD_SEQ::insert: end of alignment reached !");
585            }
586        }
587        for (i= seq_len-text_len-1; i>=position;i--) {
588            seq[i+text_len] = seq[i];
589        }
590
591        for (i = 0 ;i<text_len;i++) {
592            seq[position + i] = text[i];
593        }
594    }else{
595        if ( position - text_len < 0) {
596            return new AD_ERR("AD_SEQ::You cannot insert that many characters before cursor !");
597        }
598        for (i = 0; i<text_len; i++) {
599            if (!ADPP_IS_ALIGN_CHARACTER(seq[i])) {
600                return new AD_ERR("AD_SEQ::insert: start of alignment reached !");
601            }
602        }
603        for (i= 0; i<position-text_len;i++) {
604            seq[i] = seq[i+text_len];
605        }
606
607        for (i = 0 ;i<text_len;i++) {
608            seq[position - i -1] = text[i];
609        }
610    }
611    return 0;
612}
613
614AD_ERR  * AD_SEQ::remove(int charsToDelete,long position, int direction) {
615    long new_len;
616    long i;
617    if (direction<0) position -= charsToDelete;
618    if ((position >= seq_len) || (charsToDelete == 0) || (seq_len - charsToDelete < 0)) {
619        return new AD_ERR("AD_SEQ::delete outside sequence !");
620    }
621    if ((charsToDelete + position) >= seq_len) {
622        charsToDelete = (int)(seq_len-position);
623    }
624    new_len = seq_len - charsToDelete;
625    if (direction>=0){
626        strncpy((char *)&seq[position],
627                (const char *)&seq[position+charsToDelete],
628                (int)(new_len-position));
629        for (i = new_len; i<seq_len; i++) {
630            seq[i] = SEQ_POINT;
631        }
632    }else{
633        for (i=position+charsToDelete-1;i>=charsToDelete;i--) {
634            seq[i] = seq[i-charsToDelete];
635        }
636        for (i = 0; i<charsToDelete; i++) {
637            seq[i] = SEQ_POINT;
638        }
639    }
640    seq[seq_len] = '\0';
641    return 0;
642}
643
644
645AD_ERR * AD_SEQ::replace(char *text,long position, int direction) {
646    int text_len = strlen(text);
647    int i;
648    if (direction>=0){
649
650        if ((position + text_len > seq_len) || (position > seq_len)) {
651            return new AD_ERR("AD_SEQ.replace() ERROR ! Replace after end of sequence !");
652        }
653        for ( i = 0; i < text_len ; i ++) {
654            seq[i+position] = text[i];
655        }
656    }else{
657        if ((position - text_len < 0 ) || (position > seq_len)) {
658        return new AD_ERR("AD_SEQ.replace() ERROR ! Replace before start of sequence !");
659    }
660    for ( i = 0; i < text_len ; i ++) {
661        seq[position - i - 1] = text[i];
662    }
663}
664return 0;
665}
666
667AD_ERR  *AD_SEQ::swap_gaps(long position, char ch){
668    long i;
669    for (i = position; i < seq_len; i++) {
670        if ( !ADPP_IS_ALIGN_CHARACTER(seq[i])) break;
671        seq[i] = ch;
672    }
673    for (i = position; i >= 0; i--) {
674        if ( !ADPP_IS_ALIGN_CHARACTER(seq[i])) break;
675        seq[i] = ch;
676    }
677    return 0;
678}
679
680
681AD_ERR *AD_SEQ::check_base(char chr,long position, int direction) {
682    if (direction < 0) position --;
683    if (position <0 && position >= seq_len) return new AD_ERR();
684    if (seq[position] != chr){
685        return new AD_ERR();            // beep beep
686    }
687    return 0;
688}
689
690AD_ERR *AD_SEQ::push(long position, int direction) {
691    long i;
692    long end = this->get_next_gap(position,direction);
693    if ( end < 0   || end  >= seq_len  )
694        return 0;       // end reached
695    if (end == position) return 0;              // dont push '.'
696
697    int gap = '-';
698    int offset;
699
700    if (direction < 0) {
701        position --;
702        end --;
703        if (end<0) return 0;
704        offset = 1;
705    }else{
706        offset = -1;
707    }
708
709    if ( position+offset <= 0 || position+offset >= seq_len-1 ||
710         seq[position+offset] == '.') gap = '.';
711
712    for (i= end  ; i!= position; i -= direction) {
713        seq[i] = seq[i- direction];
714    };
715    seq[position] = gap;
716    return 0;
717}
718
719
720AD_ERR *AD_SEQ::jump(long position, int direction) {
721    int offset = 0; if (direction <0) offset = -1;
722    long npos = get_next_base(position,-direction) + offset;
723    int swap;
724    position += offset;
725    swap = seq[position]; seq[position] = seq[npos]; seq[npos] = swap;
726    return 0;
727}
728
729AD_ERR *AD_SEQ::fetch(long position, int direction) {
730    int offset = 0; if (direction <0) offset = -1;
731    long npos = get_next_base(position,direction) + offset;
732    if (npos <0 || npos >= seq_len) return 0;
733    int swap;
734    position += offset;
735    swap = seq[position]; seq[position] = seq[npos]; seq[npos] = swap;
736    return 0;
737}
738
739long AD_SEQ::get_next_base(long position, int direction) {
740    long pos;
741    if (direction < 0) position--;
742    for (pos = position; pos>=0 && pos < seq_len; pos += direction){
743        if (!ADPP_IS_ALIGN_CHARACTER(seq[pos])) break;
744    }
745    if (direction<0) pos++;
746    if (pos <  0 ) pos = 0;
747    if (pos > seq_len) pos = seq_len;
748    return pos;
749}
750
751long AD_SEQ::get_next_gap(long position, int direction) {
752    long pos;
753    if (direction < 0) position--;
754    for (pos = position; pos >= 0 && pos < seq_len; pos += direction){
755        if (ADPP_IS_ALIGN_CHARACTER(seq[pos])) break;
756    }
757    if (direction<0) pos++;
758    if (pos <  0 ) pos = 0;
759    if (pos > seq_len) pos = seq_len;
760    return pos;
761}
762
763
764AD_ERR  *AD_SEQ::command( AW_key_mod keymod, AW_key_code keycode, char key, int direction, long &cursorpos, int & changed_flag)
765{
766    static int nrepeat = 0;
767    long oldcursorpos = cursorpos;
768    char str[2];
769    str[0] = key;
770    str[1] = 0;
771    changed_flag = 0;
772    if (direction > 0) {
773        direction = 1;          // may be inverted to allow right to left insert
774    }else{
775        direction = -1;
776    }
777
778    if ((cursorpos > seq_len) || (cursorpos < 0 )) {
779        return new AD_ERR("AD_SEQ.command ERROR ! Cursor out of sequence !");
780    }
781
782    AD_EDITMODI edit_mode = this->get_ad_main()->mode;
783    AD_ERR *ad_err = 0;
784    long        h,offset;
785
786    switch (keycode) {
787        case AW_KEY_ASCII:
788            if (key == ' ') {
789                long left;
790                int l,r;
791                left = cursorpos-1; if (left<0) left = 0;
792                l = seq[left]; r = seq[cursorpos];
793                key = '-';
794                if (ADPP_IS_ALIGN_CHARACTER(l)) key = l;
795                if (ADPP_IS_ALIGN_CHARACTER(r)) key = r;
796                str[0] = key;
797            }
798            switch (edit_mode) {
799                case AD_allign:
800                    if (isdigit(key)) {
801                        nrepeat = nrepeat * 10 + (key - '0');
802                        break;
803                    }
804                    if (ADPP_IS_ALIGN_CHARACTER(key)){
805                        long left;
806                        int l,r;
807                        left = cursorpos-1; if (left<0) left = 0;
808                        l = seq[left]; r = seq[cursorpos];
809                        if (ADPP_IS_ALIGN_CHARACTER(l) && l!=key) {
810                            ad_err = this->swap_gaps(left,key);
811                        }else if (ADPP_IS_ALIGN_CHARACTER(r) && r!=key ) {
812                            ad_err = this->swap_gaps(cursorpos,key);
813                        }else if (!ad_err){
814                            if (!nrepeat) nrepeat = 1;
815                            char *nstr = (char *)calloc(1,nrepeat+1);
816                            int i;
817                            for (i = 0; i< nrepeat; i++) nstr[i] = key;
818                            ad_err = this->insert(nstr,cursorpos,direction);
819                            if (!ad_err) cursorpos+=direction*nrepeat;
820                            delete nstr;
821                        }
822                        changed_flag = 1;
823                    }else{
824                        cursorpos = get_next_base(cursorpos,direction);
825                        ad_err = check_base(key,cursorpos,direction);
826                        if (!ad_err) cursorpos+=direction;
827                    }
828                    nrepeat = 0;
829                    break;
830                case AD_replace:
831                    ad_err = this->replace(str,cursorpos,direction);
832                    if (!ad_err) cursorpos+=direction;
833                    changed_flag = 1;
834                    break;
835                case AD_insert:
836                    ad_err = this->insert(str,cursorpos,direction);
837                    if (!ad_err) cursorpos+=direction;
838                    if (!ad_err) changed_flag = 1;
839                    break;
840                default:        break;
841            }
842            break;
843        case AW_KEY_HOME:
844            nrepeat = 0;
845            cursorpos = get_next_base(0,1);
846            break;
847        case AW_KEY_END:
848            nrepeat = 0;
849            cursorpos = get_next_base(seq_len,-1);
850            break;
851        case AW_KEY_DELETE:
852        case AW_KEY_BACKSPACE:
853            if (!nrepeat) nrepeat = 1;
854            if (edit_mode != AD_allign) nrepeat = 1;
855            if (keycode == AW_KEY_DELETE || keymod ) {
856                h = cursorpos;
857            }else{
858                h = cursorpos;
859                if (direction > 0) {
860                    cursorpos-=nrepeat;
861                }else{
862                    cursorpos+= nrepeat;
863                }
864                if (cursorpos <0 || cursorpos >= seq_len) {
865                    cursorpos = h;
866                    if (nrepeat >1) {
867                        ad_err = new AD_ERR("Out of sequence");
868                    }
869                    nrepeat = 0;
870                    break;
871                }
872                h = cursorpos;
873            }
874            switch (edit_mode) {
875                case AD_allign:
876                    {
877                        int repeat;
878                        ad_err = 0;
879                        if (direction>=0) offset = 0; else offset = -nrepeat;
880                        for (repeat = nrepeat-1; repeat>=0; repeat--) {
881                            if (!ADPP_IS_ALIGN_CHARACTER(seq[h+offset+repeat])){
882                                ad_err = new AD_ERR("You cannot remove bases in align mode");
883                                break;
884                            }
885                        }
886                        if (ad_err) break;
887                    }
888                case AD_replace:
889                case AD_insert:
890                    ad_err = this->remove(nrepeat,h,direction);
891                    if (!ad_err) changed_flag = 1;
892                    break;
893                default:        break;
894            }
895            nrepeat = 0;
896
897            break;
898
899        case AW_KEY_LEFT:
900        case AW_KEY_RIGHT:
901            direction = 1;
902            if (keycode == AW_KEY_LEFT) direction = -1;
903            if (keymod == 0) {
904                if (!nrepeat) nrepeat = 1;
905                cursorpos+= direction * nrepeat;
906                nrepeat = 0;
907                break;
908            }
909            nrepeat = 0;
910            if (direction>=0) offset = 0; else offset = -1;
911            if (keymod & AW_KEYMODE_CONTROL) {      // push pull
912                if (ADPP_IS_ALIGN_CHARACTER(seq[cursorpos+offset])){
913                    // pull operation
914                    h = this->get_next_gap(     cursorpos,-direction);
915                }else{  // push
916                    h = cursorpos;
917                }
918                ad_err = this->push(h,direction);
919                if (!ad_err) {
920                    changed_flag = 1;
921                    cursorpos += direction;
922                }
923            }else if (keymod & AW_KEYMODE_ALT) {    // jump fetch
924                if (ADPP_IS_ALIGN_CHARACTER(seq[cursorpos+offset])){
925                    // fetch
926                    ad_err = fetch(cursorpos,direction);
927                }else if (ADPP_IS_ALIGN_CHARACTER(seq[cursorpos-1-offset])){
928                    ad_err = jump(cursorpos,direction);
929                }else{
930                    ad_err = new AD_ERR("You can only jump single bases !!!");
931                }
932                if (!ad_err) {
933                    changed_flag = 1;
934                    cursorpos += direction;
935                }
936            }else{
937                if (ADPP_IS_ALIGN_CHARACTER(seq[cursorpos+offset])){
938                    cursorpos = get_next_base(cursorpos,direction);
939                }else{
940                    cursorpos = get_next_gap(cursorpos,direction);
941                }
942            }
943            break;
944        default:
945            break;
946
947    }
948    if (ad_err) cursorpos = oldcursorpos;
949    if (cursorpos < 0 ) cursorpos = 0;
950    if (cursorpos > seq_len) cursorpos = seq_len;
951
952    return ad_err;
953}
954
955AD_ERR * AD_SEQ::changemode(AD_EDITMODI mod) {
956    // check rights
957    // not implemented
958    this->get_ad_main()->mode = mod;
959    return 0;
960}
961
962AD_EDITMODI AD_SEQ::mode() {
963    return this->get_ad_main()->mode;
964}
965
966
967
968
969
970/***************************
971AD_CONT
972container wird mit spezies,alignment initialisiert
973entspricht ungefaehr dem ali_xxx container der ARB DB
974********************/
975
976AD_CONT::AD_CONT()
977{
978    ad_species =0;
979    ad_ali =0;
980    gb_ali =0;
981    gb_species = 0;
982}
983
984AD_CONT::~AD_CONT()
985{
986    // vergessen ein exit zu machen !
987    if (ad_species) {
988        new AD_ERR("AD_CONT: NO exit() !!",CORE);
989    }
990}
991
992AD_ERR * AD_CONT::init(AD_SPECIES * adptr1,AD_ALI * adptr2)
993{
994    if (!con_insert(adptr1,adptr2)) // test ob container schoneinmal initialisiert
995        return new AD_ERR("AD_CONT::init  ONLY ONE AD_CONT PER SPECIES/ALIGN");
996    ad_species = adptr1;
997    ad_ali      = adptr2;
998    gb_species = ad_species->gb_species;
999    gb_ali = GB_entry(gb_species,ad_ali->name());
1000    if (gb_ali) {
1001        (ad_species->count) ++; // in species eintragen
1002        (ad_ali->count) ++;
1003    }else{
1004        con_remove(ad_species,ad_ali);
1005    }
1006    AD_READWRITE::gbdataptr = gb_ali;
1007    return 0;
1008}
1009
1010AD_ERR *AD_CONT::create(AD_SPECIES * adptr1,AD_ALI *adptr2)
1011{
1012    GBDATA *erg =  GBT_add_data(adptr1->gb_species,adptr2->name(),"data", GB_STRING);
1013    if (!erg) return new AD_ERR(GB_await_error());
1014    return this->init(adptr1,adptr2);
1015}
1016
1017AD_ERR * AD_CONT::exit()
1018{
1019    if (ad_species && gb_ali) {
1020        ad_species->count --; // verweis in AD_SPEC loeschen
1021        ad_ali->count --;
1022        con_remove(ad_species,ad_ali);
1023    }
1024    ad_species = 0;ad_ali = 0;
1025    AD_READWRITE::gbdataptr = 0;
1026    return 0;
1027}
1028
1029int AD_CONT::eof(void)
1030{
1031    if (gb_ali) return 0;
1032    return 1;
1033}
1034
1035int AD_CONT::con_insert(AD_SPECIES * adptr1,AD_ALI * adptr2)
1036{
1037    class CONTLIST *cont;
1038    cont = adptr1->container;
1039    return cont->insert(adptr1,adptr2);
1040    // ist der selbe container schon vorhanden ?
1041}
1042
1043
1044void AD_CONT::con_remove(AD_SPECIES * adptr1,AD_ALI * adptr2)
1045// entfernt ein AD_CONT aus der Liste in AD_species
1046{
1047    class CONTLIST *cont;
1048    cont = adptr1->container;
1049    cont->remove(adptr1,adptr2);
1050    // entfernt den container
1051}
1052
1053int AD_CONT::get_cach_flag()
1054// implementiert um mehrfachzeiger zu vermeiden
1055{
1056    AD_MAIN * adptr;
1057    adptr = ad_species->ad_main;
1058    return adptr->get_cach_flag();
1059}
1060
1061
1062
Note: See TracBrowser for help on using the repository browser.