ARB
ED4_block.cxx
Go to the documentation of this file.
1 #include "ed4_awars.hxx"
2 #include "ed4_class.hxx"
3 #include "ed4_tools.hxx"
4 #include "ed4_block.hxx"
5 #include "ed4_edit_string.hxx"
6 #include "ed4_list.hxx"
7 
8 #include <awt_sel_boxes.hxx>
9 #include <fast_aligner.hxx>
10 
11 #include <aw_awars.hxx>
12 #include <aw_msg.hxx>
13 #include <aw_root.hxx>
14 #include <aw_select.hxx>
15 
16 #include <arbdbt.h>
17 #include <arb_defs.h>
18 #include <gb_aci.h>
19 
20 #include <climits>
21 #include <cctype>
22 #include <map>
23 
24 using namespace std;
25 
26 // --------------------------------------------------------------------------------
27 
28 class ED4_block : virtual Noncopyable {
29  // stores columnrange of highlighted region
30  // (linerange is stored in EDIT4 marks)
32  bool columnBlockUsed;
33  PosRange range;
34 
35 public:
37  : type(ED4_BT_NOBLOCK),
38  columnBlockUsed(false)
39  {}
40 
41  ED4_blocktype get_type() const { return type; }
42  void set_type(ED4_blocktype bt);
43  void toggle_type();
44  void autocorrect_type();
45 
46  const PosRange& get_colblock_range() const {
47  e4_assert(type == ED4_BT_COLUMNBLOCK || type == ED4_BT_MODIFIED_COLUMNBLOCK); // otherwise range may be undefined
48  return range;
49  }
50  void set_range(const PosRange& new_range) { range = new_range; }
51 
53  PosRange res;
54 
55  switch (type) {
56  case ED4_BT_NOBLOCK:
57  res = PosRange::empty();
58  break;
59 
60  case ED4_BT_COLUMNBLOCK:
62  res = get_colblock_range();
63  break;
64 
65  case ED4_BT_LINEBLOCK:
66  res = PosRange::whole();
67  break;
68  }
69 
70  return res;
71  }
72 };
73 
75 
76 // --------------------------------------------------------------------------------
77 
78 class SeqPart {
79  const char *seq;
80 
81  int offset;
82  int len; // of part
83 
84  static char to_gap(char c) { return ED4_is_gap_character(c) ? c : 0; }
85 
86 public:
87  SeqPart(const char *seq_, int offset_, int len_)
88  : seq(seq_),
89  offset(offset_),
90  len(len_)
91  {}
92 
93  const char *data() const { return seq+offset; }
94  int length() const { return len; }
95 
96  // detect which gap to use at border of SeqPart:
97  char left_gap() const {
98  char gap = to_gap(seq[offset]);
99  if (!gap && offset) gap = to_gap(seq[offset-1]);
100  if (!gap) gap = '-';
101  return gap;
102  }
103  char right_gap() const {
104  char gap = to_gap(seq[offset+len-1]);
105  if (!gap) gap = to_gap(seq[offset+len]);
106  if (!gap) gap = '-';
107  return gap;
108  }
109 };
110 
111 // --------------------------------------------------------------------------------
112 
114  seq_term->request_refresh();
115  ED4_columnStat_terminal *colStatTerm = seq_term->corresponding_columnStat_terminal();
116  if (colStatTerm) colStatTerm->request_refresh();
117 }
118 
119 static void refresh_highlighted(bool refresh_name_terminals) {
121  while (listElem) {
122  ED4_species_name_terminal *name_term = listElem->elem()->object;
123  ED4_sequence_terminal *seq_term = name_term->corresponding_sequence_terminal();
124 
125  if (refresh_name_terminals) name_term->request_refresh();
126  if (seq_term) col_block_refresh_on_seq_term(seq_term);
127 
128  listElem = listElem->next();
129  }
130 }
131 
132 // --------------------------------------------------------------------------------
133 
135  if (type != bt) {
136  type = bt;
137  refresh_highlighted(true);
139  columnBlockUsed = true;
140  }
141  }
142 }
143 
145  switch (type) {
146  case ED4_BT_NOBLOCK: {
147  aw_message("No block highlighted.");
148  break;
149  }
150  case ED4_BT_LINEBLOCK: {
151  if (columnBlockUsed) {
153  }
154  else {
155  aw_message("No columnblock marked so far - I can't guess the column range");
156  }
157  break;
158  }
160  case ED4_BT_COLUMNBLOCK: {
162  break;
163  }
164  }
165 }
166 
168  // this has to be called every time the selection has changed
169 
170  if (!ED4_ROOT->highlighted_objects->head()) { // no objects are highlighted
172  }
173  else {
174  switch (type) {
175  case ED4_BT_NOBLOCK: {
177  break;
178  }
179  case ED4_BT_COLUMNBLOCK: {
181  break;
182  }
183  case ED4_BT_LINEBLOCK:
185  break;
186  }
187  }
188  }
189 }
190 
191 // --------------------------------------------------------------------------------
192 
193 // if block_operation returns NULp => no changes will be made to database
194 // otherwise the changed sequence(part) will be written to the database
195 
197  GBDATA *gbd = term->get_species_pointer();
198  GB_ERROR error = NULp;
199 
200  if (gbd) {
201  char *seq = GB_read_string(gbd);
202  int len = GB_read_string_count(gbd);
203 
204  int new_len;
205  char *new_seq = block_operator.operate(SeqPart(seq, 0, len), new_len);
206  error = block_operator.get_error();
207 
208  if (new_seq) {
209  if (new_len<len) {
210  memcpy(seq, new_seq, new_len);
211  char gap = ED4_is_gap_character(seq[len-1]) ? seq[len-1] : '.';
212  int l;
213  for (l=new_len; l<len; l++) {
214  seq[l] = gap;
215  }
216  seq[l] = 0;
217  }
218  else if (new_len>len) {
219  for (int l=new_len-1; l>=len; l--) {
220  if (!ED4_is_gap_character(new_seq[l])) {
221  error = "Result of block-operation to large (not enough gaps at end of sequence data)";
222  break;
223  }
224  }
225 
226  if (!error) { // there are enough gaps at end of sequence
227  memcpy(seq, new_seq, len);
228  }
229  }
230  else {
231  memcpy(seq, new_seq, len);
232  }
233 
234  if (!error) {
235  error = GB_write_string(gbd, seq);
236  if (!error) term->request_refresh();
237  }
238  free(new_seq);
239  }
240  free(seq);
241  }
242 
243  return error;
244 }
245 
246 // uses range_col1 till range_col2 as range
248  GBDATA *gbd = term->get_species_pointer();
249  GB_ERROR error = NULp;
250 
251  if (gbd) {
252  char *seq = GB_read_string(gbd);
253  int len = GB_read_string_count(gbd);
254 
255  ExplicitRange range(block.get_colblock_range(), len);
256 
257  int len_part = range.size();
258  char *seq_part = seq+range.start();
259  int new_len;
260  char *new_seq_part = block_operator.operate(SeqPart(seq, range.start(), len_part), new_len);
261  error = block_operator.get_error();
262 
263  if (new_seq_part) {
264  if (new_len<len_part) {
265  memcpy(seq_part, new_seq_part, new_len);
266  char gap = '-';
267  if (seq_part[len_part-1] == '.' || seq_part[len_part] == '.') gap = '.';
268 
269  for (int l=new_len; l<len_part; l++) {
270  seq_part[l] = gap;
271  }
272  }
273  else if (new_len>len_part) {
274  for (int l=new_len-1; l>=len_part; l--) {
275  if (!ED4_is_gap_character(new_seq_part[l])) {
276  error = "Result of block-operation to large (not enough gaps at end of marked columnblock)";
277  break;
278  }
279  }
280 
281  if (!error) { // there are enough gaps at end of sequence
282  memcpy(seq_part, new_seq_part, len_part);
283  }
284  }
285  else {
286  memcpy(seq_part, new_seq_part, len_part);
287  }
288  delete new_seq_part;
289 
290  if (!error) {
291  error = GB_write_autoconv_string(gbd, seq);
292  if (!error) term->request_refresh();
293  }
294  }
295 
296  delete seq;
297  }
298 
299  return error;
300 }
301 
302 static void ED4_with_whole_block(const ED4_block_operator& block_operator) {
305 
306  typedef map<ED4_window*, int> CursorPositions;
307  CursorPositions at_base;
308 
309  for (ED4_window *win = ED4_ROOT->first_window; win; win = win->next) {
310  ED4_cursor& cursor = win->cursor;
311  if (cursor.owner_of_cursor) at_base[win] = cursor.get_base_position();
312  }
313 
314 
315  switch (block.get_type()) {
316  case ED4_BT_NOBLOCK: {
317  aw_message("No block marked -- use right mouse button");
318  break;
319  }
320  case ED4_BT_LINEBLOCK:
322  case ED4_BT_COLUMNBLOCK: {
324  while (listElem && !error) {
325  ED4_species_name_terminal *nameTerm = listElem->elem()->object;
326  ED4_sequence_terminal *seqTerm = nameTerm->corresponding_sequence_terminal();
327 
328  error = block.get_type() == ED4_BT_LINEBLOCK
329  ? perform_block_operation_on_whole_sequence(block_operator, seqTerm)
330  : perform_block_operation_on_part_of_sequence(block_operator, seqTerm);
331 
332  listElem = listElem->next();
333  }
334  break;
335  }
336  default: {
337  error = "Illegal blocktype";
338  break;
339  }
340  }
341 
342  if (error) error = GBS_global_string("[In block operation] %s", error);
343  GB_end_transaction_show_error(gb_main, error, aw_message);
344 
345  if (!error) {
346  ED4_ROOT->root_group_man->update_remap(); // if mapping is out-of-date, cursor positioning below will misbehave
347 
348  for (CursorPositions::iterator ab = at_base.begin(); ab != at_base.end(); ++ab) {
349  ED4_window *win = ab->first;
350  win->cursor.jump_base_pos(ab->second, ED4_JUMP_KEEP_VISIBLE); // restore cursor at same base
351  }
352  }
353 }
354 
356  if (block.get_type() == ED4_BT_NOBLOCK) return false;
357  if (!term->containing_species_manager()->is_highlighted()) return false;
358 
359  range = block.get_range_according_to_type();
360  return true;
361 }
362 
364 void ED4_setBlocktype(ED4_blocktype bt) { block.set_type(bt); }
367 
369  static ED4_sequence_terminal *last_term1, *last_term2;
370  static PosRange last_range;
371 
372  if (!term1) return; // e.g. when 1st click was into consensus
373 
374  if (pos1>pos2) {
375  block.set_range(PosRange(pos2, pos1));
376  }
377  else {
378  block.set_range(PosRange(pos1, pos2));
379  }
380 
381  if (block.get_type()==ED4_BT_MODIFIED_COLUMNBLOCK) {
382  refresh_highlighted(false);
383  }
384  else {
385  { // ensure term1 is the upper terminal
386  AW_pos dummy, y1, y2;
387 
388  term1->calc_world_coords(&dummy, &y1);
389  term2->calc_world_coords(&dummy, &y2);
390 
391  if (y1>y2) {
392  ED4_sequence_terminal *t = term1; term1 = term2; term2 = t;
393  AW_pos y = y1; y1 = y2; y2 = y;
394  }
395  }
396 
397  int do_above = 1; // we have to update terminals between last_term1 and term1
398  int do_below = 1; // we have to update terminals between term2 and last_term2
399 
400  ED4_terminal *term = term1;
401 
402  bool xRangeChanged = block.get_range_according_to_type() != last_range;
403 
404  while (term) {
405  if (term->is_sequence_terminal()) {
406  ED4_sequence_terminal *seq_term = term->to_sequence_terminal();
407 
408  if (seq_term==last_term1) {
409  do_above = 0;
410  }
411  if (seq_term==last_term2) {
412  do_below = 0;
413  }
414 
415  ED4_species_name_terminal *name_term = seq_term->corresponding_species_name_terminal();
416  ED4_species_manager *species_man = name_term->containing_species_manager();
417  if (species_man->is_highlighted()) { // already highlighted
418  if (xRangeChanged) {
420  }
421  }
422  else { // highlight it
423  if (!species_man->is_consensus_manager()) {
424  ED4_ROOT->add_to_highlighted(name_term);
425  }
426  }
427  }
428  if (term==term2) {
429  break;
430  }
431  term = term->get_next_terminal();
432  }
433 
434  if (!initial_call) {
435  if (do_below) {
436  while (term) {
437  if (term->is_species_name_terminal()) {
438  ED4_species_manager *species_man = term->containing_species_manager();
439  if (species_man->is_highlighted() && !species_man->is_consensus_manager()) {
440  ED4_ROOT->remove_from_highlighted(term->to_species_name_terminal());
441  }
442  }
443  if (term==last_term2) break;
444  term = term->get_next_terminal();
445  }
446  }
447 
448  if (do_above) {
449  term = last_term1->corresponding_species_name_terminal();
450  while (term && term!=term1) {
451  if (term->is_species_name_terminal()) {
452  ED4_species_manager *species_man = term->containing_species_manager();
453  if (species_man->is_highlighted() && !species_man->is_consensus_manager()) {
454  ED4_ROOT->remove_from_highlighted(term->to_species_name_terminal());
455  }
456  }
457  term = term->get_next_terminal();
458  }
459  }
460  }
461  }
462 
463  last_term1 = term1;
464  last_term2 = term2;
465  last_range = block.get_range_according_to_type();
466 
467  // save range of highlighted block in global awar:
468  {
469  const char *range_as_text = GBS_global_string("%i-%i", info2bio(last_range.start()), info2bio(last_range.end()));
470  ED4_ROOT->aw_root->awar(AWAR_RANGE)->write_string(range_as_text);
471  }
472 }
473 
475  static ED4_sequence_terminal *fix_term = NULp;
476  static ED4_index fix_pos = 0;
477 
478  ED4_index seq_pos;
479  {
480  AW_pos termw_x, termw_y;
481  seq_term->calc_world_coords(&termw_x, &termw_y);
482 
483  ED4_index scr_pos = ED4_ROOT->pixel2pos(event->x - termw_x);
484  ED4_remap *remap = ED4_ROOT->root_group_man->remap();
485  seq_pos = remap->screen_to_sequence(scr_pos);
486  }
487 
488  switch (event->type) {
489  case AW_Mouse_Press: {
490  if (block.get_type() == ED4_BT_NOBLOCK) { // initial columnblock
491  if (!seq_term->is_consensus_terminal()) {
493 
494  fix_term = seq_term;
495  fix_pos = seq_pos;
496 
497  highlight_and_update(fix_term, seq_term, fix_pos, seq_pos, 1);
498  }
499  }
500  else if (block.get_type()==ED4_BT_LINEBLOCK) { // change lineblock to columnblock
502 
503  fix_term = seq_term;
504  if (seq_pos<(MAXSEQUENCECHARACTERLENGTH/2)) { // in first half of sequence
505  fix_pos = MAXSEQUENCECHARACTERLENGTH;
506  }
507  else {
508  fix_pos = 0;
509  }
510 
511  highlight_and_update(fix_term, seq_term, fix_pos, seq_pos, 1);
512  }
513  else { // expand columnblock (search nearest corner/border -> fix opposite corner/border)
515 
517  e4_assert(listElem);
518 
519  if (block.get_type()==ED4_BT_COLUMNBLOCK) {
520  AW_pos min_term_y = LONG_MAX;
521  AW_pos max_term_y = LONG_MIN;
522  ED4_species_name_terminal *min_term = NULp;
523  ED4_species_name_terminal *max_term = NULp;
524  AW_pos xpos, ypos;
525 
526  while (listElem) {
527  ED4_species_name_terminal *name_term = listElem->elem()->object;
528  name_term->calc_world_coords(&xpos, &ypos);
529 
530  if (ypos<min_term_y) {
531  min_term_y = ypos;
532  min_term = name_term;
533  }
534  if (ypos>max_term_y) {
535  max_term_y = ypos;
536  max_term = name_term;
537  }
538 
539  listElem = listElem->next();
540  }
541 
542  seq_term->calc_world_coords(&xpos, &ypos);
543  ED4_species_name_terminal *fix_name_term;
544  if (fabs(ypos-min_term_y)<fabs(ypos-max_term_y)) { // seq_term is closer to min_term
545  fix_name_term = max_term; // select max_term as fixed corner
546  }
547  else {
548  fix_name_term = min_term;
549  }
550  e4_assert(fix_name_term);
551  fix_term = fix_name_term->corresponding_sequence_terminal();
552  }
553 
554  AW_screen_area area_rect;
555  {
556  AW_pos ex = event->x;
557  AW_pos ey = event->y;
558  current_ed4w()->world_to_win_coords(&ex, &ey);
559 
560  if (ED4_ROOT->get_area_rectangle(&area_rect, ex, ey)!=ED4_R_OK) {
561  e4_assert(0);
562  break;
563  }
564  }
565 
566 
567  const ED4_remap *rm = ED4_ROOT->root_group_man->remap();
568 
569  PosRange screen_range = rm->clip_screen_range(seq_term->calc_interval_displayed_in_rectangle(&area_rect));
570  int scr_pos = rm->sequence_to_screen(seq_pos);
571 
572  PosRange block_screen_range = rm->sequence_to_screen(block.get_colblock_range());
573  PosRange block_visible_part = intersection(screen_range, block_screen_range);
574 
575  if (block_visible_part.is_empty()) {
576  if (scr_pos>block_screen_range.end()) {
577  fix_pos = block.get_colblock_range().start();
578  }
579  else {
580  e4_assert(scr_pos<block_screen_range.start());
581  fix_pos = block.get_colblock_range().end();
582  }
583  }
584  else {
585  int dist_left = abs(scr_pos-block_visible_part.start());
586  int dist_right = abs(scr_pos-block_visible_part.end());
587 
588  if (dist_left < dist_right) { // click nearer to left border of visible part of block
589  fix_pos = block.get_colblock_range().end(); // keep right block-border
590  }
591  else {
592  fix_pos = block.get_colblock_range().start();
593  }
594  }
595 
596  highlight_and_update(fix_term, seq_term, fix_pos, seq_pos, 0);
597  }
598  break;
599  }
600  case AW_Mouse_Drag: {
601  highlight_and_update(fix_term, seq_term, fix_pos, seq_pos, 0);
602  break;
603  }
604  case AW_Mouse_Release: {
605  highlight_and_update(fix_term, seq_term, fix_pos, seq_pos, 0);
606  break;
607  }
608  default: {
609  e4_assert(0);
610  break;
611  }
612  }
613 }
614 
615 // --------------------------------------------------------------------------------
616 // Replace
617 
618 inline bool matchesUsingWildcard(GB_CSTR s1, GB_CSTR s2, int len) {
619  // s2 may contain '?' as wildcard
620  int cmp = 0;
621 
622  for (int i = 0; i<len && !cmp; ++i) {
623  cmp = int(s1[i])-int(s2[i]);
624  if (cmp && s2[i] == '?') cmp = 0;
625  }
626 
627  return !cmp;
628 }
629 
630 class replace_op : public ED4_block_operator { // derived from Noncopyable
631  const char *oldString;
632  const char *newString;
633 
634  int olen;
635  int nlen;
636 
637 public:
638  replace_op(const char *oldString_, const char *newString_)
639  : oldString(oldString_),
640  newString(newString_)
641  {
642  olen = strlen(oldString);
643  nlen = strlen(newString);
644  }
645 
646  char* operate(const SeqPart& part, int& new_len) const OVERRIDE {
647  int maxlen;
648  int len = part.length();
649  int max_o = len-olen;
650 
651  if (nlen<=olen) {
652  maxlen = len;
653  }
654  else {
655  maxlen = (len/olen+1)*nlen;
656  }
657 
658  char *new_seq = ARB_alloc<char>(maxlen+1);
659  int replaced = 0;
660  int o = 0;
661  int n = 0;
662 
663  const char *sequence = part.data();
664  while (o<len) {
665  if (o <= max_o && matchesUsingWildcard(sequence+o, oldString, olen)) {
666  memcpy(new_seq+n, newString, nlen);
667  n += nlen;
668  o += olen;
669  replaced++;
670  }
671  else {
672  new_seq[n++] = sequence[o++];
673  }
674  }
675  new_seq[n] = 0;
676 
677  if (replaced) {
678  new_len = n;
679  }
680  else {
681  freenull(new_seq);
682  }
683 
684  return new_seq;
685  }
686 };
687 
689  AW_root *awr = ED4_ROOT->aw_root;
693 }
694 
696  AW_window_simple *aws = new AW_window_simple;
697 
698  aws->init(root, "REPLACE", "Search & Replace");
699  aws->load_xfig("edit4/replace.fig");
700 
701  aws->at("close");
702  aws->callback(AW_POPDOWN);
703  aws->create_button("CLOSE", "Close", "C");
704 
705  aws->at("help");
706  aws->callback(makeHelpCallback("e4_replace.hlp"));
707  aws->create_button("HELP", "Help", "H");
708 
709  aws->at("spattern");
710  aws->create_input_field(ED4_AWAR_REP_SEARCH_PATTERN, 30);
711 
712  aws->at("rpattern");
713  aws->create_input_field(ED4_AWAR_REP_REPLACE_PATTERN, 30);
714 
715  aws->at("go");
716  aws->callback(replace_in_block);
717  aws->create_button("GO", "Go", "G");
718 
719  return aws;
720 }
721 
722 // --------------------------------------------------------------------------------
723 // Other block operations
724 
725 inline char *dont_return_unchanged(char *result, int& new_len, const SeqPart& part) {
726  if (result) {
727  if (new_len == part.length()) {
728  if (memcmp(result, part.data(), new_len) == 0) {
729  freenull(result);
730  }
731  }
732  }
733  return result;
734 }
735 
736 class case_op : public ED4_block_operator {
737  bool to_upper;
738 public:
739  case_op(bool to_upper_) : to_upper(to_upper_) {}
740 
741  char *operate(const SeqPart& part, int& new_len) const OVERRIDE {
742  int len = part.length();
743  const char *seq = part.data();
744  char *new_seq = ARB_alloc<char>(len+1);
745 
746  if (to_upper) {
747  for (int i=0; i<len; i++) new_seq[i] = toupper(seq[i]);
748  }
749  else {
750  for (int i=0; i<len; i++) new_seq[i] = tolower(seq[i]);
751  }
752  new_seq[len] = 0;
753 
754  new_len = len;
755  return dont_return_unchanged(new_seq, new_len, part);
756  }
757 };
758 
760  bool reverse;
761  bool complement;
762  char T_or_U;
763 
764 public:
765  revcomp_op(GB_alignment_type aliType, bool reverse_, bool complement_)
766  : reverse(reverse_),
767  complement(complement_),
768  T_or_U(0)
769  {
770  if (complement) {
771  error = GBT_determine_T_or_U(aliType, &T_or_U, reverse ? "reverse-complement" : "complement");
772  }
773  }
774 
775  char *operate(const SeqPart& part, int& new_len) const OVERRIDE {
776  char *result = NULp;
777  if (!error) {
778  int len = part.length();
779  if (complement) {
780  result = GBT_complementNucSequence(part.data(), len, T_or_U);
781  if (reverse) freeset(result, GBT_reverseNucSequence(result, len));
782  }
783  else if (reverse) result = GBT_reverseNucSequence(part.data(), len);
784 
785  new_len = len;
786  }
787  return dont_return_unchanged(result, new_len, part);
788  }
789 
790 };
791 
793  int direction;
794 public:
795  unalign_op(int direction_) : direction(direction_) {}
796 
797  char *operate(const SeqPart& part, int& new_len) const OVERRIDE {
798  int len = part.length();
799  const char *seq = part.data();
800  char *result = ARB_alloc<char>(len+1);
801 
802  int o = 0;
803  int n = 0;
804 
805  while (o<len) {
806  if (!ED4_is_gap_character(seq[o])) result[n++] = seq[o];
807  o++;
808  }
809 
810  if (n<len) { // (move and) dot rest
811  int gapcount = len-n;
812  switch (direction) {
813  case 1: // rightwards
814  memmove(result+gapcount, result, n);
815  memset(result, part.left_gap(), gapcount);
816  break;
817  case 0: { // center
818  int leftgaps = gapcount/2;
819  int rightgaps = gapcount-leftgaps;
820 
821  memmove(result+leftgaps, result, n);
822  memset(result, part.left_gap(), leftgaps);
823  memset(result+leftgaps+n, part.right_gap(), rightgaps);
824 
825  break;
826  }
827  case -1: // leftwards
828  memset(result+n, part.right_gap(), gapcount);
829  break;
830  }
831  }
832  result[len] = 0;
833  new_len = len;
834 
835  return dont_return_unchanged(result, new_len, part);
836  }
837 
838 
839 };
840 
841 class shift_op : public ED4_block_operator {
842  int direction;
843 
844  char *shift_left_sequence(const SeqPart& part, int& new_len) const {
845  char *result = NULp;
846  const char *seq = part.data();
847 
848  if (!ED4_is_gap_character(seq[0])) {
849  error = "Need a gap at block start for shifting left";
850  }
851  else {
852  int len = part.length();
853  ARB_alloc(result, len+1);
854  result[len] = 0;
855  new_len = len;
856  result[len-1] = part.right_gap();
857  memcpy(result, seq+1, len-1);
858  }
859  return result;
860  }
861 
862  char *shift_right_sequence(const SeqPart& part, int& new_len) const {
863  char *result = NULp;
864  const char *seq = part.data();
865  int len = part.length();
866 
867  if (!ED4_is_gap_character(seq[len-1])) {
868  error = "Need a gap at block end for shifting right";
869  }
870  else {
871  ARB_alloc(result, len+1);
872  result[len] = 0;
873  new_len = len;
874  result[0] = part.left_gap();
875  memcpy(result+1, seq, len-1);
876  }
877  return result;
878  }
879 
880 
881 public:
882  shift_op(int direction_) : direction(direction_) {}
883 
884  char *operate(const SeqPart& part, int& new_len) const OVERRIDE {
885  char *result = direction<0
886  ? shift_left_sequence(part, new_len)
887  : shift_right_sequence(part, new_len);
888  return dont_return_unchanged(result, new_len, part);
889  }
890 };
891 
893  switch (operationType) {
894  case ED4_BO_UPPER_CASE: ED4_with_whole_block(case_op(true)); break;
895  case ED4_BO_LOWER_CASE: ED4_with_whole_block(case_op(false)); break;
896 
900 
904 
907 
908  default: {
909  e4_assert(0);
910  break;
911  }
912  }
913 }
914 
915 // --------------------------------------
916 // modify range of selected sai
917 
918 #define AWAR_MOD_SAI_SCRIPT "modsai/script"
919 
920 static void modsai_cb(AW_window *aww) {
921  ED4_MostRecentWinContext context;
922 
923  ED4_cursor *cursor = &current_cursor();
924  GB_ERROR error = NULp;
925 
926  if (!cursor->in_SAI_terminal()) {
927  error = "Please select the SAI you like to modify";
928  }
929  else if (block.get_type() == ED4_BT_NOBLOCK) {
930  error = "Please highlight the range where the SAI shall be modified";
931  }
932  else {
933  AW_root *aw_root = aww->get_root();
934  char *script = aw_root->awar(AWAR_MOD_SAI_SCRIPT)->read_string();
935  const char *sainame = aw_root->awar(AWAR_SAI_NAME)->read_char_pntr();
936 
938  GB_transaction ta(gb_main);
939  GBDATA *gb_sai = GBT_find_SAI(gb_main, sainame);
940 
941  if (!gb_sai) {
942  error = GB_have_error()
943  ? GB_await_error()
944  : GBS_global_string("Failed to find SAI '%s'", sainame);
945  }
946  else {
947  GBDATA *gb_data = GBT_find_sequence(gb_sai, ED4_ROOT->get_alignment_name());
948 
949  if (!gb_data) error = GB_await_error();
950  else {
951  char *seq = GB_read_string(gb_data); // @@@ NOT_ALL_SAI_HAVE_DATA
952  int len = GB_read_string_count(gb_data);
953 
954  ExplicitRange range(block.get_range_according_to_type(), len);
955  char *part = range.dup_corresponding_part(seq, len);
956 
957  char *result = GB_command_interpreter_in_env(part, script, GBL_simple_call_env(gb_sai));
958  if (!result) error = GB_await_error();
959  else {
960  int reslen = strlen(result);
961  if (reslen>range.size()) {
962  error = GBS_global_string("Cannot insert modified range (result too long; %i>%i)", reslen, range.size());
963  }
964  else {
965  memcpy(seq+range.start(), result, reslen);
966  int rest = range.size()-reslen;
967  if (rest>0) memset(seq+range.start()+reslen, '-', rest);
968 
969  error = GB_write_string(gb_data, seq);
970  }
971  free(result);
972  }
973 
974  free(part);
975  free(seq);
976  }
977  }
978  free(script);
979  error = ta.close(error);
980  }
981 
982  aw_message_if(error);
983 }
984 
987 
988  AW_window_simple *aws = new AW_window_simple;
989  aws->init(root, "modsai", "Modify SAI range");
990  aws->load_xfig("edit4/modsai.fig");
991 
992  aws->at("close");
993  aws->callback(AW_POPDOWN);
994  aws->create_button("CLOSE", "Close", "C");
995 
996  aws->at("help");
997  aws->callback(makeHelpCallback("e4_modsai.hlp"));
998  aws->create_button("HELP", "Help", "H");
999 
1001  GB_ERROR error;
1002  {
1003  StorableSelectionList storable_sellist(TypedSelectionList("sellst", sellist, "SRT/ACI scripts", "srt_aci"));
1004  error = storable_sellist.load(GB_path_in_ARBLIB("sellists/mod_sequence*.sellst"), false);
1005  }
1006  aw_message_if(error);
1007 
1008  aws->at("go");
1009  aws->callback(modsai_cb);
1010  aws->create_button("go", "GO");
1011 
1012  return aws;
1013 }
1014 
1015 
1016 // --------------------------------------------------------------------------------
1017 
1018 #ifdef UNIT_TESTS
1019 #ifndef TEST_UNIT_H
1020 #include <test_unit.h>
1021 #endif
1022 
1023 static arb_test::match_expectation blockop_expected_io(const ED4_block_operator& blockop, const char *oversized_input, const char *expected_result, const char *part_of_error) {
1024  int whole_len = strlen(oversized_input);
1025  SeqPart part(oversized_input, 1, whole_len-2);
1026  int new_len = 0;
1027  char *result = blockop.operate(part, new_len);
1028 
1029  using namespace arb_test;
1030 
1031  expectation_group expectations;
1032  expectations.add(part_of_error
1033  ? that(blockop.get_error()).does_contain(part_of_error)
1034  : that(blockop.get_error()).is_equal_to_NULL());
1035  expectations.add(that(result).is_equal_to(expected_result));
1036  if (expected_result) expectations.add(that(new_len).is_equal_to(whole_len-2));
1037 
1038  free(result);
1039 
1040  return all().ofgroup(expectations);
1041 }
1042 
1043 #define TEST_EXPECT_BLOCKOP_PERFORMS(oversized_input,blockop,expected) TEST_EXPECTATION(blockop_expected_io(blockop, oversized_input, expected, NULp))
1044 #define TEST_EXPECT_BLOCKOP_PERFORMS__BROKEN(oversized_input,blockop,expected) TEST_EXPECTATION__BROKEN(blockop_expected_io(blockop, oversized_input, expected, NULp))
1045 #define TEST_EXPECT_BLOCKOP_ERRORHAS(oversized_input,blockop,expected) TEST_EXPECTATION(blockop_expected_io(blockop, oversized_input, NULp, expected))
1046 #define TEST_EXPECT_BLOCKOP_ERRORHAS__BROKEN(oversized_input,blockop,expected) TEST_EXPECTATION__BROKEN(blockop_expected_io(blockop, oversized_input, NULp, expected))
1047 
1048 void TEST_block_operators() {
1050 
1051  // Note: make sure tests perform an identity block operation at least once for each operator
1052 
1053  // replace_op
1054  TEST_EXPECT_BLOCKOP_PERFORMS("-A-C--", replace_op("-", "."), "A.C.");
1055  TEST_EXPECT_BLOCKOP_PERFORMS("-A-C--", replace_op("?", "."), "....");
1056  TEST_EXPECT_BLOCKOP_PERFORMS("AACAG-", replace_op("AC", "CA"), "CAAG");
1057  TEST_EXPECT_BLOCKOP_PERFORMS("-ACAG-", replace_op("A?", "Ax"), "AxAx");
1058 
1059  TEST_EXPECT_BLOCKOP_PERFORMS("GACAG-", replace_op("GA", "AG"), NULp); // unchanged
1060  TEST_EXPECT_BLOCKOP_PERFORMS("GAGAGA", replace_op("GA", "AG"), "AAGG");
1061  TEST_EXPECT_BLOCKOP_PERFORMS("GACAGA", replace_op("GA", "AG"), NULp);
1062  TEST_EXPECT_BLOCKOP_PERFORMS("AGAGAG", replace_op("GA", "AG"), "AGAG");
1063 
1064  // case_op
1065  TEST_EXPECT_BLOCKOP_PERFORMS("-AcGuT-", case_op(true), "ACGUT");
1066  TEST_EXPECT_BLOCKOP_PERFORMS("-AcGuT-", case_op(false), "acgut");
1067  TEST_EXPECT_BLOCKOP_PERFORMS("-acgut-", case_op(false), NULp);
1068  TEST_EXPECT_BLOCKOP_PERFORMS("-------", case_op(false), NULp);
1069 
1070  // revcomp_op
1071  TEST_EXPECT_BLOCKOP_PERFORMS("-Ac-GuT-", revcomp_op(GB_AT_RNA, false, false), NULp); // noop
1072  TEST_EXPECT_BLOCKOP_PERFORMS("-Ac-GuT-", revcomp_op(GB_AT_RNA, true, false), "TuG-cA");
1073  TEST_EXPECT_BLOCKOP_PERFORMS("-Ac-GuT-", revcomp_op(GB_AT_RNA, false, true), "Ug-CaA");
1074  TEST_EXPECT_BLOCKOP_PERFORMS("-Ac-GuT-", revcomp_op(GB_AT_RNA, true, true), "AaC-gU");
1075  TEST_EXPECT_BLOCKOP_PERFORMS("-Ac-GuT-", revcomp_op(GB_AT_DNA, true, true), "AaC-gT");
1076  TEST_EXPECT_BLOCKOP_PERFORMS("-AcGCgT-", revcomp_op(GB_AT_DNA, true, true), NULp);
1077  TEST_EXPECT_BLOCKOP_PERFORMS("--------", revcomp_op(GB_AT_DNA, true, true), NULp);
1078 
1079  TEST_EXPECT_BLOCKOP_PERFORMS("-AR-DQF-", revcomp_op(GB_AT_AA, false, false), NULp); // noop
1080  TEST_EXPECT_BLOCKOP_PERFORMS("-AR-DQF-", revcomp_op(GB_AT_AA, true, false), "FQD-RA");
1081  TEST_EXPECT_BLOCKOP_ERRORHAS("-AR-DQF-", revcomp_op(GB_AT_AA, false, true), "complement not available");
1082  TEST_EXPECT_BLOCKOP_ERRORHAS("-AR-DQF-", revcomp_op(GB_AT_AA, true, true), "reverse-complement not available");
1083 
1084  // unalign_op
1085  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-G--T-", unalign_op(-1), "AcGT----");
1086  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-G-T-T", unalign_op(-1), "AcGT----");
1087  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-G--TT", unalign_op(-1), "AcGT----");
1088  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-G--T.", unalign_op(-1), "AcGT....");
1089  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-G-T.T", unalign_op(-1), "AcGT....");
1090 
1091  TEST_EXPECT_BLOCKOP_PERFORMS("A-Ac-G--T-", unalign_op(+1), "----AcGT");
1092  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-G--T-", unalign_op(+1), "----AcGT");
1093  TEST_EXPECT_BLOCKOP_PERFORMS("A.Ac-G--T-", unalign_op(+1), "....AcGT");
1094  TEST_EXPECT_BLOCKOP_PERFORMS(".A-c-G--T-", unalign_op(+1), "....AcGT");
1095  TEST_EXPECT_BLOCKOP_PERFORMS("AA-c-G--T-", unalign_op(+1), "----AcGT");
1096 
1097  TEST_EXPECT_BLOCKOP_PERFORMS("AA-c-G--TT", unalign_op(0), "--AcGT--");
1098  TEST_EXPECT_BLOCKOP_PERFORMS(".A-c-G--T-", unalign_op(0), "..AcGT--");
1099  TEST_EXPECT_BLOCKOP_PERFORMS(".A-c-G--T.", unalign_op(0), "..AcGT..");
1100  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-G--T.", unalign_op(0), "--AcGT..");
1101  TEST_EXPECT_BLOCKOP_PERFORMS("-A-c-Gc-T.", unalign_op(0), "-AcGcT..");
1102 
1103  TEST_EXPECT_BLOCKOP_PERFORMS("-AcGcT.", unalign_op(0), NULp);
1104  TEST_EXPECT_BLOCKOP_PERFORMS("-AcGcT..", unalign_op(0), NULp);
1105  TEST_EXPECT_BLOCKOP_PERFORMS("--AcGcT.", unalign_op(0), "AcGcT.");
1106 
1107  TEST_EXPECT_BLOCKOP_PERFORMS("-ACGT-", unalign_op(-1), NULp);
1108  TEST_EXPECT_BLOCKOP_PERFORMS("-ACGT-", unalign_op(+1), NULp);
1109  TEST_EXPECT_BLOCKOP_PERFORMS("------", unalign_op(+1), NULp);
1110 
1111  // shift_op
1112  TEST_EXPECT_BLOCKOP_PERFORMS("-A-C--", shift_op(+1), "-A-C"); // take gap outside region
1113  TEST_EXPECT_BLOCKOP_PERFORMS(".A-C--", shift_op(+1), ".A-C"); // -"-
1114  TEST_EXPECT_BLOCKOP_PERFORMS("-.AC--", shift_op(+1), "..AC"); // take gap inside region
1115 
1116  TEST_EXPECT_BLOCKOP_PERFORMS("--A-C-", shift_op(-1), "A-C-"); // same for other direction
1117  TEST_EXPECT_BLOCKOP_PERFORMS("--A-C.", shift_op(-1), "A-C.");
1118  TEST_EXPECT_BLOCKOP_PERFORMS("--AC..", shift_op(-1), "AC..");
1119  TEST_EXPECT_BLOCKOP_PERFORMS("------", shift_op(-1), NULp);
1120 
1121  TEST_EXPECT_BLOCKOP_PERFORMS("G-TTAC", shift_op(-1), "TTA-"); // no gap reachable
1122 
1123  TEST_EXPECT_BLOCKOP_ERRORHAS("GATTAC", shift_op(-1), "Need a gap at block"); // no space
1124  TEST_EXPECT_BLOCKOP_ERRORHAS("GATTAC", shift_op(+1), "Need a gap at block"); // no space
1125 }
1126 
1127 #endif // UNIT_TESTS
1128 
1129 // --------------------------------------------------------------------------------
1130 
unalign_op(int direction_)
Definition: ED4_block.cxx:795
GB_ERROR GB_begin_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2528
char * operate(const SeqPart &part, int &new_len) const OVERRIDE
Definition: ED4_block.cxx:775
const char * GB_ERROR
Definition: arb_core.h:25
string result
GB_TYPES type
int screen_to_sequence(int screen_pos) const
group_matcher all()
Definition: test_unit.h:1011
static GB_ERROR perform_block_operation_on_whole_sequence(const ED4_block_operator&block_operator, ED4_sequence_terminal *term)
Definition: ED4_block.cxx:196
static char * y[maxsp+1]
char left_gap() const
Definition: ED4_block.cxx:97
#define ED4_AWAR_REP_REPLACE_PATTERN
Definition: ed4_awars.hxx:64
AW_window * ED4_create_modsai_window(AW_root *root)
Definition: ED4_block.cxx:985
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
Definition: arbdb.cxx:1387
void load_xfig(const char *file, bool resize=true)
Definition: AW_window.cxx:720
PosRange intersection(PosRange r1, PosRange r2)
Definition: pos_range.h:101
GBDATA * get_species_pointer() const
Definition: ed4_class.hxx:948
const char * data() const
Definition: ED4_block.cxx:93
char * operate(const SeqPart &part, int &new_len) const OVERRIDE
Definition: ED4_block.cxx:646
char * operate(const SeqPart &part, int &new_len) const OVERRIDE
Definition: ED4_block.cxx:741
char * GBT_complementNucSequence(const char *s, int len, char T_or_U)
Definition: adRevCompl.cxx:78
ED4_columnStat_terminal * corresponding_columnStat_terminal() const
Definition: ed4_class.hxx:2005
int start() const
Definition: pos_range.h:60
ExplicitRange clip_screen_range(PosRange screen_range) const
Definition: ed4_class.hxx:1770
static void ED4_with_whole_block(const ED4_block_operator&block_operator)
Definition: ED4_block.cxx:302
shift_op(int direction_)
Definition: ED4_block.cxx:882
void ED4_setBlocktype(ED4_blocktype bt)
Definition: ED4_block.cxx:364
char * dont_return_unchanged(char *result, int &new_len, const SeqPart &part)
Definition: ED4_block.cxx:725
static int pos1
Definition: ClustalV.cxx:58
ED4_returncode get_area_rectangle(AW_screen_area *rect, AW_pos x, AW_pos y)
Definition: ED4_root.cxx:754
char * GBT_reverseNucSequence(const char *s, int len)
Definition: adRevCompl.cxx:66
void GB_end_transaction_show_error(GBDATA *gbd, GB_ERROR error, void(*error_handler)(GB_ERROR))
Definition: arbdb.cxx:2584
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
ED4_root * ED4_ROOT
Definition: ED4_main.cxx:49
ED4_highlighted_list * highlighted_objects
Definition: ed4_class.hxx:1433
bool GB_have_error()
Definition: arb_msg.cxx:338
STL namespace.
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
int size() const
Definition: pos_range.h:69
ED4_terminal * owner_of_cursor
Definition: ed4_class.hxx:644
int get_base_position() const
Definition: ed4_class.hxx:671
static void highlight_and_update(ED4_sequence_terminal *term1, ED4_sequence_terminal *term2, ED4_index pos1, ED4_index pos2, int initial_call)
Definition: ED4_block.cxx:368
static PosRange whole()
Definition: pos_range.h:52
bool in_SAI_terminal() const
Definition: ed4_class.hxx:1854
bool is_empty() const
Definition: pos_range.h:72
FILE * seq
Definition: rns.c:46
#define e4_assert(bed)
Definition: ed4_class.hxx:14
virtual char * operate(const SeqPart &part, int &new_len) const =0
void world_to_win_coords(AW_pos *xPtr, AW_pos *yPtr) const
Definition: ed4_class.hxx:354
GBDATA * GBT_find_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:177
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
PosRange get_range_according_to_type()
Definition: ED4_block.cxx:52
size_t GB_read_string_count(GBDATA *gbd)
Definition: arbdb.cxx:916
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
double AW_pos
Definition: aw_base.hxx:29
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
TYPE * ARB_alloc(size_t nelem)
Definition: arb_mem.h:56
T * elem() const
Definition: ed4_list.hxx:25
#define is_equal_to_NULL()
Definition: test_unit.h:1028
void set_type(ED4_blocktype bt)
Definition: ED4_block.cxx:134
static PosRange empty()
Definition: pos_range.h:51
bool matchesUsingWildcard(GB_CSTR s1, GB_CSTR s2, int len)
Definition: ED4_block.cxx:618
static void col_block_refresh_on_seq_term(ED4_sequence_terminal *seq_term)
Definition: ED4_block.cxx:113
ED4_blocktype get_type() const
Definition: ED4_block.cxx:41
void jump_base_pos(int base_pos, ED4_CursorJumpType jump_type)
GBDATA * get_gb_main() const
Definition: ed4_class.hxx:1422
int sequence_to_screen(int sequence_pos) const
void ED4_toggle_block_type()
Definition: ED4_block.cxx:365
static void modsai_cb(AW_window *aww)
Definition: ED4_block.cxx:920
void remove_from_highlighted(ED4_species_name_terminal *object)
Definition: ED4_root.cxx:329
case_op(bool to_upper_)
Definition: ED4_block.cxx:739
#define false
Definition: ureadseq.h:13
ED4_returncode add_to_highlighted(ED4_species_name_terminal *object)
Definition: ED4_root.cxx:381
ED4_window * first_window
Definition: ed4_class.hxx:1428
ED4_terminal * get_next_terminal()
Definition: ED4_base.cxx:454
SeqPart(const char *seq_, int offset_, int len_)
Definition: ED4_block.cxx:87
static void error(const char *msg)
Definition: mkptypes.cxx:96
ED4_cursor cursor
Definition: ed4_class.hxx:722
expectation_group & add(const expectation &e)
Definition: test_unit.h:812
ASSERTING_CONSTEXPR_INLINE int info2bio(int infopos)
Definition: arb_defs.h:27
#define that(thing)
Definition: test_unit.h:1043
ED4_root_group_manager * root_group_man
Definition: ed4_class.hxx:1432
PosRange calc_interval_displayed_in_rectangle(AW_screen_area *area_rect)
Definition: ED4_base.cxx:545
char right_gap() const
Definition: ED4_block.cxx:103
#define AWAR_SAI_NAME
#define cmp(h1, h2)
Definition: admap.cxx:50
void calc_world_coords(AW_pos *x, AW_pos *y) const
Definition: ed4_class.hxx:983
replace_op(const char *oldString_, const char *newString_)
Definition: ED4_block.cxx:638
char * read_string() const
Definition: AW_awar.cxx:198
ED4_blocktype
Definition: ed4_block.hxx:15
GB_CSTR GB_path_in_ARBLIB(const char *relative_path)
Definition: adsocket.cxx:1156
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
static int pos2
Definition: ClustalV.cxx:59
void set_type(TYPE type)
Definition: probe_tree.h:59
GBDATA * GBT_find_sequence(GBDATA *gb_species, const char *aliname)
Definition: adali.cxx:708
ED4_list_elem * next() const
Definition: ed4_list.hxx:24
GB_alignment_type alignment_type
Definition: ed4_class.hxx:1440
void autocorrect_type()
Definition: ED4_block.cxx:167
#define is_equal_to(val)
Definition: test_unit.h:1025
char * operate(const SeqPart &part, int &new_len) const OVERRIDE
Definition: ED4_block.cxx:797
ED4_blocktype ED4_getBlocktype()
Definition: ED4_block.cxx:363
AW_selection_list * awt_create_selection_list_with_input_field(AW_window *aww, const char *awar_name, const char *at_box, const char *at_field)
GB_alignment_type
Definition: arbdb_base.h:61
void toggle_type()
Definition: ED4_block.cxx:144
#define does_contain(val)
Definition: test_unit.h:1040
bool is_consensus_terminal() const
Definition: ed4_class.hxx:1848
AW_event_type type
Definition: aw_window.hxx:81
ED4_cursor & current_cursor()
Definition: ed4_class.hxx:1400
GB_ERROR get_error() const
Definition: ed4_block.hxx:51
ED4_species_name_terminal * corresponding_species_name_terminal() const
Definition: ed4_class.hxx:1941
int MAXSEQUENCECHARACTERLENGTH
Definition: ED4_main.cxx:56
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:35
int length() const
Definition: ED4_block.cxx:94
static GB_ERROR perform_block_operation_on_part_of_sequence(const ED4_block_operator&block_operator, ED4_sequence_terminal *term)
Definition: ED4_block.cxx:247
void ED4_setColumnblockCorner(AW_event *event, ED4_sequence_terminal *seq_term)
Definition: ED4_block.cxx:474
#define to_upper(c)
Definition: ureadseq.h:23
#define OVERRIDE
Definition: cxxforward.h:112
const char * get_alignment_name() const
Definition: ed4_class.hxx:1458
char * GB_read_string(GBDATA *gbd)
Definition: arbdb.cxx:909
ED4_window * current_ed4w()
Definition: ed4_class.hxx:1398
AW_root * aw_root
Definition: ed4_class.hxx:1425
ED4_list_elem< T > * head() const
Definition: ed4_list.hxx:45
revcomp_op(GB_alignment_type aliType, bool reverse_, bool complement_)
Definition: ED4_block.cxx:765
#define abs(x)
Definition: f2c.h:151
bool ED4_is_gap_character(char chr)
void request_refresh(int clear=1) FINAL_OVERRIDE
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
ED4_index pixel2pos(AW_pos click_x)
Definition: ED4_root.cxx:1941
AW_root * get_root()
Definition: aw_window.hxx:359
void set_range(const PosRange &new_range)
Definition: ED4_block.cxx:50
ED4_species_manager * containing_species_manager() const
Definition: ed4_class.hxx:1830
bool ED4_get_highlighted_range(ED4_terminal *term, PosRange &range)
Definition: ED4_block.cxx:355
AW_window_simple * win
#define NULp
Definition: cxxforward.h:116
const ED4_remap * remap() const
Definition: ed4_class.hxx:1781
ED4_blockoperation_type
Definition: ed4_block.hxx:22
int end() const
Definition: pos_range.h:64
const PosRange & get_colblock_range() const
Definition: ED4_block.cxx:46
GB_ERROR write_string(const char *aw_string)
#define offset(field)
Definition: GLwDrawA.c:73
char * dup_corresponding_part(const char *source, size_t source_len) const
Definition: pos_range.cxx:27
int is_sequence_terminal() const
Definition: ed4_class.hxx:1083
void ED4_setup_gaps_and_alitype(const char *gap_chars, GB_alignment_type alitype)
Definition: ED4_main.cxx:253
static ED4_block block
Definition: ED4_block.cxx:74
NOT4PERL char * GB_command_interpreter_in_env(const char *str, const char *commands, const GBL_call_env &callEnv)
Definition: gb_aci.cxx:361
static void refresh_highlighted(bool refresh_name_terminals)
Definition: ED4_block.cxx:119
void ED4_correctBlocktypeAfterModification()
Definition: ED4_block.cxx:366
GB_ERROR load(const char *filemask, bool append) const
GB_transaction ta(gb_var)
GBDATA * gb_main
Definition: adname.cxx:32
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
#define ED4_AWAR_REP_SEARCH_PATTERN
Definition: ed4_awars.hxx:63
#define AWAR_MOD_SAI_SCRIPT
Definition: ED4_block.cxx:918
AW_window * ED4_create_replace_window(AW_root *root)
Definition: ED4_block.cxx:695
char * operate(const SeqPart &part, int &new_len) const OVERRIDE
Definition: ED4_block.cxx:884
long ED4_index
Definition: ed4_defs.hxx:113
void ED4_perform_block_operation(ED4_blockoperation_type operationType)
Definition: ED4_block.cxx:892
int is_species_name_terminal() const
Definition: ed4_class.hxx:1080
void aw_message_if(GB_ERROR error)
Definition: aw_msg.hxx:21
NOT4PERL GB_ERROR GBT_determine_T_or_U(GB_alignment_type alignment_type, char *T_or_U, const char *supposed_target)
Definition: adRevCompl.cxx:90
#define AWAR_RANGE
static void replace_in_block(AW_window *)
Definition: ED4_block.cxx:688
GB_ERROR GB_write_autoconv_string(GBDATA *gbd, const char *val)
Definition: arbdb.cxx:1479