19 #define SAFE_EDITING // undef this to remove sequence test code
21 int ED4_Edit_String::nrepeat = 0;
22 int ED4_Edit_String::nrepeat_zero_requested = 0;
23 int ED4_Edit_String::nrepeat_is_already_set = 0;
25 GB_ERROR ED4_Edit_String::insert(
char *text,
long position,
int direction,
int removeAtNextGap) {
27 int text_len = strlen(text);
28 if (text_len == 0)
return NULp;
33 rest_len = seq_len-position;
39 if (rest_len<=0 || text_len>rest_len) {
43 if (removeAtNextGap) {
44 int nextGap = get_next_gap(position, direction);
49 int afterGap = nextGap+direction;
51 if (afterGap>=0 && afterGap<seq_len) {
52 if (seq[afterGap]!=seq[nextGap]) {
53 return GBS_global_string(
"Only one gap %s text => insert aborted", direction>=0 ?
"after" :
"before");
57 rest_len = (afterGap-position)*direction;
61 if (text_len + position >= seq_len) {
65 for (i = rest_len-text_len; i<rest_len; i++) {
71 for (i = position+rest_len-text_len-1; i>=position; i--) {
72 seq[i+text_len] = seq[i];
75 for (i = 0; i<text_len; i++) {
76 seq[position+i] = text[i];
80 if (position - text_len < 0) {
81 return GBS_global_string(
"You cannot insert that many characters before cursor!");
84 for (i = 0; i<text_len; i++) {
89 for (i = 0; i<position-text_len; i++) {
90 seq[i] = seq[i+text_len];
93 for (i = 0; i<text_len; i++) {
94 seq[position-i-1] = text[i];
101 return GBS_global_string(
"There are no/not enough gaps at %s of sequence => can't insert characters%s",
102 direction >= 0 ?
"end" :
"start",
103 direction >= 0 ?
"\nMaybe your sequences are not formatted?" :
"");
106 GB_ERROR ED4_Edit_String::remove(
int len,
long position,
int direction,
int insertAtNextGap) {
110 if ((len + position) >= seq_len) len = (
int)(seq_len-position);
111 rest_len = seq_len-position;
115 if (len>position) len = position;
119 if ((position >= seq_len) || (len == 0) || (seq_len - len < 0)) {
123 if (insertAtNextGap) {
124 int nextGap = get_next_gap(position+len*direction, direction);
127 rest_len = (nextGap-position)*direction;
131 int new_len = rest_len-len;
135 for (i=0; i<new_len; i++) {
136 seq[position+i] = seq[position+len+i];
138 for (; i<rest_len; i++) {
139 seq[position+i] =
'.';
143 for (i=0; i<new_len; i++) {
144 seq[position-i] = seq[position-len-i];
146 for (; i<rest_len; i++) {
147 seq[position-i] =
'.';
156 GB_ERROR ED4_Edit_String::replace(
char *text,
long position,
int direction) {
157 int text_len = strlen(text);
161 if ((position + text_len > seq_len) || (position > seq_len)) {
164 for (i = 0; i < text_len; i ++) {
165 seq[i+position] = text[i];
169 if ((position - text_len < 0) || (position > seq_len)) {
172 for (i = 0; i < text_len; i ++) {
173 seq[position - i - 1] = text[i];
179 GB_ERROR ED4_Edit_String::swap_gaps(
long position,
char ch) {
181 for (i = position; i < seq_len; i++) {
185 for (i = position; i >= 0; i--) {
193 GB_ERROR ED4_Edit_String::moveBase(
long source_position,
long dest_position,
unsigned char gap_to_use) {
194 e4_assert(source_position!=dest_position);
196 if (!legal_seqpos(dest_position) || !legal_seqpos(source_position)) {
197 return "Position out of sequence";
201 int direction = dest_position<source_position ? -1 : 1;
202 int base = seq[source_position];
204 seq[source_position] = gap_to_use;
206 long p = source_position+direction;
207 while (p!=dest_position) {
211 return "Internal error: Tried to change base order in moveBase()";
219 seq[dest_position] = base;
223 GB_ERROR ED4_Edit_String::shiftBases(
long source_pos,
long last_source,
long dest_pos,
int direction,
long *last_dest,
unsigned char gap_to_use) {
232 err = moveBase(source_pos, dest_pos, gap_to_use);
233 if (err || source_pos>=last_source)
break;
245 err = moveBase(source_pos, dest_pos, gap_to_use);
246 if (err || source_pos<=last_source)
break;
256 *last_dest = dest_pos;
262 long ED4_Edit_String::get_next_base(
long position,
int direction) {
264 if (direction < 0) position--;
265 for (pos = position; pos>=0 && pos < seq_len; pos += direction) {
269 return pos<0 || pos>=seq_len ? -1 : pos;
271 long ED4_Edit_String::get_next_gap(
long position,
int direction) {
273 if (direction < 0) position--;
274 for (pos = position; pos >= 0 && pos < seq_len; pos += direction) {
278 return pos<0 || pos>=seq_len ? -1 : pos;
280 long ED4_Edit_String::get_next_visible_base(
long position,
int direction) {
282 if (direction < 0) position--;
283 for (pos = position; pos>=0 && pos < seq_len; pos += direction) {
289 return pos<0 || pos>=seq_len ? -1 : pos;
291 long ED4_Edit_String::get_next_visible_gap(
long position,
int direction) {
293 if (direction < 0) position--;
294 for (pos = position; pos >= 0 && pos < seq_len; pos += direction) {
300 return pos<0 || pos>=seq_len ? -1 : pos;
302 long ED4_Edit_String::get_next_visible_pos(
long position,
int direction) {
304 if (direction < 0) position--;
305 for (pos = position; pos >= 0 && pos < seq_len; pos += direction) {
310 return pos<0 || pos>=seq_len ? -1 : pos;
313 unsigned char ED4_Edit_String::get_gap_type(
long pos,
int direction) {
315 if (!legal_seqpos(pos))
return '.';
358 long &seq_pos,
bool &changed_flag,
ED4_CursorJumpType& cursor_jump,
bool &cannot_handle,
bool &write_fault,
GBDATA* gb_data,
bool is_sequence)
362 if (keymod+keycode+key==0)
return NULp;
366 long old_seq_pos = seq_pos;
374 direction = direction>0 ? 1 : -1;
376 if ((cursorpos > screen_len) || (cursorpos < 0)) {
380 memcpy(seq2, seq, seq_len);
391 return GBS_global_string(
"Cursor out of sequence at screen_pos #%i!", cursorpos);
397 bool reinterpret_key =
true;
399 while (reinterpret_key) {
400 reinterpret_key =
false;
404 int new_seq_pos = get_next_visible_base(0, 1);
405 if (new_seq_pos>=0) seq_pos = new_seq_pos==seq_pos ? 0 : new_seq_pos;
410 int new_seq_pos = get_next_visible_base(seq_len, -1);
411 if (new_seq_pos>=0) {
412 int new_gap_pos = get_next_visible_gap(new_seq_pos, 1);
413 if (new_gap_pos >= 0) {
414 seq_pos = new_gap_pos==seq_pos ? seq_len : new_gap_pos;
436 seq_pos += direction;
438 while (legal_curpos(seq_pos) && !remap->
is_shown(seq_pos));
443 if (mode==
AD_NOWRITE) { write_fault = 1;
break; }
445 int jump_or_fetch = 0;
446 int push_or_pull = 0;
451 while (!ad_err && n-->0 && legal_curpos(seq_pos)) {
454 int adjacent_scr_pos = cursorpos - (direction<0);
461 int real_adjacent_seq_pos = seq_pos - (direction<0);
463 if (adjacent_seq_pos<0 || adjacent_seq_pos>=seq_len) {
471 if (adjacent_scr_pos>=0) {
472 long pos = adjacent_seq_pos;
476 pos = get_next_visible_base(pos, direction);
477 if (pos>=0) pos = get_next_visible_gap(pos, direction);
480 pos = get_next_visible_gap(pos, direction);
484 ? (direction<0 ? pos+1 : pos)
485 : (direction<0 ? 0 : seq_len-1));
489 else { seq_pos = get_next_visible_gap(pos, direction); }
491 if (direction<0) { seq_pos = seq_pos==-1 ? 0 : seq_pos+1; }
492 else { seq_pos = seq_pos==-1 ? seq_len : seq_pos; }
501 if (is_consensus) { cannot_handle = 1;
return NULp; }
504 if (jump_or_fetch!=1) {
506 long source_pos = get_next_base(adjacent_seq_pos, direction);
507 if (source_pos==-1) {
511 ad_err = moveBase(source_pos, adjacent_seq_pos, get_gap_type(source_pos, direction));
512 seq_pos = adjacent_seq_pos + (direction>0);
520 if (jump_or_fetch!=2) {
522 int next_gap = adjacent_seq_pos - direction;
525 int dest_pos = get_next_base(next_gap, -direction);
528 dest_pos = direction>0 ? 0 : seq_len-1;
531 dest_pos += direction;
535 ad_err = moveBase(adjacent_seq_pos, dest_pos, get_gap_type(adjacent_seq_pos, direction));
537 seq_pos = get_next_base(seq_pos, direction)+(direction<0);
539 seq_pos = direction<0 ? 0 : seq_len;
565 if (is_consensus) { cannot_handle = 1;
return NULp; };
568 long dest_pos = real_adjacent_seq_pos;
569 long source_pos = real_adjacent_seq_pos-direction;
574 long next_gap = get_next_gap(source_pos, -direction);
575 long last_source = next_gap>=0 ? next_gap : (direction>0 ? 0 : seq_len-1);
578 last_source = get_next_base(last_source, direction);
581 ad_err = shiftBases(source_pos, last_source, dest_pos, direction,
NULp,
582 is_sequence ? get_gap_type(last_source, -direction) :
'.');
585 seq_pos = dest_pos + (direction>0);
594 long next_gap = get_next_gap(adjacent_seq_pos, direction);
596 if (next_gap>=0 && push_or_pull!=2) {
598 long dest_pos = next_gap;
599 long source_pos = get_next_base(next_gap, -direction);
600 long last_source = adjacent_seq_pos;
603 ad_err = shiftBases(source_pos, last_source, dest_pos, direction, &dest_pos,
604 is_sequence ? get_gap_type(last_source, -direction) :
'.');
607 seq_pos = dest_pos + (direction<0);
628 if (seq_pos <0 || seq_pos >= seq_len) {
637 if (is_consensus) { cannot_handle = 1;
return NULp; };
638 if (keymod) {
return NULp; }
640 if (mode==
AD_NOWRITE) { write_fault = 1;
break; }
648 if (direction>=0) offset = 0;
649 else offset = -nrepeat;
651 for (len = nrepeat-1; len>=0; len--) {
662 ad_err =
remove(nrepeat, h, direction, !is_sequence);
696 if (key >0 && key<=26) {
700 if (is_consensus) { cannot_handle = 1;
return NULp; };
704 localDataAccess.do_refresh =
false;
718 for (pos=0; pos < seq_pos && pos<seq_len; pos++) {
727 freeset(seq, aligned_seq);
731 int basesLeftOf2 = 0;
732 int lastCorrectPos = -1;
733 for (pos=0; pos<seq_pos && pos<seq_len; pos++) {
736 if (basesLeftOf2 == basesLeftOf) lastCorrectPos = pos;
740 if (basesLeftOf != basesLeftOf2) {
741 if (lastCorrectPos != -1) {
742 seq_len = lastCorrectPos+1;
745 for (; pos<seq_len; pos++) {
748 if (basesLeftOf2 == basesLeftOf) {
765 if (is_consensus) { cannot_handle = 1;
return NULp; };
790 else ad_err =
ARB_strdup(
"Not at helix position");
794 static int last_mode;
796 int next_mode = last_mode;
798 if (current_mode==0) {
799 if (last_mode==0) next_mode = 2;
807 last_mode = current_mode;
817 if (is_consensus) { cannot_handle = 1;
return NULp; }
824 reinterpret_key =
true;
830 reinterpret_key =
true;
846 if (is_consensus) { cannot_handle = 1;
return NULp; }
847 if (mode==
AD_NOWRITE) { write_fault = 1;
break; }
851 long left = seq_pos>0 ? seq_pos-1 : 0;
853 int r = seq[seq_pos];
859 key = gapchar_at_pos ? gapchar_at_pos :
'-';
862 case AW_KEYMODE_CONTROL:
863 if (gapchar_at_pos) key = gapchar_at_pos ==
'-' ?
'.' :
'-';
875 long left = seq_pos>0 ? seq_pos-1 : 0;
877 int r = seq[seq_pos];
880 else if (
ED4_is_gap_character(r) && r!=key) { ad_err = swap_gaps(seq_pos, key); changed_flag = 1; }
888 char *nstr = ARB_calloc<char>(nrepeat+1);
890 for (
int i = 0; i< nrepeat; i++) nstr[i] = key;
891 ad_err = insert(nstr, seq_pos, direction, 0);
892 if (!ad_err) seq_pos = get_next_visible_pos(seq_pos+(direction>=0 ? nrepeat : 0), direction);
899 while (nrepeat && !ad_err) {
901 seq_pos = get_next_visible_base(seq_pos, direction);
902 if (seq_pos<0 || seq_pos>=seq_len) {
905 else if (seq[seq_pos]!=key) {
906 ad_err =
GBS_global_string(
"Base '%c' at %li does not match '%c'", seq[seq_pos], seq_pos, key);
909 seq_pos = get_next_visible_pos(seq_pos, direction)+1;
920 while (nrepeat && !ad_err) {
923 ad_err = replace(str, seq_pos, 1);
931 int left_pos = get_next_visible_pos(seq_pos, -1);
933 if (left_pos>=0) ad_err = replace(str, left_pos+1, -1);
934 else ad_err =
"End of sequence";
945 while (nrepeat && !ad_err) {
948 ad_err = insert(str, seq_pos, 1, !is_sequence);
956 int left_pos = get_next_visible_pos(seq_pos, -1);
959 ad_err = insert(str, left_pos+1, -1, !is_sequence);
962 ad_err =
"End of sequence";
989 if (ad_err) seq_pos = old_seq_pos;
990 seq_pos = seq_pos<0 ? 0 : (seq_pos>seq_len ? seq_len : seq_pos);
1001 remap(
ED4_ROOT->root_group_man->remap())
1025 seq_len = strlen(seq);
1031 seq_len = seq_len_int;
1039 AW_advice(
"You have keymapped the space-key!\n"
1040 "The new functionality assigned to space-key is not available when\n"
1041 "key-mapping is enabled.\n",
1051 nrepeat_zero_requested = 1;
1053 nrepeat_is_already_set = 1;
1061 if (nrepeat_is_already_set) { nrepeat = 0; }
1062 nrepeat_zero_requested = 0;
1065 nrepeat = nrepeat * 10 + (map_key -
'0');
1066 if (nrepeat>10000) {
1069 else if (nrepeat<0) {
1075 printf(
"nrepeat=%i\n", nrepeat);
1080 nrepeat_zero_requested = 0;
1087 printf(
"nrepeat is %i\n", nrepeat);
1093 if (is_remapped_sequence) {
1101 bool write_fault = 0;
1122 ?
"Check 'Show all gaps' when editing remarks"
1123 :
"This terminal is write-protected!");
1132 int old_seq_len_int;
1134 old_seq_len = old_seq_len_int;
1156 nrepeat_is_already_set = 0;
1157 if (nrepeat_zero_requested) {
1158 nrepeat_zero_requested = 0;
GB_ERROR GB_begin_transaction(GBDATA *gbd)
bool is_pairpos(size_t pos) const
GB_ERROR GB_commit_transaction(GBDATA *gbd)
int screen_to_sequence(int screen_pos) const
ED4_terminal * working_terminal
#define ED4_AWAR_COMPRESS_SEQUENCE_GAPS
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
ED4_group_manager * is_in_folded_group() const
GBDATA * get_species_pointer() const
static GB_ERROR toggle_cursor_group_folding()
void FastAligner_set_align_current(AW_root *root, AW_default db1)
#define ED4_AWAR_FAST_CURSOR_JUMP
void ED4_request_relayout()
char * ARB_strdup(const char *str)
bool is_shown(int seq_pos) const
#define ED4_AWAR_COMPRESS_SEQUENCE_TYPE
ED4_species_manager * get_consensus_manager() const
ED4_reference * reference
const char * GBS_global_string(const char *templat,...)
void AW_normal_cursor(AW_root *awr)
void AW_advice(const char *message, AW_Advice_Type type, const char *title, const char *corresponding_help)
Show a message box with an advice for the user.
ED4_multi_species_manager * get_multi_species_manager() const
size_t opposite_position(size_t pos) const
GB_ERROR edit(ED4_work_info *info) __ATTR__USERESULT
size_t get_max_screen_pos() const
ED4_terminal * owner_of_cursor
void ED4_request_full_refresh()
GBDATA * GB_get_grandfather(GBDATA *gbd)
void AW_clock_cursor(AW_root *awr)
bool has_property(ED4_properties prop) const
void FastAligner_set_reference_species(AW_root *root)
int sequence_to_screen(int sequence_pos) const
void FastAligner_start(AW_window *aw, const AlignDataAccess *data_access)
static void error(const char *msg)
AW_window * current_aww()
#define ED4_AWAR_DIGITS_AS_REPEAT
int sequence_to_screen_PLAIN(int sequence_pos) const
GB_ERROR ED4_repeat_last_search(ED4_window *ed4w)
void ED4_viewDifferences_setNewReference()
int GB_read_flag(GBDATA *gbd)
AW_awar * awar(const char *awar)
bool setCursorTo(ED4_cursor *cursor, int seq_pos, bool unfoldGroups, ED4_CursorJumpType jump_type)
ED4_cursor & current_cursor()
int MAXSEQUENCECHARACTERLENGTH
void GB_write_flag(GBDATA *gbd, long flag)
ED4_CursorJumpType cursor_jump
char * GB_read_string(GBDATA *gbd)
GB_ERROR write_sequence(const char *seq, int seq_len)
ED4_window * current_ed4w()
void ED4_toggle_viewDifferences(AW_root *awr)
bool ED4_is_gap_character(char chr)
void aw_message(const char *msg)
char * resolve_pointer_to_string_copy(int *str_len=NULp) const FINAL_OVERRIDE
const AlignDataAccess * ED4_get_aligner_data_access()
int get_sequence_pos() const
GB_transaction ta(gb_var)
ED4_manager * get_parent(ED4_level lev) const
static int info[maxsites+1]
GB_ERROR write_int(long aw_int)
static void toggle_mark_of_specData(GBDATA *gb_data)