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