1 #include "seaview.h"
2 #include <string.h>
3 #include <stdlib.h>
4
5 void draw_comment_lines(Fl_Widget *ob, SEA_VIEW *view);
6 int parse_comment_lines_from_header(char *header, char ***plines,
7 char ***pnames, int **plengths, int *pmax_seq_length);
8 int insert_char_in_comment(int key, int num, SEA_VIEW *view);
9 int insert_gap_all_comments(int numgaps, int pos, SEA_VIEW *view);
10 int delete_char_in_comment(SEA_VIEW *view, int count, int comnum, int depart,
11 int protect);
12 int delete_in_all_comments(int numdels, int pos, SEA_VIEW *view);
13 void update_menu_footers(SEA_VIEW *view);
14 void footers_menu_callback(Fl_Widget *ob, void* data);
15
16 /* used prototypes */
17 void set_and_show_new_cursor_site(SEA_VIEW *view, int new_pos, int center,
18 int force_redraw);
19 int compute_size_params(SEA_VIEW *view, int force_recompute);
20
21
draw_comment_lines(Fl_Widget * ob,SEA_VIEW * view)22 void draw_comment_lines(Fl_Widget *ob, SEA_VIEW *view)
23 {
24 int offset, x, y, l_line, nline;
25 int couleur, background;
26
27 if( !view->show_comment_lines ) return;
28 x = view->x_seq;
29 y = view->y_seq + (view->pos_first_comment_line - 1) * view->line_height;
30 /* write lines */
31 x = view->x_seq;
32 offset= view->first_site - 1;
33 for(nline = 0;
34 nline < view->tot_comment_lines ; nline++, y += view->line_height ) {
35 if(view->mod_comment_line == 0 || view->mod_comment_line == nline+1 ) {
36 if(view->active_comment_line == nline + 1) {
37 couleur = FL_WHITE;
38 background = FL_BLACK;
39 }
40 else {
41 couleur = FL_BLACK;
42 background = ob->selection_color();
43 }
44 fl_font(FL_COURIER_ITALIC, ob->labelsize() );
45 fl_color(background);
46 fl_rectf( view->x_name,
47 y - view->line_height + fl_descent(),
48 (view->wid_names+1) * view->char_width,
49 view->line_height);
50 fl_color(couleur);
51 fl_draw(view->comment_name[nline],
52 FL_min((unsigned)view->wid_names,
53 strlen(view->comment_name[nline]) ),
54 view->x_name, y);
55 l_line = (
56 offset + view->tot_sites < view->comment_length[nline] ?
57 view->tot_sites : view->comment_length[nline] - offset);
58 if(l_line <= 0) continue;
59 fl_font(ob->labelfont(), ob->labelsize() );
60 fl_color(ob->color());
61 fl_rectf(x, y - view->line_height + fl_descent(),
62 (view->tot_sites + 1) * view->char_width,
63 view->line_height);
64 fl_color(FL_BLACK);
65 fl_draw(view->comment_line[nline] + offset, l_line, x, y);
66 }
67 }
68 }
69
70
parse_comment_lines_from_header(char * header,char *** plines,char *** pnames,int ** plengths,int * pmax_seq_length)71 int parse_comment_lines_from_header(char *header, char ***plines,
72 char ***pnames, int **plengths, int *pmax_seq_length)
73 {
74 char *new_header, *fin_new_header, *old_header, *j, *p, *q;
75 int l_header, num, total, max_seq_length;
76 char **lines, **names;
77 int *lengths;
78
79 if(header == NULL) return 0;
80 old_header = header;
81 l_header = strlen(header);
82 total = 0;
83 while (*header!= 0) {
84 if(strncmp(header,";;|",3) == 0) {
85 total++;
86 do header = strchr(header,'\n') + 1;
87 while(strncmp(header, ";;||", 4) != 0);
88 }
89 header = strchr(header,'\n') + 1;
90 }
91 if(total == 0) return 0;
92 names = (char **)malloc(total * sizeof(char *));
93 lines = (char **)malloc(total * sizeof(char *));
94 lengths = (int *)malloc(total * sizeof(int));
95 if( names == NULL || lines == NULL || lengths == NULL) out_of_memory();
96 header = old_header;
97 if( (new_header = (char *)malloc(l_header+1)) == NULL) out_of_memory();
98 fin_new_header = new_header;
99 *new_header = 0;
100 num = -1;
101 max_seq_length = *pmax_seq_length;
102 while (*header!= 0) {
103 if(strncmp(header,";;|",3) == 0) {
104 num++;
105 p = header + 3; while(*p == ' ') p++;
106 q = strchr(p, '\n');
107 names[num] = (char *)malloc(q - p + 1);
108 if( names[num] == NULL ) out_of_memory();
109 memcpy( names[num], p, q - p );
110 names[num][q - p] = 0;
111 header = q + 1;
112 p = header;
113 do p = strchr(p,'\n') + 1;
114 while(strncmp(p, ";;||", 4) != 0);
115 if(p - header > max_seq_length) max_seq_length = p - header;
116 lines[num] = (char *)malloc(p - header + 1);
117 if( lines[num] == NULL ) out_of_memory();
118 q = lines[num];
119 do {
120 p = strchr(header,'\n') + 1;
121 memcpy(q, header + 2, p - header - 3);
122 q += p - header - 3;
123 header = p;
124 }
125 while(strncmp(p, ";;||", 4) != 0);
126 *q = 0;
127 lengths[num] = strlen(lines[num]);
128 }
129 else {
130 j=(char *)memccpy(fin_new_header, header, '\n', l_header);
131 fin_new_header += (j - fin_new_header);
132 }
133 header = strchr(header,'\n') + 1;
134 }
135 *fin_new_header = 0;
136 strcpy(old_header, new_header);
137 free(new_header);
138 *pnames = names; *plines = lines; *plengths = lengths;
139 *pmax_seq_length = max_seq_length;
140 return num + 1;
141 }
142
143
insert_char_in_comment(int key,int num,SEA_VIEW * view)144 int insert_char_in_comment(int key, int num, SEA_VIEW *view)
145 {
146 char *pos;
147 int l;
148
149 if(num + view->comment_length[view->active_comment_line - 1] >
150 view->max_seq_length)
151 num = view->max_seq_length -
152 view->comment_length[view->active_comment_line - 1];
153 pos = view->comment_line[view->active_comment_line - 1] + view->cursor_site - 1;
154 l = view->comment_length[view->active_comment_line - 1] - view->cursor_site + 1;
155 memmove(pos + num, pos, l + 1);
156 memset(pos, key, num);
157 view->mod_comment_line = view->cursor_seq;
158 view->comment_length[view->active_comment_line - 1] += num;
159 set_and_show_new_cursor_site(view, view->cursor_site + num, FALSE, TRUE);
160 set_seaview_modified(view, TRUE);
161 return num;
162 }
163
164
insert_gap_all_comments(int numgaps,int pos,SEA_VIEW * view)165 int insert_gap_all_comments(int numgaps, int pos, SEA_VIEW *view)
166 {
167 int num, l, total = 0;
168 char *debut;
169 for(num = 0; num < view->tot_comment_lines; num++) {
170 if(pos > view->comment_length[num] + 1) continue; /* beyond end */
171 total = numgaps;
172 if(total + view->comment_length[num] > view->max_seq_length) {
173 total = view->max_seq_length - view->comment_length[num];
174 fl_beep(FL_BEEP_DEFAULT);
175 }
176 debut = view->comment_line[num] + pos - 1;
177 l = view->comment_length[num] - pos + 1;
178 memmove(debut + total, debut, l + 1);
179 memset(debut, '-', total);
180 view->comment_length[num] += total;
181 }
182 return total;
183 }
184
185
delete_char_in_comment(SEA_VIEW * view,int count,int comnum,int depart,int protect)186 int delete_char_in_comment(SEA_VIEW *view, int count, int comnum, int depart,
187 int protect)
188 {
189 char *pos;
190 int l, total;
191
192 if(count >= depart) count = depart - 1;
193 pos = view->comment_line[comnum - 1] + depart - 1;
194 l = view->comment_length[comnum - 1] - depart + 1;
195 if(protect) {
196 for(total = 1; total <= count ; total++)
197 if( *(pos - total) != '-' ) break;
198 count = total - 1;
199 if(count == 0) return 0;
200 }
201 memmove(pos - count, pos, l + 1);
202 view->mod_comment_line = comnum;
203 view->comment_length[comnum - 1] -= count;
204 set_and_show_new_cursor_site(view, depart - count, FALSE, TRUE);
205 set_seaview_modified(view, TRUE);
206 return count;
207 }
208
209
delete_in_all_comments(int numdels,int pos,SEA_VIEW * view)210 int delete_in_all_comments(int numdels, int pos, SEA_VIEW *view)
211 {
212 int num, l;
213 char *debut;
214 numdels = FL_min(numdels, pos);
215 for(num = 0; num < view->tot_comment_lines; num++) {
216 if(pos > view->comment_length[num] + 1) continue; /* beyond end */
217 debut = view->comment_line[num] + pos - 1;
218 l = view->comment_length[num] - pos + 1;
219 memmove(debut - numdels, debut, l + 1);
220 view->comment_length[num] -= numdels;
221 }
222 return numdels;
223 }
224
225
update_menu_footers(SEA_VIEW * view)226 void update_menu_footers(SEA_VIEW *view)
227 {
228 Fl_Menu_Item *items = (Fl_Menu_Item *)view->menu_footers;
229 if(view->tot_comment_lines > 0)
230 items[SHOW_HIDE_FOOTERS].activate();
231 else
232 items[SHOW_HIDE_FOOTERS].deactivate();
233 items[SHOW_HIDE_FOOTERS].label( view->show_comment_lines ? "Hide footers" : "Show footers" );
234 if(view->show_comment_lines && view->active_comment_line > 0)
235 items[DELETE_FOOTER].activate();
236 else
237 items[DELETE_FOOTER].deactivate();
238 if(view->tot_seqs > 0 )
239 items[CREATE_FOOTER].activate();
240 else
241 items[CREATE_FOOTER].deactivate();
242 }
243
244
footers_menu_callback(Fl_Widget * ob,void * data)245 void footers_menu_callback(Fl_Widget *ob, void* data)
246 {
247 SEA_VIEW *view = (SEA_VIEW *) ob->user_data();
248 int num, reponse = view->menubar->mvalue() - view->menu_footers;
249 if(reponse == SHOW_HIDE_FOOTERS && view->tot_comment_lines > 0) {
250 view->show_comment_lines = !view->show_comment_lines;
251 view->active_comment_line = 0;
252 view->cursor_in_comment = FALSE;
253 compute_size_params(view, TRUE);
254 view->DNA_obj->redraw();
255 }
256 else if(reponse == CREATE_FOOTER) {
257 char **pline, **pname, *texte, *name;
258 const char *c_name;
259 int *plength;
260 c_name = fl_input("Name of new footer line?", "Comments" );
261 if(c_name == NULL || strlen(c_name) == 0) return;
262 num = view->tot_comment_lines;
263 pline = (char **)malloc((view->tot_comment_lines + 1) *sizeof(char *));
264 if(pline == NULL) return;
265 pname = (char **)malloc((view->tot_comment_lines + 1) *sizeof(char *));
266 if(pname == NULL) return;
267 plength = (int *)malloc((view->tot_comment_lines + 1) *sizeof(int ));
268 if(plength == NULL) return;
269 texte = (char *)malloc((view->max_seq_length + 1) *sizeof(char));
270 if(texte == NULL) return;
271 name = (char *)malloc(strlen(c_name) + 1);
272 if(name == NULL) return;
273 memset(texte, '-', view->seq_length);
274 texte[view->seq_length] = 0;
275 strcpy(name, c_name);
276 if(view->tot_comment_lines > 0) {
277 memcpy(pline, view->comment_line,
278 view->tot_comment_lines * sizeof(char *));
279 free(view->comment_line);
280 }
281 pline[view->tot_comment_lines] = texte;
282 view->comment_line = pline;
283 if(view->tot_comment_lines > 0) {
284 memcpy(pname, view->comment_name,
285 view->tot_comment_lines * sizeof(char *));
286 free(view->comment_name);
287 }
288 pname[view->tot_comment_lines] = name;
289 view->comment_name = pname;
290 if(view->tot_comment_lines > 0) {
291 memcpy(plength, view->comment_length,
292 view->tot_comment_lines * sizeof(int));
293 free(view->comment_length);
294 }
295 plength[view->tot_comment_lines] = view->seq_length;
296 view->comment_length = plength;
297 ++(view->tot_comment_lines);
298 view->show_comment_lines = TRUE;
299 view->active_comment_line = 0;
300 view->cursor_in_comment = FALSE;
301 set_seaview_modified(view, TRUE);
302 compute_size_params(view, TRUE);
303 view->DNA_obj->redraw();
304 }
305 else if(reponse == DELETE_FOOTER) {
306 if(view->tot_comment_lines == 0 || view->active_comment_line == 0)
307 return;
308 if(! fl_choice("Confirm deletion?", "Cancel", "Delete", NULL) ) return;
309 free(view->comment_line[view->active_comment_line - 1]);
310 free(view->comment_name[view->active_comment_line - 1]);
311 for(num = view->active_comment_line; num < view->tot_comment_lines;
312 num++) {
313 view->comment_line[num - 1] = view->comment_line[num];
314 view->comment_name[num - 1] = view->comment_name[num];
315 view->comment_length[num - 1] = view->comment_length[num];
316 }
317 (view->tot_comment_lines)--;
318 if(view->tot_comment_lines == 0) view->show_comment_lines = FALSE;
319 view->active_comment_line = 0;
320 view->cursor_in_comment = FALSE;
321 set_seaview_modified(view, TRUE);
322 compute_size_params(view, TRUE);
323 view->DNA_obj->redraw();
324 }
325 update_menu_footers(view);
326 }
327