1 
2 
3 #include <vibrant.h>
4 #include <drawseq.h>
5 #include <edutil.h>
6 
7 Uint1 custom_color[3];
8 
9 #define SCALE_SPACE 20
10 static Boolean  AddFlatNodeSymbol PROTO((SegmenT pseg, ValNodePtr fnp_node, Int4 scale));
11 
12 /*######################################################################
13 #
14 #	functions for setting up the color for different object
15 #
16 ######################################################################*/
17 
18 
19 #define RGB_B(x) (Uint1)((x)&255);
20 #define RGB_G(x) (Uint1)(((x)>>8)&255);
21 #define RGB_R(x) (Uint1)(((x)>>16)&255);
convert_color(Int4 val,Uint1Ptr color)22 static Boolean convert_color(Int4 val, Uint1Ptr color)
23 {
24 
25 	if(val<0 || color == NULL)
26 		return FALSE;
27 	color[0] = RGB_R(val);
28 	color[1] = RGB_G(val);
29 	color[2] = RGB_B(val);
30 	return TRUE;
31 }
32 
33 
34 Uint1 MUSK_COLOR[3];
35 /************************************************************************
36 *
37 *	get_seg_color(order)
38 *	set up the color for a segmented sequence
39 *
40 *************************************************************************/
get_seg_color(Int2 order)41 Uint1Ptr get_seg_color(Int2 order)
42 {
43 	Int2 c_num;
44 	Int4 color_val;
45 
46 	c_num = (Int2)GetMuskCParam(MSM_CCOLOR, MSM_NOSUBCLASS, MSM_NUM);
47 	if(c_num != 0)
48 	{
49 		order = (Int2)(order)%c_num +1;
50 		color_val = GetMuskCParam(MSM_CCOLOR, order, MSM_COLOR);
51 		if(convert_color(color_val, MUSK_COLOR))
52 			return MUSK_COLOR;
53 	}
54 	return NULL;
55 
56 }
57 
58 
59 /**********************************************************************
60 *
61 *	get the color for different enzymes
62 *	used in drawing the restriction map
63 *
64 **********************************************************************/
get_enz_color(Int2 enzID)65 Uint1Ptr get_enz_color(Int2 enzID)
66 {
67 	return get_seg_color(enzID);
68 }
69 
70 
71 /**********************************************************************
72 *
73 *
74 *
75 ***********************************************************************/
DrawSquiggle(SegmenT seg,Int4 x,Int4 y,Int2 primID,Boolean is_left)76 static void DrawSquiggle(SegmenT seg, Int4 x, Int4 y, Int2 primID, Boolean is_left)
77 {
78 	Int4 space;
79 
80 	space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
81 	AddLine(seg, x, y, x, y-space, FALSE, 0);
82 	if(is_left)
83 		AddSymbol(seg, x+2, y - space, LEFT_TRIANGLE_SYMBOL, TRUE, LOWER_LEFT, primID);
84 	else
85 		AddSymbol(seg, x, y - space, RIGHT_TRIANGLE_SYMBOL, TRUE, LOWER_RIGHT, primID);
86 
87 }
88 
89 
get_arrow_for_strand(Uint1 strand)90 static Int2 get_arrow_for_strand(Uint1 strand)
91 {
92 	switch(strand)
93 	{
94 		case Seq_strand_minus:
95 			return LEFT_ARROW;
96 		case Seq_strand_plus:
97 			return RIGHT_ARROW;
98 		default:
99 			return NO_ARROW;
100 	}
101 }
102 
add_attribute_pen(SegmenT seg,Int2 p_class,Int2 sub_class)103 void add_attribute_pen(SegmenT seg, Int2 p_class, Int2 sub_class)
104 {
105 	Uint1 color[3];
106 	Uint1 flags = COLOR_ATT|STYLE_ATT|SHADING_ATT|WIDTH_ATT;
107 	Int4  c_val;
108 	Uint1 linestyle;
109 	Uint1 penwidth;
110 	Uint1 shading;
111 
112 	c_val = GetMuskCParam(p_class, sub_class, MSM_COLOR);
113 	convert_color(c_val, color);
114 
115 	linestyle = (Uint1)GetMuskCParam(p_class, sub_class, MSM_LTYPE);
116 	penwidth = (Uint1)GetMuskCParam(p_class, sub_class, MSM_PENWIDTH);
117 	shading = (Uint1)GetMuskCParam(p_class, sub_class, MSM_SHADING);
118 
119 	AddAttribute(seg, flags, &color[0], linestyle, shading, penwidth, COPY_MODE);
120 
121 }
122 
123 /*************************************************************************
124 *
125 *	DrawFeatNode(vnp, type, rec_width, scale, seg, label_type, fill)
126 *	Draw a list of featnode, return TRUE for success
127 *	vnp: a list of featnode
128 *	rec_width: width for drawing a rectangle. if <2, draw a line
129 *	scale: max scale
130 * 	seg: drawing segment
131 *	label_type: Add label on the segment
132 *	fill: fill the rectangle?
133 *
134 *************************************************************************/
135 
AddLabelWithAlign(SegmenT seg,Uint1 label_align,Int4 left,Int4 right,Int4 top,Int4 bottom,CharPtr label,FonT font,Uint4 itemID)136 static void AddLabelWithAlign(SegmenT seg, Uint1 label_align, Int4 left, Int4 right, Int4 top, Int4 bottom, CharPtr label, FonT font, Uint4 itemID)
137 {
138 	Int4 center, middle;
139 
140 
141 	switch(label_align)
142 	{
143 		case MSM_LABEL_TOP:
144 			center = (left + right)/2;
145 			AddTextLabel(seg, center, top, label, font, 0, UPPER_CENTER, itemID);
146 			break;
147 		case MSM_LABEL_BOTTOM:
148 			center = (left + right)/2;
149 			AddTextLabel(seg, center, bottom, label, font, 0, LOWER_CENTER, itemID);
150 			break;
151 		case MSM_LABEL_LEFT:
152 			middle = (top + bottom)/2;
153 			AddTextLabel(seg, left, middle, label, font, 0, MIDDLE_LEFT, itemID);
154 			break;
155 		case MSM_LABEL_RIGHT:
156 			middle = (top + bottom)/2;
157 			AddTextLabel(seg, right, middle, label, font, 0, MIDDLE_RIGHT, itemID);
158 			break;
159 		default:
160 			break;
161 	}
162 }
163 
load_gene_data(GeneDataPtr gdp,FeatNodePtr fnp,Uint2 itemType,Int4 x,Int4 y)164 static Boolean load_gene_data(GeneDataPtr gdp, FeatNodePtr fnp, Uint2 itemType, Int4 x, Int4 y)
165 {
166 	while(gdp)
167 	{
168 		if(gdp->entityID == fnp->entityID)
169 		{
170 			if(gdp->itemID == fnp->itemID)
171 			{
172 				if(gdp->itemType == itemType)
173 				{
174 					gdp->x = x;
175 					gdp->y = y;
176 					return TRUE;
177 				}
178 			}
179 		}
180 		gdp = gdp->next;
181 	}
182 	return FALSE;
183 }
184 
AddBoxWithAlign(SegmenT seg,Uint1 label_align,FeatNodePtr fnp,Int4 scale,GeneDataPtr gdp,Uint2 itemType)185 static Boolean AddBoxWithAlign(SegmenT seg, Uint1 label_align, FeatNodePtr fnp, Int4 scale, GeneDataPtr gdp, Uint2 itemType)
186 {
187 	Int4 center, middle;
188 	Int4 width;
189 	Int4 left, right, top, bottom;
190 	CharPtr label;
191 	Int4 labelHeight;
192 	Uint4 itemID;
193 	Char buf[10];
194 
195 	if(fnp == NULL || fnp->label == NULL)
196 		return FALSE;
197 	left = fnp->extremes.left;
198 	right = fnp->extremes.right;
199 	top = fnp->top;
200 	bottom = fnp->bottom;
201 	labelHeight = fnp->labelHeight;
202 	itemID = fnp->itemID;
203 	label = fnp->label;
204 	if(labelHeight == 0)	/*the label will NOT be displayed*/
205 	{
206 		StringCpy(buf, "XXXX");
207 		label = buf;
208 		/* font = (FonT)GetMuskCParam(fnp->feattype, MSM_FLABEL, MSM_FONT);
209 		SelectFont(font); */
210 		labelHeight = FontHeight();
211 		label_align = MSM_LABEL_TOP;
212 		top -= labelHeight;
213 
214 	}
215 
216 	width = scale * StringWidth(label);
217 	AddAttribute (seg, COLOR_ATT, YELLOW_COLOR, 0, 0, 0, 0);
218 	switch(label_align)
219 	{
220 		case MSM_LABEL_TOP:
221 			center = (left + right)/2;
222 			left = center - width/2;
223 			right = center + width/2;
224 			bottom = top;
225 			top += labelHeight;
226 			break;
227 		case MSM_LABEL_BOTTOM:
228 			center = (left + right)/2;
229 			left = center - width/2;
230 			right = center + width/2;
231 			top = bottom;
232 			bottom -= labelHeight;
233 			break;
234 		case MSM_LABEL_LEFT:
235 			middle = (top + bottom)/2;
236 			top = middle - labelHeight/2;
237 			bottom = middle + labelHeight/2;
238 			right = left;
239 			left = left - width;
240 
241 			break;
242 		case MSM_LABEL_RIGHT:
243 			middle = (top + bottom)/2;
244 			top = middle - labelHeight/2;
245 			bottom = middle + labelHeight/2;
246 			left  = right;
247 			right += width;
248 			break;
249 		default:
250 			return FALSE;
251 	}
252 	AddRectangle (seg, left, top+5, right, bottom+5, FALSE, TRUE, itemID);
253 	load_gene_data(gdp, fnp, itemType, left, top);
254 
255 	/*show the partial label*/
256 	if(fnp->labelHeight == 0 && fnp->label != NULL)
257 	{
258 		center = (fnp->extremes.left + fnp->extremes.right)/2;
259 		middle = (fnp->top + fnp->bottom)/2;
260 		AddAttribute (seg, COLOR_ATT, RED_COLOR, 0, 0, 0, 0);
261 		AddSymbol(seg, center, middle, DIAMOND_SYMBOL, TRUE, MIDDLE_CENTER, fnp->itemID);
262 	}
263 	return TRUE;
264 }
265 
266 
267 
AddFeatNodeLabel(SegmenT seg,FeatNodePtr fnp,Uint1 label_align,FonT font)268 static void AddFeatNodeLabel(SegmenT seg, FeatNodePtr fnp, Uint1 label_align, FonT font)
269 {
270 	if(fnp->labelHeight > 0)
271 		AddLabelWithAlign(seg, label_align, fnp->extremes.left, fnp->extremes.right, fnp->top, fnp->bottom, fnp->label, font, fnp->itemID);
272 }
273 
AddFeatNodeTickMark(SegmenT seg,FeatNodePtr fnp,Uint1 label_align)274 static void AddFeatNodeTickMark(SegmenT seg, FeatNodePtr fnp, Uint1 label_align)
275 {
276 	Int4 center, middle;
277 	Int4 y_pos, x_pos;
278 	Int4 tick_len;
279 
280 
281 	tick_len = TICK_LEN;
282 	switch(label_align)
283 	{
284 		case MSM_LABEL_TOP:
285 			center = (fnp->extremes.left + fnp->extremes.right)/2;
286 			y_pos = fnp->bottom;
287 			AddLine(seg, center, y_pos, center, y_pos-tick_len, FALSE, fnp->itemID);
288 			break;
289 		case MSM_LABEL_BOTTOM:
290 			center = (fnp->extremes.left + fnp->extremes.right)/2;
291 			y_pos = fnp->top;
292 			AddLine(seg, center, y_pos, center, y_pos+tick_len, FALSE, fnp->itemID);
293 			break;
294 		case MSM_LABEL_LEFT:
295 			middle = (fnp->top + fnp->bottom)/2;
296 			x_pos = fnp->extremes.left;
297 			AddLine(seg, x_pos, middle, x_pos-tick_len, middle, FALSE, fnp->itemID);
298 			break;
299 		case MSM_LABEL_RIGHT:
300 			middle = (fnp->top + fnp->bottom)/2;
301 			x_pos = fnp->extremes.right;
302 			AddLine(seg, x_pos, middle, x_pos+tick_len, middle, FALSE, fnp->itemID);
303 			break;
304 		default:
305 			break;
306 	}
307 }
308 
309 
310 /*gdata is added to record the possible selected marker*/
AddFeatNodeListLabel(SegmenT p_seg,ValNodePtr fnp_node,Uint1 label_align,Int4 scale,GeneDataPtr gdata)311 static Boolean  AddFeatNodeListLabel(SegmenT p_seg, ValNodePtr fnp_node, Uint1 label_align, Int4 scale, GeneDataPtr gdata)
312 {
313 	FeatNodePtr fnp;
314 	Boolean has_prev = FALSE;
315 	Int2 ptype = 0, _class;
316 	FonT font = NULL;
317 	Int4 color_val;
318 	Uint1 color[3];
319 
320 	SegmenT seg = NULL;
321 	Uint2 p_entityID = 0;
322 
323 /*	if(label_align > MSM_LABEL_RIGHT || label_align < MSM_LABEL_TOP)*/
324 	if(label_align > 3 /* || label_align < 0 */)
325 		return FALSE;
326 	while(fnp_node)
327 	{
328 		fnp = fnp_node->data.ptrvalue;
329 		if(!has_prev || fnp->entityID != p_entityID)
330 		{
331 			seg = CreateSegment(p_seg, fnp->entityID, 0);
332 			p_entityID = fnp->entityID;
333 			has_prev = FALSE;
334 		}
335 		if(fnp && fnp->label)
336 		{
337 			_class = get_current_class(fnp);
338 
339 			if(!has_prev || ptype != _class)
340 			{
341 				/*if(has_prev)
342 					DeleteFont(font);*/
343 				font = (FonT)GetMuskCParam(_class, MSM_FLABEL, MSM_FONT);
344 				SelectFont(font);
345 				color_val = GetMuskCParam(_class, MSM_FLABEL, MSM_COLOR);
346 				convert_color(color_val, color);
347 				AddAttribute(seg, COLOR_ATT, &(color[0]), 0, 0, 0, 0);
348 
349 				has_prev = TRUE;
350 				ptype = _class;
351 			}
352 			if(fnp->landmark)
353 			{
354 				AddBoxWithAlign(seg, label_align, fnp, scale, gdata, (Uint2)(fnp_node->choice));
355 				AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, 0);
356 			}
357 			AddFeatNodeLabel(seg, fnp, label_align, font);
358 		}
359 		if(fnp->draw_tick)
360 			AddFeatNodeTickMark(seg, fnp, label_align);
361 
362 		fnp_node = fnp_node->next;
363 	}
364 
365 	/*if(has_prev)
366 		DeleteFont(font);*/
367 	return TRUE;
368 }
369 
DrawGapInterval(SegmenT seg,Int4 left,Int4 right,Int4 top,Int4 bottom,Int4 gap_style,Uint4 itemID)370 static void DrawGapInterval(SegmenT seg, Int4 left, Int4 right, Int4 top, Int4 bottom, Int4 gap_style, Uint4 itemID)
371 {
372 	Int4 center, middle;
373 
374 	switch(gap_style)
375 	{
376 		case MSM_GAP_LINE:
377 			middle = (top + bottom)/2;
378 			AddLine(seg, left, middle, right, middle, FALSE, itemID);
379 			break;
380 		case MSM_GAP_ANGLE:
381 			center = (left + right)/2;
382 			middle = (top + bottom)/2;
383 			AddLine(seg, left, middle, center, top, FALSE, itemID);
384 			AddLine(seg, center, top, right, middle, FALSE, itemID);
385 			break;
386 		default:
387 			break;
388 	}
389 }
390 
391 
AddGapForOneFeatNode(FeatNodePtr fnp,Int4Ptr pstyle,Int2Ptr p_class,BoolPtr has_prev,SegmenT seg)392 static void AddGapForOneFeatNode(FeatNodePtr fnp, Int4Ptr pstyle, Int2Ptr p_class, BoolPtr has_prev, SegmenT seg)
393 {
394 	Int4 prev_pos, i_left, i_right;
395 	Int4 start, stop;
396 	Int4 style, segstyle;
397 	ValNodePtr ivals;
398 	IvalNodePtr inp = NULL;
399 	Int4 top, bottom;
400 	Int2 _class;
401 	Boolean show_gap;
402 
403 	ivals = fnp->interval;
404 
405 	_class = get_current_class(fnp);
406 	if(!(*has_prev) || (*p_class) != _class)
407 	{
408 		style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
409 		segstyle = (style & MSM_SEG_FORM);
410 		show_gap = ((segstyle == MSM_SEG_BOX) || (segstyle == MSM_SEG_LINE));
411 		if(!show_gap)
412 			return;
413 
414 		add_attribute_pen(seg, _class, MSM_FGAP);
415 		style = GetMuskCParam(_class, MSM_FGAP, MSM_STYLE);
416 		*has_prev = TRUE;
417 		*p_class = _class;
418 		*pstyle = segstyle;
419 	}
420 	else
421 	{
422 		segstyle = *pstyle;
423 		show_gap =(segstyle == MSM_SEG_BOX || segstyle == MSM_SEG_LINE);
424 		if(!show_gap)
425 			return;
426 		else
427 			style = GetMuskCParam(_class, MSM_FGAP, MSM_STYLE);
428 
429 	}
430 
431 
432 	top = fnp->top;
433 	bottom = fnp->bottom;
434 	if(ivals == NULL)
435 	{
436 		start = fnp->extremes.left;
437 		stop = fnp->extremes.right;
438 		DrawGapInterval(seg, start, stop, top, bottom, style, fnp->itemID);
439 		return;
440 	}
441 
442 	if(fnp->extremes.strand == Seq_strand_minus)
443 		prev_pos = fnp->extremes.right;
444 	else
445 		prev_pos = fnp->extremes.left;
446 	while(ivals)
447 	{
448 		inp = ivals->data.ptrvalue;
449 		i_left = inp->gr.left;
450 		i_right = inp->gr.right;
451 		if(inp->gr.strand == Seq_strand_minus)
452 		{
453 			stop = prev_pos;
454 			start = i_right;
455 			prev_pos = i_left;
456 		}
457 		else
458 		{
459 			start = prev_pos;
460 			stop = i_left;
461 			prev_pos  = i_right;
462 		}
463 		if(stop > start)
464 			DrawGapInterval(seg, start, stop, top, bottom, style, fnp->itemID);
465 		ivals = ivals->next;
466 	}
467 
468 	/*check the last piece*/
469 	if(inp !=NULL)
470 	{
471 		if(inp->gr.strand == Seq_strand_minus)
472 		{
473 			stop = prev_pos;
474 			start = fnp->extremes.left;
475 		}
476 		else
477 		{
478 			start = prev_pos;
479 			stop = fnp->extremes.right;
480 		}
481 		if(stop > start)
482 			DrawGapInterval(seg, start, stop, top, bottom, style, fnp->itemID);
483 	}
484 }
485 
486 
AddFeatNodeListGaps(SegmenT p_seg,ValNodePtr fnp_node)487 static void AddFeatNodeListGaps(SegmenT p_seg, ValNodePtr fnp_node)
488 {
489 	FeatNodePtr fnp;
490 	Boolean has_prev = FALSE;
491 	Int2 pclass = -1;
492 	Int4 style = 0;
493 	SegmenT seg = NULL;
494 	Uint2 p_entityID = 0;
495 
496 	while(fnp_node)
497 	{
498 		fnp = fnp_node->data.ptrvalue;
499 		if(!has_prev || fnp->entityID != p_entityID)
500 		{
501 			seg = CreateSegment(p_seg, fnp->entityID, 0);
502 			p_entityID = fnp->entityID;
503 			has_prev = FALSE;	/*Reset has_prev to reset the style of the current seg*/
504 		}
505 		AddGapForOneFeatNode(fnp, &style, &pclass, &has_prev, seg);
506 		fnp_node = fnp_node->next;
507 	}
508 }
509 
DrawFeatNodeSegment(FeatNodePtr fnp,Int4 segstyle,Int2 subclass,SegmenT seg,Boolean show_arrow,Boolean show_interval)510 static Boolean DrawFeatNodeSegment(FeatNodePtr fnp, Int4 segstyle, Int2 subclass, SegmenT seg, Boolean show_arrow, Boolean show_interval)
511 {
512 	Int4 e_left, e_right, end_pos;
513 	Int4 i_left, i_right;
514 	Int4 top, bottom;
515 	Uint1 strand;
516 	Boolean fill;
517 	Int2 arrow = NO_ARROW;
518 	ValNodePtr ivals;
519 	IvalNodePtr inp;
520 
521 	if(fnp == NULL)
522 		return FALSE;
523 	if(subclass != MSM_SEGMENT && subclass != MSM_SEG_BORD)
524 		return FALSE;
525 	if(segstyle != MSM_SEG_LINE && segstyle != MSM_SEG_BOX)
526 		return FALSE;
527 	if(segstyle == MSM_SEG_LINE && subclass == MSM_SEG_BORD)
528 		return FALSE;
529 	fill = (subclass == MSM_SEGMENT);
530 
531 	e_left = fnp->extremes.left;
532 	e_right = fnp->extremes.right;
533 	top = fnp->top;
534 	bottom = fnp->bottom;
535 	strand = fnp->extremes.strand;
536 	if(fnp->interval == NULL)
537 	{
538 		if(show_interval)
539 			return TRUE;
540 		if(show_arrow)
541 			arrow = get_arrow_for_strand(strand);
542 		if(segstyle == MSM_SEG_BOX)
543 			AddRectangle(seg, e_left, top, e_right, bottom, arrow, fill, fnp->itemID);
544 		else
545 			AddLine(seg, e_left, bottom, e_right, bottom, FALSE, fnp->itemID);
546 	}
547 	if(strand == Seq_strand_minus)
548 		end_pos = e_left;
549 	else
550 		end_pos = e_right;
551 
552 	for(ivals = fnp->interval; ivals !=NULL; ivals = ivals->next)
553 	{
554 		arrow = NO_ARROW;
555 		inp = ivals->data.ptrvalue;
556 		i_left = inp->gr.left;
557 		i_right = inp->gr.right;
558 		if(show_arrow)
559 		{
560 			if(strand == Seq_strand_minus && i_left == end_pos)
561 				arrow = LEFT_ARROW;
562 			if(strand == Seq_strand_plus && i_right == end_pos)
563 				arrow = RIGHT_ARROW;
564 		}
565 		if(segstyle == MSM_SEG_BOX)
566 			AddRectangle (seg, i_left, top, i_right, bottom, arrow, fill, fnp->itemID);
567 		else
568 			AddLine(seg, i_left, bottom, i_right, bottom, FALSE, fnp->itemID);
569 	}
570 	return TRUE;
571 }
572 
573 
AddFeatNodeListBorder(SegmenT p_seg,ValNodePtr fnp_node,Boolean show_arrow,Boolean show_interval)574 static void AddFeatNodeListBorder(SegmenT p_seg, ValNodePtr fnp_node, Boolean show_arrow, Boolean show_interval)
575 {
576 	FeatNodePtr fnp;
577 	Boolean has_prev = FALSE;
578 	Int2 ptype = 0, _class;
579 	Boolean show_border = FALSE;
580 	Int4 style, segstyle = 0;
581 	Boolean arrow = FALSE;
582 	SegmenT seg = NULL;
583 	Uint2 p_entityID = 0;
584 
585 
586 
587 	while(fnp_node)
588 	{
589 		fnp = fnp_node->data.ptrvalue;
590 		_class = get_current_class(fnp);
591 		if(!has_prev || fnp->entityID != p_entityID)
592 		{
593 			seg = CreateSegment(p_seg, fnp->entityID, 0);
594 			p_entityID = fnp->entityID;
595 			has_prev = FALSE;	/*force reset of the current style*/
596 		}
597 		if(!has_prev || ptype != _class)
598 		{
599 			/*the border is drawn only when the segment is drawn as a box */
600 			style = GetMuskCParam(_class, MSM_SEG_BORD, MSM_TRUEFALSE);
601 			if(style != 0)
602 			{
603 				style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
604 				segstyle = (style & MSM_SEG_FORM);
605 				show_border = (segstyle == MSM_SEG_BOX);
606 				if(show_border)
607 				{
608 					add_attribute_pen(seg, _class, MSM_SEG_BORD);
609 					if(show_arrow)
610 						arrow = (Boolean)(style & (Int4)MSM_SEG_SHOWORIENT);
611 					else
612 						arrow = FALSE;
613 				}
614 			}
615 			else
616 				show_border = FALSE;
617 			has_prev = TRUE;
618 			ptype = _class;
619 		}
620 		if(show_border)
621 			DrawFeatNodeSegment(fnp, segstyle, MSM_SEG_BORD, seg, arrow, show_interval);
622 		fnp_node = fnp_node->next;
623 	}
624 }
625 
AddFeatNodeListSegments(SegmenT p_seg,ValNodePtr fnp_node,Boolean show_arrow,Boolean show_interval)626 static void AddFeatNodeListSegments(SegmenT p_seg, ValNodePtr fnp_node, Boolean show_arrow, Boolean show_interval)
627 {
628 	Int4 style, segstyle = 0;
629 	FeatNodePtr fnp;
630 	Boolean has_prev = FALSE;
631 	Int2 ptype = 0, _class;
632 	Boolean show_segments = FALSE;
633 	Boolean arrow = FALSE;
634 	SegmenT seg = NULL;
635 	Uint2 p_entityID = 0;
636 
637 	while(fnp_node)
638 	{
639 		fnp = fnp_node->data.ptrvalue;
640 		if(!has_prev || fnp->entityID != p_entityID)
641 		{
642 			seg = CreateSegment(p_seg, fnp->entityID, 0);
643 			p_entityID = fnp->entityID;
644 			has_prev = FALSE;	/*force to reset the style*/
645 		}
646 		_class = get_current_class(fnp);
647 		if(!has_prev || ptype != _class)
648 		{
649 
650 			style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
651 			segstyle = (style & MSM_SEG_FORM);
652 			if(segstyle == MSM_SEG_BOX || segstyle == MSM_SEG_LINE)
653 			{
654 				add_attribute_pen(seg, _class, MSM_SEGMENT);
655 				has_prev = TRUE;
656 				ptype = _class;
657 				show_segments = TRUE;
658 				if(show_arrow)
659 					arrow = (Boolean)(style & (Int4)MSM_SEG_SHOWORIENT);
660 				else
661 					arrow = FALSE;
662 			}
663 		}
664 		if(show_segments)
665 			DrawFeatNodeSegment(fnp, segstyle, MSM_SEGMENT, seg, arrow, show_interval);
666 		fnp_node = fnp_node->next;
667 	}
668 }
669 
670 
create_flat_node(ValNodePtr fnp_node)671 static ValNodePtr create_flat_node (ValNodePtr fnp_node)
672 {
673 	ValNodePtr flat_list = NULL, prev = NULL, curr;
674 	FeatNodePtr fnp;
675 	Int4 segstyle, style;
676 	Int2 _class;
677 
678 	while(fnp_node)
679 	{
680 		if(fnp_node->choice == OBJ_SEQFEAT)
681 		{
682 			fnp = fnp_node->data.ptrvalue;
683 			_class = get_current_class(fnp);
684 			style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
685 			segstyle = (style & MSM_SEG_FORM);
686 			if(segstyle != MSM_SEG_BOX && segstyle != MSM_SEG_LINE)
687 			{
688 				curr = ValNodeNew(NULL);
689 				curr->choice = fnp_node->choice;
690 				curr->data.ptrvalue = fnp;
691 				if(prev == NULL)
692 					flat_list = curr;
693 				else
694 					prev->next = curr;
695 				prev = curr;
696 			}
697 		}
698 		fnp_node = fnp_node->next;
699 	}
700 
701 	return flat_list;
702 }
703 
DrawFeatNode(ValNodePtr fnp_node,SegmenT seg,Uint1 label_type,Boolean show_arrow,Int4 scale,GeneDataPtr gdata)704 Boolean DrawFeatNode (ValNodePtr fnp_node, SegmenT seg, Uint1 label_type, Boolean show_arrow, Int4 scale, GeneDataPtr gdata)
705 {
706 	Uint1 label_align;
707 	Boolean show_interval = TRUE;
708 	ValNodePtr flat_list;
709 
710 	label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
711 	flat_list = create_flat_node (fnp_node);
712 	if(flat_list != NULL)
713 	{
714 		if(label_type != NO_LABEL)
715 			AddFeatNodeListLabel(seg, flat_list, label_align, scale, gdata);
716 		AddFlatNodeSymbol(seg, flat_list, scale);
717 		ValNodeFree(flat_list);
718 	}
719 
720 	if(scale > GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE))
721 		show_interval = FALSE;
722 	label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
723 
724 	if(fnp_node == NULL || fnp_node->choice !=OBJ_SEQFEAT)
725 		return FALSE;
726 	if(label_type != NO_LABEL)
727 		AddFeatNodeListLabel(seg, fnp_node, label_align, scale, gdata);
728 	if(show_interval)
729 		AddFeatNodeListGaps(seg, fnp_node);
730 	AddFeatNodeListSegments(seg, fnp_node, show_arrow, show_interval);
731 	AddFeatNodeListBorder(seg, fnp_node, show_arrow, show_interval);
732 
733 		/**if(draw_trunc)
734 		{
735 			if(fnp->extremes.l_trunc)
736 				DrawSquiggle(seg, e_left, fnp->line, fnp->itemID, TRUE);
737 			if(fnp->extremes.r_trunc)
738 				DrawSquiggle(seg, e_right, fnp->line, fnp->itemID, FALSE);
739 		}**/
740 
741 	return TRUE;
742 }
743 
get_bin_symbol(Uint2 bin_order)744 static Uint1 get_bin_symbol(Uint2 bin_order)
745 {
746 	switch(bin_order%4)
747 	{
748 		case 0:
749 			return UP_TRIANGLE_SYMBOL;
750 		case 1:
751 			return LEFT_TRIANGLE_SYMBOL;
752 		case 2:
753 			return DOWN_TRIANGLE_SYMBOL;
754 		default:
755 			return RIGHT_TRIANGLE_SYMBOL;
756 	}
757 }
758 
get_map_type(Uint4 extra)759 Uint1 get_map_type(Uint4 extra)
760 {
761 	if(extra & EXTRA_FRAME_WORK)
762 		return FRAME_WORK;
763 
764 	if(extra & EXTRA_RECMIN)
765 		return RECMIN;
766 
767 	if(extra & EXTRA_LIKELY)
768 		return LIKELY;
769 
770 	if(extra & EXTRA_MDUP)
771 		return MDUP;
772 
773 	if(extra & EXTRA_DUP)
774 		return DUP;
775 
776 	if(extra & EXTRA_CONTIG_STS)
777 		return CONTIG_STS;
778 
779 	return 0;
780 }
781 
get_symbol_color(Uint4 extra)782 static Uint1Ptr get_symbol_color(Uint4 extra)
783 {
784 	if(extra & EXTRA_YAC_END)
785 		return GREEN_COLOR;
786 	if(extra & EXTRA_RANDOM)
787 	{	/*this is a gold color */
788 		custom_color[0] = 255;
789 		custom_color[1] = 200;
790 		/* custom_color[1] = 215; */
791 		custom_color[2] = 0;
792 		return custom_color;
793 	}
794 	if(extra & EXTRA_GENETIC)
795 		return MAGENTA_COLOR;
796 	if(extra & EXTRA_GENE)
797 		return RED_COLOR;
798 	if(extra & EXTRA_EST)
799 		return BLUE_COLOR;
800 	if(extra & EXTRA_MISC)
801 		return CYAN_COLOR;
802 	return BLACK_COLOR;
803 }
804 
AddFlatNodeSymbol(SegmenT pseg,ValNodePtr fnp_node,Int4 scale)805 static Boolean  AddFlatNodeSymbol(SegmenT pseg, ValNodePtr fnp_node, Int4 scale)
806 {
807 	FeatNodePtr fnp;
808 	Boolean has_prev = FALSE;
809 	SegmenT seg = NULL;
810 	Int2 ptype, _class;
811 	Int4 symbol_height = 8;
812 	Int4 middle, center;
813 	/*Int4 color_val;*/
814 	Int4 segstyle;
815 	/*Uint1 color[3];*/
816 	Uint1Ptr this_color;
817 	Uint1 symbol_type = 0, symbol;
818 	/*Uint2 bin_order;*/
819 	Boolean fill;
820 	Uint1 map_mark_type;
821 	Uint2 p_entityID;
822 
823 	if(fnp_node == NULL)
824 		return FALSE;
825 	ptype = 0;
826 	p_entityID = 0;
827 	while(fnp_node)
828 	{
829 		fnp = fnp_node->data.ptrvalue;
830 		_class = get_current_class(fnp);
831 		fnp = fnp_node->data.ptrvalue;
832 		if(!has_prev || fnp->entityID != p_entityID)
833 		{
834 			seg = CreateSegment(pseg, fnp->entityID, 0);
835 			p_entityID = fnp->entityID;
836 			has_prev = FALSE;
837 		}
838 		if(!has_prev || ptype != _class)
839 		{
840 			/*color_val = GetMuskCParam(_class, MSM_SEGMENT, MSM_COLOR);
841 			convert_color(color_val, color);
842 			AddAttribute(seg, COLOR_ATT, &(color[0]), 0, 0, 0, 0);*/
843 			segstyle = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
844 			switch(segstyle & MSM_SEG_FORM)
845 			{
846 				case MSM_SEG_SYM_RECT:
847 					symbol_type = RECT_SYMBOL;
848 					break;
849 				case MSM_SEG_SYM_DIAMOND:
850 					symbol_type = DIAMOND_SYMBOL;
851 					break;
852 				case MSM_SEG_SYM_OVAL:
853 					symbol_type = OVAL_SYMBOL;
854 					break;
855 				case MSM_SEG_SYM_TRIANGLE:
856 					symbol_type = UP_TRIANGLE_SYMBOL;
857 					break;
858 				default:
859 					symbol_type = DIAMOND_SYMBOL;
860 					break;
861 			}
862 
863 			ptype = _class;
864 		}
865 		this_color = get_symbol_color(fnp->extra_data);
866 		AddAttribute(seg, COLOR_ATT, this_color, 0, 0, 0, 0);
867 		map_mark_type = get_map_type(fnp->extra_data);
868 		if(fnp->bin_order != 0)
869 			symbol = get_bin_symbol(fnp->bin_order);
870 		else
871 			symbol = symbol_type;
872 		fill = TRUE;
873 		if(map_mark_type == LIKELY || map_mark_type == MDUP || map_mark_type == DUP || map_mark_type == CONTIG_STS)
874 			fill = FALSE;
875 		center = (fnp->extremes.left + fnp->extremes.right)/2;
876 		middle = (fnp->top + fnp->bottom)/2;
877 		AddSymbol(seg, center, middle, symbol, fill, MIDDLE_CENTER, fnp->itemID);
878 		if(map_mark_type == FRAME_WORK)
879 		{
880 			AddSymbol(seg, center-8*scale, middle, symbol, TRUE, MIDDLE_CENTER, fnp->itemID);
881 			AddSymbol(seg, center+8*scale, middle, symbol, TRUE, MIDDLE_CENTER, fnp->itemID);
882 		}
883 		p_entityID = fnp->entityID;
884 		fnp_node = fnp_node->next;
885 	}
886 	return TRUE;
887 }
888 
DrawFlatNode(ValNodePtr vnp,SegmenT seg,Uint1 label_type,Int4 scale,GeneDataPtr gdata)889 Boolean DrawFlatNode(ValNodePtr vnp, SegmenT seg, Uint1 label_type, Int4 scale, GeneDataPtr gdata)
890 {
891 	Uint1 label_align;
892 
893 	if(label_type == UPPER_LABEL)
894 		label_align = MSM_LABEL_TOP;
895 	else
896 		label_align = MSM_LABEL_BOTTOM;
897 	AddFeatNodeListLabel(seg, vnp, label_align, scale, gdata);
898 	AddFlatNodeSymbol(seg, vnp, scale);
899 	return TRUE;
900 }
901 
902 
AddAlignmentLabel(ValNodePtr anp_list,SegmenT seg)903 static void AddAlignmentLabel(ValNodePtr anp_list, SegmenT seg)
904 {
905 	FonT font;
906 	Int4 color_val;
907 	Uint1 color[3];
908 	AlignNodePtr anp;
909 	Uint1 label_align;
910 	Uint4 itemID;
911 
912 
913 	font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_FONT);
914 	SelectFont(font);
915 	color_val = GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_COLOR);
916 	convert_color(color_val, color);
917 	AddAttribute(seg, COLOR_ATT|SHADING_ATT, &(color[0]), 0, SOLID_SHADING, 0, COPY_MODE);
918 
919 	label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
920 	while(anp_list)
921 	{
922 		anp = anp_list->data.ptrvalue;
923 		if(anp->use_seq_ids)
924 			itemID = anp->bsp_itemID;
925 		else
926 			itemID = anp->itemID;
927 		AddLabelWithAlign(seg, label_align, anp->extremes.left, anp->extremes.right, anp->top, anp->bottom, anp->label, font, itemID);
928 		anp_list = anp_list->next;
929 	}
930 	/*DeleteFont(font);*/
931 }
932 
933 
get_color_for_block(AlignNodePtr anp,Uint2 val)934 static Uint1Ptr get_color_for_block (AlignNodePtr anp, Uint2 val)
935 {
936 	switch(anp->index)
937 	{
938 		case 0:
939 			return get_seg_color((Int2)val);
940 		case 1:	/*it is a map index */
941 			if(val == MAP_STATUS_Mapping)
942 				return MAGENTA_COLOR;
943 			if(val == MAP_STATUS_Mapped)
944 				return RED_COLOR;
945 			if(val == MAP_STATUS_Paused)
946 				return BLUE_COLOR;
947 			return BLACK_COLOR;
948 		case 2:	/*it is a sequence index*/
949 			if(val == SEQ_STATUS_Plan)
950 				return CYAN_COLOR;
951 			if(val == SEQ_STATUS_Sequencing)
952 				return MAGENTA_COLOR;
953 			if(val == SEQ_STATUS_Sequenced)
954 				return RED_COLOR;
955 			if(val == SEQ_STATUS_Paused)
956 				return BLUE_COLOR;
957 			return BLACK_COLOR;
958 		default:
959 			return BLACK_COLOR;
960 	}
961 }
962 
963 
AddAlignBlocks(ValNodePtr anp_list,SegmenT seg)964 static void AddAlignBlocks(ValNodePtr anp_list, SegmenT seg)
965 {
966 	AlignNodePtr anp;
967 	Uint1Ptr color;
968 	AlignBlockPtr abp;
969 	Int2 arrow;
970 	Int2 c_num;
971 	Uint4 itemID;
972 
973 
974 	c_num = (Int2)GetMuskCParam(MSM_CCOLOR, MSM_NOSUBCLASS, MSM_NUM);
975 	while(anp_list)
976 	{
977 		anp = anp_list->data.ptrvalue;
978 		if(anp->use_seq_ids)
979 			itemID = anp->bsp_itemID;
980 		else
981 			itemID = anp->itemID;
982 		for(abp = anp->blocks; abp != NULL; abp = abp->next)
983 		{
984 			arrow = get_arrow_for_strand(abp->gr.strand);
985 			color = get_color_for_block (anp,(Int2)(abp->order));
986 
987 			/* pseg = CreateSegment(seg, OBJ_BIOSEQ_SEG, 0);
988 			sseg = CreateSegment(pseg, anp->entityID, 0);
989 			AddAttribute(sseg, COLOR_ATT, color, 0, 0, 0, 0);
990 			AddRectangle(sseg, abp->gr.left, anp->top, abp->gr.right, anp->bottom, arrow, TRUE, abp->order); */
991 			AddAttribute(seg, COLOR_ATT, color, 0, 0, 0, 0);
992 			AddRectangle(seg, abp->gr.left, anp->top, abp->gr.right, anp->bottom, arrow, TRUE, itemID);
993 		}
994 		anp_list = anp_list->next;
995 	}
996 }
997 
AddSeqWithAlignmentSymbol(SegmenT seg,ValNodePtr anp_list,Int4 scale)998 static void AddSeqWithAlignmentSymbol(SegmenT seg, ValNodePtr anp_list, Int4 scale)
999 {
1000 	Int4 length, width;
1001 	AlignNodePtr anp;
1002 	Int4 left, right, center;
1003 	Uint4 itemID;
1004 
1005 
1006 	length = scale *4;
1007 	width = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
1008 	if(width > 3)
1009 		width = 3;
1010 
1011 	while(anp_list)
1012 	{
1013 		anp = anp_list->data.ptrvalue;
1014 		if(anp && anp->seq_has_align == TRUE)
1015 		{
1016 			center = (anp->extremes.left + anp->extremes.right)/2;
1017 			left = center - length/2;
1018 			right = center + length/2;
1019 			if(anp->use_seq_ids)
1020 				itemID = anp->bsp_itemID;
1021 			else
1022 				itemID = anp->itemID;
1023 			AddRectangle(seg, left, anp->top + width, right, anp->top, FALSE, TRUE, itemID);
1024 		}
1025 
1026 		anp_list = anp_list->next;
1027 	}
1028 
1029 }
1030 /*#######################################################################
1031 #
1032 #	functions related to DrawAlignNode
1033 #
1034 #######################################################################*/
1035 
1036 
AddRepeatsToAlignment(ValNodePtr anp_list,SegmenT seg)1037 static void AddRepeatsToAlignment (ValNodePtr anp_list, SegmenT seg)
1038 {
1039 	AlignNodePtr anp;
1040 	AlignSegPtr asp;
1041 	Int4 left, right;
1042 	ValNodePtr f_node;
1043 	FeatNodePtr fnp;
1044 	Uint4 itemID;
1045 	Uint1 arrow;
1046 
1047 	AddAttribute(seg, COLOR_ATT|SHADING_ATT, BLACK_COLOR, 0, LIGHT_SHADING, 0, 0);
1048 	while(anp_list)
1049 	{
1050 		if(anp_list->choice != OBJ_SEQANNOT)
1051 		{
1052 			anp = anp_list->data.ptrvalue;
1053 			if(anp != NULL &&  anp->segs != NULL)
1054 			{
1055 				if(anp->use_seq_ids)
1056 					itemID = anp->bsp_itemID;
1057 				else
1058 					itemID = anp->itemID;
1059 				for(asp = anp->segs; asp != NULL; asp = asp->next)
1060 				{
1061 					f_node = asp->cnp;
1062 					while(f_node)
1063 					{
1064 						fnp = f_node->data.ptrvalue;
1065 						arrow = NO_ARROW;
1066 						left = fnp->extremes.right;
1067 						right =fnp->extremes.left;
1068 						if(anp->extremes.strand == Seq_strand_minus)
1069 						{
1070 							if(fnp->extremes.left == anp->extremes.left)
1071 								arrow = LEFT_ARROW;
1072 						}
1073 						else
1074 						{
1075 							if(fnp->extremes.right == anp->extremes.right)
1076 								arrow = RIGHT_ARROW;
1077 						}
1078 
1079 						if(fnp->feattype == FEATDEF_repeat_region || fnp->feattype == FEATDEF_repeat_unit)
1080 							AddRectangle(seg, left, asp->top-1, right, asp->bottom+1, arrow, TRUE, itemID);
1081 						f_node = f_node->next;
1082 					}
1083 				}
1084 			}
1085 		}
1086 		anp_list = anp_list->next;
1087 	}
1088 	AddAttribute(seg, COLOR_ATT|SHADING_ATT, BLACK_COLOR, 0, SOLID_SHADING, 0, COPY_MODE);
1089 }
1090 
1091 
DrawAlignSegs(SegmenT seg,AlignNodePtr anp)1092 static void DrawAlignSegs(SegmenT seg, AlignNodePtr anp)
1093 {
1094 	Int4 i_left, i_right, e_left, e_right;
1095 	Int4 p_left = 0, p_right = 0, p_top = 0, p_bottom = 0;
1096 	AlignSegPtr asp;
1097 	Int2 c_arrow, p_arrow = 0;
1098 	Uint1 strand;
1099 	Boolean has_prev = FALSE;
1100 	Boolean load;
1101 	Int4 seglen;
1102 	Uint4 itemID;
1103 
1104 
1105 
1106 	/*add each segment in alignment*/
1107 	strand = anp->extremes.strand;
1108 	e_left = anp->extremes.left;
1109 	e_right = anp->extremes.right;
1110 	if(anp->use_seq_ids)
1111 		itemID = anp->bsp_itemID;
1112 	else
1113 		itemID = anp->itemID;
1114 
1115 
1116 	if(anp->extremes.l_trunc == TRUE)
1117 		DrawSquiggle(seg, e_left, anp->bottom, itemID, TRUE);
1118 	if(anp->extremes.r_trunc == TRUE)
1119 		DrawSquiggle(seg, e_right, anp->bottom, itemID, FALSE);
1120 
1121 	if(anp->segs == NULL)	/*no intervals*/
1122 	{
1123 		c_arrow = get_arrow_for_strand(strand);
1124 		if(ABS(anp->bottom - anp->top) <= 3)
1125 			AddLine(seg, e_left, anp->top, e_right, anp->top, FALSE, itemID);
1126 		else
1127 			AddRectangle(seg, e_left, anp->top, e_right, anp->bottom, c_arrow, FALSE, itemID);
1128 		return;
1129 	}
1130 
1131 
1132 
1133 	for(asp = anp->segs; asp !=NULL; asp = asp->next)
1134 	{
1135 		switch(asp->type)
1136 		{
1137 			case INS_SEG:
1138 				seglen = asp->gr.right;
1139 				AddRectangle(seg, asp->gr.left, asp->top, (asp->gr.left+seglen-1), asp->bottom, NO_ARROW, FALSE, itemID);
1140 				AddLine(seg, asp->ins_pos, anp->bottom, asp->ins_pos, asp->top, FALSE, itemID);
1141 				break;
1142 			case GAP_SEG:
1143 				AddLine(seg, asp->gr.left, asp->top, asp->gr.right, asp->top, FALSE, itemID);
1144 				break;
1145 			default:
1146 				i_left = asp->gr.left;
1147 				i_right = asp->gr.right;
1148 				c_arrow = NO_ARROW;
1149 				if(i_left == e_left && strand == Seq_strand_minus)
1150 					c_arrow = LEFT_ARROW;
1151 				if(i_right == e_right && strand == Seq_strand_plus)
1152 					c_arrow = RIGHT_ARROW;
1153 				load = FALSE;
1154 
1155 				if(has_prev)
1156 				{
1157 					if(p_right+1 == i_left)
1158 					{
1159 						p_right = i_right;
1160 						if(strand != Seq_strand_minus)
1161 							p_arrow = c_arrow;
1162 						load = TRUE;
1163 					}
1164 					else
1165 						AddRectangle(seg, p_left, asp->top, p_right, asp->bottom, p_arrow, FALSE, itemID);
1166 				}
1167 				if(!load)
1168 				{
1169 					p_left = i_left;
1170 					p_right = i_right;
1171 					p_top = asp->top;
1172 					p_bottom = asp->bottom;
1173 					p_arrow = c_arrow;
1174 				}
1175 				has_prev = TRUE;
1176 				break;
1177 		}
1178 	}
1179 	if(has_prev)
1180 		AddRectangle(seg, p_left, p_top, p_right, p_bottom, p_arrow, FALSE, itemID);
1181 
1182 
1183 }
1184 
AddAlignmentSegs(ValNodePtr anp_list,SegmenT seg)1185 static void AddAlignmentSegs(ValNodePtr anp_list, SegmenT seg)
1186 {
1187 	AlignNodePtr anp;
1188 	Int2 num;	/*counting the number of the follower groups*/
1189 	Boolean p_follower = FALSE;
1190 
1191 	add_attribute_pen(seg, MSM_SEQUENCE, MSM_SEG_BORD);
1192 	num = 0;
1193 	while(anp_list)
1194 	{
1195 		anp = anp_list->data.ptrvalue;
1196 		if(anp->num_follower != 0 )
1197 		{
1198 			++num;
1199 			switch(num%3)
1200 			{
1201 				case 1:
1202 					AddAttribute (seg, COLOR_ATT, BLUE_COLOR,
1203 						NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1204 					break;
1205 				case 2:
1206 					AddAttribute (seg, COLOR_ATT, CYAN_COLOR,
1207 						NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1208 					break;
1209 				default:
1210 					AddAttribute (seg, COLOR_ATT, GREEN_COLOR,
1211 						NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1212 					break;
1213 			}
1214 		}
1215 		else if(num > 0 && anp->follower == FALSE && p_follower == TRUE)
1216 			AddAttribute (seg, COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1217 		p_follower = anp->follower;
1218 		DrawAlignSegs(seg, anp);
1219 		anp_list = anp_list->next;
1220 	}
1221 }
1222 
1223 
1224 
1225 typedef struct alignfeature{
1226 	Uint4 itemID;
1227 	Int4 e_left;
1228 	Int4 e_right;
1229 }AlignFeature, PNTR AlignFeaturePtr;
1230 
ck_load_itemID(Uint4 itemID,Int4 e_left,Int4 e_right,ValNodePtr PNTR item_list)1231 static void ck_load_itemID (Uint4 itemID, Int4 e_left, Int4 e_right, ValNodePtr PNTR item_list)
1232 {
1233 	ValNodePtr curr;
1234 	AlignFeaturePtr afp;
1235 
1236 
1237 	for(curr = *item_list; curr !=NULL; curr = curr->next)
1238 	{
1239 		afp = curr->data.ptrvalue;
1240 		if(afp->itemID == itemID)
1241 		{
1242 			afp->e_left = MIN(afp->e_left, e_left);
1243 			afp->e_right = MAX(afp->e_right, e_right);
1244 			return;
1245 		}
1246 	}
1247 
1248 	afp = MemNew(sizeof(AlignFeature));
1249 	afp->e_left = e_left;
1250 	afp->e_right = e_right;
1251 	afp->itemID = itemID;
1252 
1253 	ValNodeAddPointer(item_list, 0, (Pointer)afp);
1254 }
1255 
1256 
dup_interval_node(ValNodePtr list)1257 static ValNodePtr dup_interval_node(ValNodePtr list)
1258 {
1259 	ValNodePtr new = NULL;
1260 	IvalNodePtr inp, n_inp;
1261 
1262 	while(list)
1263 	{
1264 		inp = list->data.ptrvalue;
1265 		n_inp = MemNew(sizeof(IvalNode));
1266 		MemCopy((Pointer)n_inp, (Pointer)inp, sizeof(IvalNode));
1267 		ValNodeAddPointer(&new, 0, n_inp);
1268 
1269 		list = list->next;
1270 	}
1271 
1272 	return new;
1273 }
1274 
get_last_node(ValNodePtr list)1275 static ValNodePtr get_last_node(ValNodePtr list)
1276 {
1277 	if(list == NULL)
1278 		return NULL;
1279 
1280 	while(list->next != NULL)
1281 		list = list->next;
1282 	return list;
1283 }
1284 
merge_feature_interval_node(ValNodePtr PNTR i_node,ValNodePtr list,GatherRangePtr grp_i,GatherRangePtr grp_l)1285 static Boolean merge_feature_interval_node(ValNodePtr PNTR i_node, ValNodePtr list, GatherRangePtr grp_i, GatherRangePtr grp_l)
1286 {
1287 	ValNodePtr i_last, l_last, new;
1288 	IvalNodePtr i_inp, l_inp;
1289 
1290 
1291 	if(grp_i->right +1 == grp_l->left)
1292 	{
1293 		if(list != NULL)
1294 		{
1295 			if(*i_node == NULL)
1296 				*i_node = dup_interval_node(list);
1297 			else
1298 			{
1299 				i_last = get_last_node(*i_node);
1300 				i_inp = i_last->data.ptrvalue;
1301 				l_inp = list->data.ptrvalue;
1302 				if(i_inp->gr.right +1 ==  l_inp->gr.left)
1303 				{
1304 					i_inp->gr.right = l_inp->gr.right;
1305 					i_last->next = dup_interval_node(list->next);
1306 				}
1307 				else
1308 					i_last->next = dup_interval_node(list);
1309 			}
1310 		}
1311 		grp_i->right = grp_l->right;
1312 		return TRUE;
1313 	}
1314 
1315 	if(grp_i->left == grp_l->right +1)
1316 	{
1317 		if(list != NULL)
1318 		{
1319 			if(*i_node == NULL)
1320 				*i_node = dup_interval_node(list);
1321 			else
1322 			{
1323 				new = dup_interval_node(list);
1324 				l_last = get_last_node(list);
1325 				l_inp = l_last->data.ptrvalue;
1326 				i_inp = (*i_node)->data.ptrvalue;
1327 				if(l_inp->gr.right +1 == i_inp->gr.left)
1328 				{
1329 					l_last = get_last_node(new);
1330 					l_inp = l_last->data.ptrvalue;
1331 					l_inp->gr.right = i_inp->gr.right;
1332 					l_last->next = (*i_node)->next;
1333 					(*i_node)->next = NULL;
1334 					ValNodeFreeData(*i_node);
1335 				}
1336 				else
1337 				{
1338 					ValNodeLink(&new, *i_node);
1339 					*i_node = new;
1340 				}
1341 			}
1342 
1343 			grp_i->left = grp_l->left;
1344 		}
1345 
1346 		return TRUE;
1347 	}
1348 
1349 	return FALSE;
1350 }
1351 
1352 
1353 
is_repeat_feature(Uint1 feattype)1354 static Boolean is_repeat_feature (Uint1 feattype)
1355 {
1356 	return (feattype == FEATDEF_repeat_region ||feattype == FEATDEF_repeat_unit);
1357 }
1358 
AddAlignFeature(AlignNodePtr anp,SegmenT a_seg,Boolean show_arrow)1359 static void AddAlignFeature(AlignNodePtr anp, SegmenT a_seg, Boolean show_arrow)
1360 {
1361 	ValNodePtr item_list = NULL, c_list;
1362 	ValNodePtr i_node, p_node;
1363 	Uint4 itemID;
1364 	AlignSegPtr asp;
1365 	FeatNodePtr fnp, c_fnp;
1366 	GatherRange extremes;
1367 	ValNode vn;
1368 	ValNodePtr f_list;
1369 	Uint1 ptype = 0;
1370 	ValNodePtr repeat_node;
1371 
1372 	SegmenT seg;
1373 	Int4 offset;
1374 	Uint1 strand;
1375 	Boolean arrow;
1376 	AlignFeaturePtr afp;
1377 
1378 
1379 	/*collect a list of feature itemIDs for REG_SEGs because some
1380 	  may need to be merged later */
1381 	/*features in INS_SEG+DIAG_SEG are drawn because they don't need
1382 	  to be merged */
1383 	for(asp = anp->segs; asp !=NULL; asp = asp->next)
1384 	{
1385 		if(asp->type == INS_SEG || asp->type == DIAG_SEG)
1386 		{
1387 			if(asp->cnp !=NULL)
1388 			{
1389 				repeat_node = strip_repeat_feature(&(asp->cnp));
1390 				seg = CreateSegment(a_seg, OBJ_SEQFEAT, 0);
1391 				/*not showing any arrow here*/
1392 				DrawFeatNode (asp->cnp, seg, NO_LABEL, FALSE, 1, NULL);
1393 				if(repeat_node != NULL)
1394 					ValNodeLink(&(asp->cnp), repeat_node);
1395 				/*resume the previous layout for FeatNode*/
1396 				if(asp->type == INS_SEG)
1397 				{
1398 					offset = asp->gr.left - asp->ins_pos;
1399 					if(offset != 0)
1400 						modify_insert_fnode(asp->cnp, (-offset));
1401 				}
1402 			}
1403 		}
1404 		if(asp->type == REG_SEG)	/*need some merging process*/
1405 		{
1406 			for(f_list = asp->cnp; f_list !=NULL; f_list = f_list->next)
1407 			{
1408 				fnp = f_list->data.ptrvalue;
1409 				if(!is_repeat_feature (fnp->feattype))
1410 					ck_load_itemID (fnp->itemID, fnp->extremes.left, fnp->extremes.right, &item_list);
1411 			}
1412 		}
1413 	}
1414 
1415    if(item_list != NULL)
1416    {
1417 
1418 	/*merge the features in REG_SEG according to their itemID*/
1419 	for(c_list = item_list; c_list != NULL; c_list = c_list->next)
1420 	{
1421 		seg = CreateSegment(a_seg, OBJ_SEQFEAT, 0);
1422 		afp = c_list->data.ptrvalue;
1423 		itemID = afp->itemID;
1424 		c_fnp = NULL;
1425 		i_node = NULL;
1426 		for(asp = anp->segs; asp !=NULL; asp = asp->next)
1427 		{	if(asp->type == REG_SEG)
1428 			{
1429 				for(f_list = asp->cnp; f_list !=NULL; f_list = f_list->next)
1430 				{
1431 					fnp = f_list->data.ptrvalue;
1432 					if(fnp->itemID == itemID && !is_repeat_feature(fnp->feattype))	/*find the match*/
1433 					{
1434 						if(c_fnp == NULL)
1435 						{
1436 							c_fnp = fnp;
1437 							if(fnp->interval != NULL)
1438 								i_node = dup_interval_node(fnp->interval);
1439 							MemCopy(&extremes, &(fnp->extremes), sizeof(GatherRange));
1440 
1441 						}
1442 						else if(!merge_feature_interval_node(&i_node, fnp->interval, &(c_fnp->extremes), &(fnp->extremes)))
1443 						{
1444 							if(show_arrow)
1445 							{
1446 								strand = c_fnp->extremes.strand;
1447 								if(strand == Seq_strand_minus)
1448 									arrow = (c_fnp->extremes.left == afp->e_left);
1449 								else
1450 									arrow = (c_fnp->extremes.right == afp->e_right);
1451 							}
1452 							else
1453 								arrow = FALSE;
1454 							p_node = c_fnp->interval;
1455 							c_fnp->interval = i_node;
1456 							vn.choice = OBJ_SEQFEAT;
1457 							vn.data.ptrvalue = c_fnp;
1458 							vn.next = NULL;
1459 							DrawFeatNode (&vn, seg, NO_LABEL, arrow, 1, NULL);
1460 							c_fnp->interval = p_node;
1461 							MemCopy((Pointer)&(c_fnp->extremes), (Pointer)&extremes, sizeof(GatherRange));
1462 							if(i_node != NULL)
1463 								i_node = ValNodeFreeData(i_node);
1464 							c_fnp = fnp;
1465 							if(fnp->interval != NULL)
1466 								i_node = dup_interval_node(fnp->interval);
1467 							MemCopy((Pointer)&extremes, (Pointer)&(fnp->extremes), sizeof(GatherRange));
1468 						}
1469 					}
1470 
1471 				}
1472 			}
1473 		}
1474 
1475 		if(c_fnp != NULL)
1476 		{
1477 			if(show_arrow)
1478 			{
1479 				strand = c_fnp->extremes.strand;
1480 				if(strand == Seq_strand_minus)
1481 					arrow = (c_fnp->extremes.left == afp->e_left);
1482 				else
1483 					arrow = (c_fnp->extremes.right == afp->e_right);
1484 			}
1485 			else
1486 				arrow = FALSE;
1487 			p_node = c_fnp->interval;
1488 			c_fnp->interval = i_node;
1489 			vn.choice = OBJ_SEQFEAT;
1490 			vn.data.ptrvalue = c_fnp;
1491 			vn.next = NULL;
1492 			DrawFeatNode (&vn, seg, NO_LABEL, arrow, 1, NULL);
1493 			c_fnp->interval = p_node;
1494 			MemCopy((Pointer)&(c_fnp->extremes), (Pointer)&extremes, sizeof(GatherRange));
1495 		}
1496 		if(i_node != NULL)
1497 			i_node = ValNodeFreeData(i_node);
1498 	}
1499 
1500 	ValNodeFreeData(item_list);
1501    }
1502 
1503 }
1504 
AddAlignmentFeature(ValNodePtr anp_node,SegmenT seg,Int4 scale)1505 static void AddAlignmentFeature(ValNodePtr anp_node, SegmenT seg, Int4 scale)
1506 {
1507 	AlignNodePtr anp;
1508 	Boolean show_arrow;
1509 
1510 	show_arrow = (GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE) >= scale);
1511 
1512 	while(anp_node)
1513 	{
1514 		anp = anp_node->data.ptrvalue;
1515 		if(anp->segs !=NULL)
1516 			AddAlignFeature(anp, seg, show_arrow);
1517 		anp_node = anp_node->next;
1518 	}
1519 }
1520 
AddAlignmentMismatch(ValNodePtr anp_node,Int4 scale,SegmenT seg)1521 static void AddAlignmentMismatch(ValNodePtr anp_node, Int4 scale, SegmenT seg)
1522 {
1523 	Int4 i_right;
1524 	Int4 top, bottom;
1525 	Int4 p_i, j;
1526 	ValNodePtr curr, list;
1527 	AlignNodePtr anp;
1528 	AlignSegPtr asp;
1529 	Int4 symbol_width = 8;
1530 	Int2 p_type = -1, type;
1531 	Uint4 itemID;
1532 
1533 	AddAttribute (seg, WIDTH_ATT | COLOR_ATT, RED_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1534 
1535 	for(list = anp_node; list !=NULL; list = list->next)
1536 	{
1537 		anp = list->data.ptrvalue;
1538 		p_i = -1;
1539 		if(anp->use_seq_ids)
1540 			itemID = anp->bsp_itemID;
1541 		else
1542 			itemID = anp->itemID;
1543 		for(asp = anp->segs; asp !=NULL; asp = asp->next)
1544 		{
1545 			i_right = asp->gr.right;
1546 			top = asp->top;
1547 			bottom = asp->bottom;
1548 			for(curr = asp->mismatch; curr!=NULL; curr = curr->next)
1549 			{
1550 				j = curr->data.intvalue;
1551 				type = curr->choice;
1552 				if(type == 0)
1553 					symbol_width = 1;
1554 				else
1555 					symbol_width = 8;
1556 				if(p_i == -1 || (j-p_i) > scale * symbol_width || p_type != type)
1557 				{
1558 					switch (type)
1559 					{
1560 						case MISMATCH_OPEN:
1561 							AddSymbol(seg, j, (top+bottom)/2, OVAL_SYMBOL, FALSE, MIDDLE_CENTER, itemID);
1562 							break;
1563 						case MISMATCH_CLOSE:
1564 							AddSymbol(seg, j, (top+bottom)/2, OVAL_SYMBOL, TRUE, MIDDLE_CENTER, itemID);
1565 							break;
1566 						case MISMATCH_SQUARE:
1567 							AddSymbol(seg, j, (top+bottom)/2, RECT_SYMBOL, TRUE, MIDDLE_CENTER, itemID);
1568 							break;
1569 						default:
1570 							AddLine(seg, j, asp->top, j, (asp->bottom), FALSE, itemID);
1571 							break;
1572 					}
1573 					p_i = j;
1574 					p_type = type;
1575 				}
1576 			}
1577 		}
1578 	}
1579 }
1580 
extra_align_node(ValNodePtr anp_node,Boolean use_seq_ids)1581 static ValNodePtr extra_align_node(ValNodePtr anp_node, Boolean use_seq_ids)
1582 {
1583 	ValNodePtr head = NULL;
1584 	AlignNodePtr anp;
1585 
1586 	while(anp_node)
1587 	{
1588 		anp = anp_node->data.ptrvalue;
1589 		if(anp->use_seq_ids == use_seq_ids)
1590 			ValNodeAddPointer(&head, anp_node->choice, anp);
1591 		anp_node = anp_node->next;
1592 	}
1593 
1594 	return head;
1595 }
1596 
1597 /**********************************************************************
1598 *
1599 *	DrawAlignNode(vnp, scale, seg)
1600 *	Draw a list of AlignNode.
1601 *	1) It always labels the sequences
1602 *	2) the label is always on top of the sequence
1603 *	3) right now, it does NOT show the truncation
1604 *
1605 **********************************************************************/
DrawAlignNode(ValNodePtr vnp,Int4 scale,SegmenT seg)1606 Boolean DrawAlignNode(ValNodePtr vnp, Int4 scale, SegmenT seg)
1607 {
1608 	ValNodePtr anp_node, curr, next;
1609 	AlignNodePtr anp;
1610 	SegmenT t_seg, p_seg;
1611 
1612 	if(vnp == NULL)
1613 		return FALSE;
1614 
1615 	anp_node = extra_align_node(vnp, TRUE);
1616 	if(anp_node != NULL)
1617 	{
1618 		p_seg = CreateSegment(seg, OBJ_BIOSEQ, 0);
1619 		curr = anp_node;
1620 		while(curr)
1621 		{
1622 			next = curr->next;
1623 			curr->next = NULL;
1624 			anp = curr->data.ptrvalue;
1625 			t_seg = CreateSegment(p_seg, anp->seq_entityID, 0);
1626 			AddAlignmentSegs(curr, t_seg);
1627 			AddSeqWithAlignmentSymbol(t_seg, curr, scale);
1628 			AddAlignmentMismatch(curr, scale, t_seg);
1629 			AddAlignmentFeature(curr, t_seg, scale);
1630 			AddAlignBlocks(curr, t_seg);	/*add the blocks that are used in segmented seq*/
1631 			AddAlignmentLabel(curr, t_seg);
1632 			AddRepeatsToAlignment (curr, t_seg);
1633 			curr->next = next;
1634 			curr = next;
1635 		}
1636 		ValNodeFree(anp_node);
1637 	}
1638 
1639 
1640 	anp_node = extra_align_node(vnp, FALSE);
1641 	if(anp_node != NULL)
1642 	{
1643 		AddAlignmentSegs(anp_node, seg);
1644 		AddSeqWithAlignmentSymbol(seg, anp_node, scale);
1645 		AddAlignmentMismatch(anp_node, scale, seg);
1646 		AddAlignmentFeature(anp_node, seg, scale);
1647 		AddAlignBlocks(anp_node, seg);	/*add the blocks that are used in segmented seq*/
1648 		AddAlignmentLabel(anp_node, seg);
1649 		AddRepeatsToAlignment(anp_node, seg);
1650 		ValNodeFree(anp_node);
1651 	}
1652 
1653 	return TRUE;
1654 }
1655 
1656 
DrawFlatAlign(SegmenT seg,ValNodePtr anp_list)1657 Boolean DrawFlatAlign(SegmenT seg, ValNodePtr anp_list)
1658 {
1659 	Uint4 itemID;
1660 	AlignNodePtr anp;
1661 	Int4 pos;
1662 
1663 	if(anp_list == NULL)
1664 		return FALSE;
1665 	AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1666 	while(anp_list)
1667 	{
1668 		if(anp_list->choice != OBJ_SEQANNOT)
1669 		{
1670 			anp = anp_list->data.ptrvalue;
1671 			itemID = anp->itemID;
1672 			pos = anp->extremes.left;
1673 
1674 			AddSymbol(seg, pos, anp->line, DIAMOND_SYMBOL, TRUE, UPPER_CENTER, itemID);
1675 
1676 		}
1677 		anp_list = anp_list->next;
1678 	}
1679 
1680 	return TRUE;
1681 }
1682 
1683 
1684 
1685 /*************************************************************************
1686 *
1687 *	DrawGeneticMap(features, mpp, pic, scale)
1688 *	draw the genetic map from featnode
1689 *	features: the list of FeatNode, will be resorted
1690 *	mpp: the current map position. The drawing will recalculate
1691 *	mpp->seq_top and mpp->bottom
1692 *	pic: the drawing picture
1693 *	scale: the maximum scale in drawing. Will be used in the layout
1694 *	gdata: to include the possible selected marker
1695 *
1696 *************************************************************************/
DrawGeneticMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR image_list)1697 Boolean DrawGeneticMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR image_list)
1698 {
1699 	SegmenT seg;
1700 	Int4 top;
1701 	ValNodePtr g_node;
1702 	Boolean retval = FALSE;
1703 
1704 	seg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1705 	g_node = extract_node_list(features, OBJ_BIOSEQ_MAPFEAT, 0, 0, ALL_LABEL);
1706 	top = mpp->seq_top;
1707 	AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1708 	if(g_node)
1709 	{
1710 		top = LayoutNodeFlat(&g_node, scale, top, UPPER_LABEL, FALSE);
1711 		if(image_list != NULL)
1712 			load_align_label_rectangle(g_node, image_list, scale, TRUE);
1713 		DrawFlatNode(g_node, seg, UPPER_LABEL, scale, gdata);
1714 		FreeFeatureList(g_node);
1715 		mpp->seq_bottom = mpp->seq_top = top;
1716 		retval = TRUE;
1717 	}
1718 	AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1719 	AddLine(seg, mpp->left, mpp->seq_top, mpp->right, mpp->seq_top, FALSE, 0);
1720 	DrawSeqScale(seg, mpp->slp, mpp->left, mpp->seq_top, scale, FALSE);
1721 	mpp->bottom = mpp->seq_bottom - SCALE_SPACE;
1722 	return retval;
1723 }
1724 
1725 
1726 
1727 /*************************************************************************
1728 *
1729 *	DrawPhysicalMap(features, mpp, pic, scale)
1730 *	draw the physical map from featnode
1731 *	features: the list of FeatNode, will be resorted
1732 *	mpp: the current map position. The drawing will recalculate
1733 *	mpp->seq_top and mpp->bottom
1734 *	pic: the drawing picture
1735 *	scale: the maximum scale in drawing. Will be used in the layout
1736 *
1737 *************************************************************************/
DrawPhysicalMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Int4 scale,ValNodePtr PNTR image_list)1738 Boolean DrawPhysicalMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Int4 scale, ValNodePtr PNTR image_list)
1739 {
1740 	SegmenT pseg, seg;
1741 	Int4 top;
1742 	ValNodePtr g_node;
1743 	Boolean retval = FALSE;
1744 
1745 	pseg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1746 	seg = CreateSegment(pseg, mpp->entityID, 0);
1747 	g_node = extract_node_list(features, OBJ_SEQFEAT, 0, 0, NUM_LABEL);
1748 	top = mpp->seq_top;
1749 	AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1750 	AddLine(seg, mpp->left, top, mpp->right, top, FALSE, 0);
1751 	if(g_node)
1752 	{
1753 		top = LayoutNodeFlat(&g_node, scale, top, LOWER_LABEL, FALSE);
1754 		if(image_list != NULL)
1755 			load_align_label_rectangle(g_node, image_list, scale, TRUE);
1756 		DrawFlatNode(g_node, pseg, LOWER_LABEL, scale, NULL);
1757 		top -= (TICK_LEN+LABEL_SPACE);
1758 		FreeFeatureList(g_node);
1759 		mpp->seq_bottom = mpp->seq_top;
1760 		retval = TRUE;
1761 	}
1762 	else
1763 		DrawSeqScale(pic, mpp->slp, mpp->left, mpp->bottom, scale, FALSE);
1764 
1765 	top -= (LABEL_SPACE+TICK_LEN);
1766 	mpp->bottom = top;
1767 	return retval;
1768 }
1769 
1770 
sort_same_itemID(ValNodePtr head)1771 static ValNodePtr sort_same_itemID(ValNodePtr head)
1772 {
1773 	FeatNodePtr fnp;
1774 	ValNodePtr list = NULL, new;
1775 
1776 	while(head)
1777 	{
1778 		fnp = head->data.ptrvalue;
1779 		new = merge_same_itemID(&head, fnp->itemID);
1780 		ValNodeLink(&list, new);
1781 	}
1782 
1783 	return list;
1784 }
1785 
1786 
1787 
1788 /***********************************************************************
1789 *
1790 *	DrawRestrictionMap(features, mpp, pic, rsite_flat, strand)
1791 *	draw the restriction map
1792 *	features: the FeatNode contains the info for restriction map
1793 *	mpp: the map position
1794 *	pic: picture
1795 *	rsite_flat: if(TRUE), all the enzymes are shown in one line.
1796 *	strand: the orientation of the map
1797 *
1798 ***********************************************************************/
DrawRestrictionMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Boolean rsite_flat,Uint1 strand,Int4 scale)1799 Boolean DrawRestrictionMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Boolean rsite_flat, Uint1 strand, Int4 scale)
1800 {
1801 
1802 	Int4 x1, x2, center;
1803 	Int2 arrow;
1804 	ValNodePtr seq_node, g_node, curr, c_head;
1805 	FeatNodePtr fnp;
1806 	IvalNodePtr inp;
1807 	ValNodePtr ivals;
1808 	Int4 top;
1809 	Int2 i;
1810 	Uint1Ptr color;
1811 	Boolean retval = FALSE;
1812 	SegmenT pseg, seg;
1813 	Int4 seq_width;
1814 	FonT font;
1815 
1816 	font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_FONT);
1817 	SelectFont(font);
1818 	seq_width = FontHeight();
1819 	/* seq_width = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT); */
1820 	arrow = get_arrow_for_strand(strand);
1821 	x1 = mpp->left;
1822 	x2 = mpp->right;
1823 	center = (x1+x2)/2;
1824 	top = mpp->seq_top;
1825 
1826 	pseg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1827 	seg = CreateSegment(pseg, mpp->entityID, 0);
1828 	if(rsite_flat)
1829 	{
1830 		seq_node = extract_node_list(features, OBJ_BIOSEQ, 0, 0, ALL_LABEL);
1831 		fnp = seq_node->data.ptrvalue;
1832 		AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1833 		AddRectangle (seg, x1, top, x2, top-seq_width, arrow, FALSE, fnp->itemID);
1834 		AddLabel(seg, x1, top, fnp->label, SMALL_TEXT, 0, LOWER_CENTER, fnp->itemID);
1835 		mpp->seq_top = top;
1836 		mpp->seq_bottom = top - seq_width;
1837 		top -= LABEL_SPACE;
1838 		FreeFeatureList(seq_node);
1839 		mpp->bottom = top;
1840 	}
1841 
1842 	g_node = extract_node_list(features, OBJ_BIOSEQ_MAPFEAT, 0, 0, ALL_LABEL);
1843 	if(g_node == NULL)
1844 		return FALSE;
1845 	i = 0;
1846 	while(g_node)
1847 	{
1848 		fnp = (FeatNodePtr)(g_node->data.ptrvalue);
1849 		c_head  = merge_same_itemID(&g_node, fnp->itemID);
1850 		if(c_head)
1851 		{
1852 			if(!rsite_flat)
1853 			{
1854 				(mpp->seq_bottom) -=seq_width;
1855 				top = mpp->seq_bottom + seq_width;
1856 				AddAttribute (seg, WIDTH_ATT | COLOR_ATT,BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
1857 				AddLabel(seg, mpp->left, top+seq_width/2, fnp->label, SMALL_TEXT, 5, LOWER_LEFT, fnp->itemID);
1858 				AddLine(seg, mpp->left, top - seq_width, mpp->right, top-seq_width, FALSE, 0);
1859 				if(i == 0)
1860 					AddLine(seg, mpp->left, top, mpp->right, top, FALSE, 0);
1861 			}
1862 
1863 		   for(curr = c_head; curr !=NULL; curr = curr->next)
1864 		   {
1865 			fnp = (FeatNodePtr)(curr->data.ptrvalue);
1866 			color = get_enz_color(i);
1867 			AddAttribute (seg, WIDTH_ATT | COLOR_ATT,color, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
1868 			ivals = fnp->interval;
1869 			while(ivals)
1870 			{
1871 				inp = ivals->data.ptrvalue;
1872 				AddLine(seg, inp->gr.left, (mpp->seq_bottom+seq_width), inp->gr.left, mpp->seq_bottom, FALSE, fnp->itemID);
1873 				ivals = ivals->next;
1874 			}
1875 		   }
1876 		   if(!rsite_flat)
1877 			top = mpp->seq_bottom;
1878 		   ++i;
1879 		   FreeFeatureList(c_head);
1880 		}
1881 	}
1882 	DrawSeqScale(seg, mpp->slp, mpp->left, mpp->seq_bottom, scale, FALSE);
1883 	mpp->bottom = mpp->seq_bottom - SCALE_SPACE;
1884 	return TRUE;
1885 }
1886 
1887 /***********************************************************************
1888 *
1889 *	DrawCytoMap(features, mpp, scale, pic)
1890 *	draw the cytogenetic map
1891 *	features: the FeatNode for cytogenetic map
1892 *	scale: maximum scale, used in layout
1893 *	pic: the drawing segment
1894 *
1895 ***********************************************************************/
label_cyto_band(Int4 x1,Int4 x2,Int4Ptr prev,CharPtr label,Int4 scale)1896 static Boolean label_cyto_band(Int4 x1, Int4 x2, Int4Ptr prev, CharPtr label, Int4 scale)
1897 {
1898 	Int4 center;
1899 	Int4 half_len;
1900 
1901 	half_len = StringWidth(label)/2;
1902 	center = (x1+x2)/(2 * scale);
1903 	if((*prev == -1) || ((center - half_len) > (*prev)))
1904 	{
1905 		*prev = center + half_len;
1906 		return TRUE;
1907 	}
1908 	else
1909 		return FALSE;
1910 }
1911 
DrawCytoMap(ValNodePtr PNTR features,MapPosPtr mpp,Int4 scale,SegmenT pic)1912 Boolean DrawCytoMap(ValNodePtr PNTR features, MapPosPtr mpp, Int4 scale, SegmenT pic)
1913 {
1914 	Int4 x1, x2, center;
1915 	SegmenT seg, pseg;
1916 	Int4 top;
1917 	Int4 prev_pos = -1;
1918 	ValNodePtr g_node, curr;
1919 	FeatNodePtr fnp;
1920 	Boolean retval = FALSE;
1921 	Uint1Ptr color = NULL;
1922 	Uint1 shading = 0;
1923 	CharPtr subdiv = NULL;
1924 	Int2 numdiv =0;
1925 	Int4 prev_right = -1;
1926 	Int4 seq_width;
1927 
1928 
1929 	top = mpp->seq_top;
1930 	seq_width = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT);
1931 
1932 	pseg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1933 	seg = CreateSegment(pseg, mpp->entityID, 0);
1934 
1935 	g_node = extract_node_list(features, OBJ_BIOSEQ_MAPFEAT, 0, 0, ALL_LABEL);
1936 	if(g_node)
1937 	{
1938 		for(curr = g_node; curr!=NULL; curr = curr->next)
1939 		{
1940 			fnp = curr->data.ptrvalue;
1941 			switch(fnp->band)
1942 			{
1943 				case BND:
1944 					color = BLACK_COLOR;
1945 					break;
1946 				case HET :
1947 					color = BLUE_COLOR;
1948 					break;
1949 				case TEL:
1950 				case CEN:
1951 					color = RED_COLOR;
1952 					shading = SOLID_SHADING;
1953 					break;
1954 				case BAND_POINT:
1955 					color = RED_COLOR;
1956 					shading = SOLID_SHADING;
1957 					break;
1958 				case GIEMSA_POS:
1959 					color = BLACK_COLOR;
1960 					shading = SOLID_SHADING;
1961 					break;
1962 				case GIEMSA_NEG:
1963 					color = WHITE_COLOR;
1964 					shading = SOLID_SHADING;
1965 					break;
1966 				case ACRO_CENTRIC:
1967 					color = BLACK_COLOR;
1968 					shading = THICK_NWSE_SHADING;
1969 					break;
1970 				case VARIABLE_REG:
1971 					color = BLACK_COLOR;
1972 					shading = THIN_NESW_SHADING;
1973 					break;
1974 
1975 				case MISC_BND:
1976 					color = BLACK_COLOR;
1977 					shading = SOLID_SHADING;
1978 					break;
1979 
1980 				default:
1981 					Message(MSG_ERROR, "Illegal type");
1982 					exit(1);
1983 			}
1984 
1985 			if(fnp->band == BND || fnp->band == HET)
1986 			{
1987 				if(numdiv == 0)
1988 				{
1989 					++numdiv;
1990 					subdiv = fnp->pos_label;
1991 				}
1992 				else
1993 				{
1994 					if(StringCmp(subdiv, fnp->pos_label))
1995 					{
1996 						++numdiv;
1997 						subdiv = fnp->pos_label;
1998 					}
1999 				}
2000 				if(numdiv%2 == 0)
2001 					shading = THIN_NESW_SHADING;
2002 				else
2003 					shading = THIN_NWSE_SHADING;
2004 			}
2005 
2006 			x1= fnp->extremes.left;
2007 			x2= fnp->extremes.right;
2008 			if(prev_right !=-1 && (x1 - prev_right) > scale)
2009 			{
2010 				AddAttribute (seg, SHADING_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, SOLID_SHADING, 1, COPY_MODE);
2011 				AddLine(seg, prev_right, top, x1, top, FALSE, 0);
2012 				AddLine(seg, prev_right, top-seq_width, x1, top-seq_width, FALSE, 0);
2013 			}
2014 			prev_right = x2;
2015 
2016 			if(fnp->band == MISC_BND)
2017 			{
2018 				AddAttribute (seg, COLOR_ATT|SHADING_ATT, BLACK_COLOR, NO_LINE_STYLE, SOLID_SHADING, 1, COPY_MODE);
2019 				AddRectangle(seg, x1, top, x2, top-seq_width, NO_ARROW, FALSE, fnp->itemID);
2020 			}
2021 			else
2022 			{
2023 				AddAttribute (seg, SHADING_ATT | COLOR_ATT, color, NO_LINE_STYLE, shading, 1, COPY_MODE);
2024 				AddRectangle(seg, x1, top, x2, top-seq_width, NO_ARROW, TRUE, fnp->itemID);
2025 				if(fnp->band == GIEMSA_NEG)
2026 					color = BLACK_COLOR;
2027 				AddAttribute (seg, SHADING_ATT | COLOR_ATT, color, NO_LINE_STYLE, SOLID_SHADING, 1, COPY_MODE);
2028 				AddRectangle(seg, x1, top, x2, top-seq_width, NO_ARROW, FALSE, fnp->itemID);
2029 			}
2030 			if(fnp->label)
2031 			{
2032 				if(label_cyto_band(x1, x2, &prev_pos, fnp->label, scale))
2033 				{
2034    					center = (x1+ x2)/2;
2035 	    	 			AddLabel(seg, center, top-seq_width-5, fnp->label, SMALL_TEXT, 0, LOWER_CENTER, fnp->itemID);
2036 				}
2037 			}
2038 		}
2039 		mpp->seq_top = top;
2040 		mpp->seq_bottom = top - seq_width;
2041 
2042 		top -= ( seq_width + LABEL_SPACE+5);
2043 		mpp->bottom = top;
2044 		FreeFeatureList(g_node);
2045 		retval = TRUE;
2046 	}
2047 
2048 	return retval;
2049 }
2050 
2051 
2052 
draw_sequence_fnp(FeatNodePtr fnp,Boolean fill,Uint1 label_align,SegmenT seg,Uint1Ptr color,Int4 segstyle,Boolean show_border)2053 static void draw_sequence_fnp(FeatNodePtr fnp, Boolean fill, Uint1 label_align, SegmenT seg, Uint1Ptr color, Int4 segstyle, Boolean show_border)
2054 {
2055 	Int2 arrow;
2056 	FonT font;
2057 	Int4 c_val;
2058 	Uint1 label_color[3];
2059 	Uint1 flags = COLOR_ATT|STYLE_ATT|SHADING_ATT|WIDTH_ATT;
2060 	Uint1 linestyle, penwidth, shading;
2061 
2062 
2063 	if(fnp->label != NULL)
2064 	{
2065 
2066 		font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_FONT);
2067 		SelectFont(font);
2068 		fnp->labelHeight = FontHeight();
2069 
2070 		c_val = GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_COLOR);
2071 		convert_color(c_val, label_color);
2072 		AddAttribute (seg, COLOR_ATT, &label_color[0], 0, 0, 0, 0);
2073 		AddFeatNodeLabel(seg, fnp, label_align, font);
2074 	}
2075 
2076 	arrow = get_arrow_for_strand(fnp->extremes.strand);
2077 
2078 	if(color == NULL)
2079 	{
2080 		if(segstyle == MSM_SEG_BOX)
2081 			add_attribute_pen(seg, MSM_SEQUENCE, MSM_SEGMENT);
2082 		else
2083 			add_attribute_pen(seg, MSM_SEQUENCE, (Int2)segstyle);
2084 	}
2085 	else	/*the one's that uses cycle color*/
2086 	{
2087 		linestyle = (Uint1)GetMuskCParam(MSM_SEQUENCE, (Int2)segstyle, MSM_LTYPE);
2088 		penwidth = (Uint1)GetMuskCParam(MSM_SEQUENCE, (Int2)segstyle, MSM_PENWIDTH);
2089 		shading = (Uint1)GetMuskCParam(MSM_SEQUENCE, (Int2)segstyle, MSM_SHADING);
2090 		AddAttribute(seg, flags, color, linestyle, shading, penwidth, COPY_MODE);
2091 	}
2092 
2093 	if(fill)
2094 	{
2095 
2096 		if(segstyle == MSM_SEG_LINE)
2097 			AddLine(seg, fnp->extremes.left, fnp->top, fnp->extremes.right, fnp->top, FALSE, fnp->itemID);
2098 		else
2099 			AddRectangle (seg, fnp->extremes.left, fnp->top, fnp->extremes.right, fnp->bottom, arrow, fill, fnp->itemID);
2100 	}
2101 
2102 	if(show_border || !fill)
2103 	{
2104 		add_attribute_pen(seg, MSM_SEQUENCE, MSM_SEG_BORD);
2105 		AddRectangle (seg, fnp->extremes.left, fnp->top, fnp->extremes.right, fnp->bottom, arrow, FALSE, fnp->itemID);
2106 	}
2107 
2108 }
2109 
2110 
2111 /*********************************************************************
2112 *
2113 *	DrawSeqMap(features, mpp, pic, flat, scale, is_raw_seq)
2114 *	Draw the real sequence map
2115 *	features: FeatNode from which the Bioseqs can be extracted
2116 *	mpp: the MapPos that contains the current map position
2117 *	pic: the picture
2118 *	flat: if TRUE, draw the map with features stacked on top
2119 *	scale: maximum scale of the sequence
2120 *	is_raw_seq: if TRUE, it is a raw DNA sequence. (This is
2121 *	used to distinguish raw sequence from virtual sequence
2122 *	if(show_segment and image_list), record the positions of the
2123 *	segments
2124 *
2125 *********************************************************************/
DrawSeqMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Int4 scale,Boolean is_raw_seq,Boolean show_segment,ValNodePtr PNTR image_list)2126 Boolean DrawSeqMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Int4 scale, Boolean is_raw_seq, Boolean show_segment, ValNodePtr PNTR image_list)
2127 {
2128 	ValNodePtr seg_node = NULL, g_node, c_node;
2129 	ValNodePtr prev, next, gap_node = NULL;
2130 	Int4 middle;
2131 	FeatNodePtr fnp, c_fnp;
2132 	SegmenT seg, pseg;
2133 	Uint1Ptr color;
2134 	Boolean fill;
2135 	Int4 top;
2136 	Int4 e_left, e_right;
2137 	Uint2 entityID;
2138 	Int2 arrow;
2139 	Uint1 label_align;
2140 	Uint1 seq_label_align;
2141 	Int4 style, segstyle;
2142 	Boolean show_border;
2143 	Int2 obj_bioseq_seg_or_delta;
2144 
2145 
2146 
2147 	entityID = (Uint2)mpp->entityID;
2148 	label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
2149 
2150 	c_node = extract_node_list(features, OBJ_BIOSEQ, entityID, 0, ALL_LABEL);
2151 	c_node = sort_same_itemID(c_node);
2152 	if(c_node == NULL)
2153 		return FALSE;
2154 	c_fnp = c_node->data.ptrvalue;
2155 	c_fnp->line = 0;
2156 
2157 	style = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_STYLE);
2158 	segstyle = (style & MSM_SEG_FORM);
2159 	if(segstyle != MSM_SEG_BOX && segstyle != MSM_SEG_LINE)
2160 		segstyle = MSM_SEG_BOX;
2161 	if(segstyle ==MSM_SEG_BOX)
2162 		show_border = (Boolean)GetMuskCParam(MSM_SEQUENCE, MSM_SEG_BORD, MSM_TRUEFALSE);
2163 	else
2164 		show_border = FALSE;
2165 
2166 	top = LayoutFeatNode(c_node, mpp->seq_top, scale, 0, TRUE, FALSE);
2167 	obj_bioseq_seg_or_delta = OBJ_BIOSEQ_SEG;
2168 	seg_node = extract_node_list(features, OBJ_BIOSEQ_SEG, entityID, 0, ALL_LABEL);
2169 	if(seg_node == NULL) {
2170 		obj_bioseq_seg_or_delta = OBJ_BIOSEQ_DELTA;
2171 		seg_node = extract_node_list(features, OBJ_BIOSEQ_DELTA, entityID, 0, ALL_LABEL);
2172 	}
2173 	fill = (is_raw_seq && seg_node == NULL);
2174 
2175 	pseg = CreateSegment(pic, OBJ_BIOSEQ, 0);
2176 	seg = CreateSegment(pseg, entityID, 0);
2177 	if(label_align != MSM_LABEL_RIGHT)
2178 		seq_label_align = MSM_LABEL_LEFT;
2179 	else
2180 		seq_label_align = MSM_LABEL_RIGHT;
2181 
2182 	draw_sequence_fnp(c_fnp, fill, seq_label_align, seg, NULL, segstyle, show_border);
2183 	/* if(image_list != NULL)
2184 	{
2185 		vn.choice = OBJ_BIOSEQ;
2186 		vn.data.ptrvalue = c_fnp;
2187 		vn.next = NULL;
2188 		load_align_label_rectangle(&vn, image_list, scale, FALSE);
2189 	} */
2190 	mpp->seq_top = c_fnp->top;
2191 	mpp->seq_bottom = c_fnp->bottom;
2192 
2193 
2194 	/*add the segments to the sequence picture. Also get rid of the
2195 	FeatNode that only contains the gaps. if(fnp->follower = TRUE), it
2196 	is a gap */
2197 
2198 	g_node = seg_node;
2199 	prev = NULL;
2200 	gap_node = NULL;
2201 	while(g_node)
2202 	{
2203 		next = g_node->next;
2204 		arrow = NO_ARROW;
2205 		fnp = g_node->data.ptrvalue;
2206 		e_left = fnp->extremes.left;
2207 		e_right = fnp->extremes.right;
2208 		if(fnp->follower)	/*it is a gap between the segment*/
2209 		{
2210 			if(prev == NULL)
2211 				seg_node = g_node->next;
2212 			else
2213 				prev->next = g_node->next;
2214 			g_node->next = NULL;
2215 			ValNodeLink(&gap_node, g_node);
2216 		}
2217 		else
2218 		{
2219 			if(e_left == c_fnp->extremes.left && c_fnp->extremes.strand == Seq_strand_minus)
2220 				arrow = LEFT_ARROW;
2221 			if(e_right == c_fnp->extremes.right && c_fnp->extremes.strand == Seq_strand_plus)
2222 				arrow = RIGHT_ARROW;
2223 			color = get_seg_color(fnp->itemID);
2224 			AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, COPY_MODE);
2225 			if(segstyle == MSM_SEG_BOX)
2226 				AddRectangle (seg, e_left, c_fnp->top, e_right, c_fnp->bottom, arrow, TRUE, c_fnp->itemID);
2227 			else
2228 				AddLine(seg, e_left, c_fnp->top, e_right, c_fnp->top, FALSE, c_fnp->itemID);
2229 			prev = g_node;
2230 		}
2231 		g_node = next;
2232 	}
2233 
2234 
2235 	if(gap_node != NULL)
2236 	{
2237 		AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 2, NO_MODE);
2238 		middle = (c_fnp->top + c_fnp->bottom)/2;
2239 		for(g_node = gap_node; g_node != NULL; g_node = g_node->next)
2240 		{
2241 			fnp = g_node->data.ptrvalue;
2242 			e_left = fnp->extremes.left;
2243 			AddSymbol(seg, e_left, middle, DIAMOND_SYMBOL, FALSE, MIDDLE_CENTER, fnp->itemID);
2244 		}
2245 		FreeFeatureList(gap_node);
2246 	}
2247 
2248 	DrawSeqScale(seg, mpp->slp, mpp->left, mpp->seq_bottom, scale, FALSE);
2249 	top -= SCALE_SPACE;	/*space for drawing the scale */
2250 	if(seg_node !=NULL && show_segment)
2251 	{
2252 		top -= GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
2253 		pseg = CreateSegment(pic, obj_bioseq_seg_or_delta, 0);
2254 		seg = CreateSegment(pseg, entityID, 0);
2255 
2256 		ReSetFeatNode(seg_node);
2257 		top = LayoutFeatNode(seg_node, top, scale, 0, TRUE, FALSE);
2258 
2259 		for(g_node = seg_node; g_node !=NULL; g_node = g_node->next)
2260 		{
2261 			fnp = g_node->data.ptrvalue;
2262 			e_left = fnp->extremes.left;
2263 			e_right = fnp->extremes.right;
2264 			color = get_seg_color(fnp->itemID);
2265 			draw_sequence_fnp(fnp, TRUE, label_align, seg, color, segstyle, show_border);
2266 		}
2267 		if(image_list != NULL)
2268 			load_align_label_rectangle(seg_node, image_list, scale, FALSE);
2269 	}
2270 
2271 
2272 	mpp->bottom = top;
2273 
2274 	FreeFeatureList(c_node);
2275 	FreeFeatureList(seg_node);
2276 	return TRUE;
2277 }
2278 
2279 
2280 
DrawOneFeatNode(ValNodePtr g_node,Int4 top,SegmenT seg,Int4 scale,Int2 group_num,GeneDataPtr gdata,ValNodePtr PNTR image_rect)2281 static Int4 DrawOneFeatNode(ValNodePtr g_node, Int4 top, SegmenT seg,  Int4 scale, Int2 group_num, GeneDataPtr gdata, ValNodePtr PNTR image_rect)
2282 {
2283 	Boolean show_arrow;
2284 	Boolean compress;
2285 
2286 
2287 	if(g_node != NULL)
2288 	{
2289 
2290 		show_arrow = (GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE) >= scale);
2291  		compress = (GetMuskCParam(MSM_GROUPS, group_num, MSM_STYLE) == MSM_COMPRESS);
2292 
2293 		top -= GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
2294 
2295 		top = LayoutFeatNode(g_node,top, scale, scale, TRUE, compress);
2296 
2297 		if(image_rect)
2298 			load_align_label_rectangle(g_node, image_rect, scale, FALSE);
2299 		DrawFeatNode (g_node, seg, UPPER_LABEL, show_arrow, scale, gdata);
2300 	}
2301 
2302 	return top;
2303 }
2304 
2305 /******************************************************************
2306 *
2307 *	ck_ordered_group(): check if the internal order is important
2308 *	to a group. Currently, only set up for the Gene-CDS-mRNA feature
2309 *
2310 *******************************************************************/
ck_ordered_group(Uint1 group_num,Uint1Ptr groupOrder)2311 static Boolean ck_ordered_group(Uint1 group_num, Uint1Ptr groupOrder)
2312 {
2313 	Uint2 i;
2314 
2315 	if(groupOrder == NULL)
2316 		return FALSE;
2317 
2318 	for(i =0; i<FEATDEF_ANY; ++i)
2319 	{
2320 		if(groupOrder[i] == group_num)
2321 		{
2322 			if(i == FEATDEF_GENE || i == FEATDEF_mRNA || i == FEATDEF_CDS)
2323 				return TRUE;
2324 		}
2325 	}
2326 	return FALSE;
2327 }
2328 
2329 
fnp_from_same_annot(FeatNodePtr fnp,CharPtr annot_db)2330 static Boolean fnp_from_same_annot(FeatNodePtr fnp, CharPtr annot_db)
2331 {
2332 	if(annot_db[0] == '\0')
2333 		return (fnp->annotDB[0] == '\0');
2334 	else
2335 		return (StringCmp(fnp->annotDB, annot_db) ==0);
2336 }
2337 
group_feature_by_annot_label(ValNodePtr PNTR g_node,CharPtr annot_db)2338 static ValNodePtr group_feature_by_annot_label(ValNodePtr PNTR g_node, CharPtr annot_db)
2339 {
2340 	ValNodePtr list = NULL;
2341 	FeatNodePtr fnp;
2342 	ValNodePtr curr, next, prev = NULL;
2343 
2344 	if(g_node == NULL || *g_node == NULL)
2345 		return NULL;
2346 
2347 	curr = *g_node;
2348 	fnp = curr->data.ptrvalue;
2349 	if(fnp == NULL)
2350 		return NULL;
2351 	if(fnp->annotDB[0] == '\0')
2352 		annot_db[0] = '\0';
2353 	else
2354 		StringCpy(annot_db, fnp->annotDB);
2355 
2356 	while(curr)
2357 	{
2358 		next = curr->next;
2359 		fnp = curr->data.ptrvalue;
2360 		if(fnp_from_same_annot(fnp, annot_db))
2361 		{
2362 			if(prev == NULL)
2363 				*g_node = next;
2364 			else
2365 				prev->next = next;
2366 			curr->next = NULL;
2367 			ValNodeLink(&list, curr);
2368 		}
2369 		else
2370 			prev = curr;
2371 		curr = next;
2372 	}
2373 
2374 	return list;
2375 }
2376 
AddAnnotGroup(Int4 left,Int4 top,Int4 right,Int4 bottom,Int2 order,CharPtr annot_db,Uint4 itemID,SegmenT seg)2377 static void AddAnnotGroup(Int4 left, Int4 top, Int4 right, Int4 bottom, Int2 order, CharPtr annot_db, Uint4 itemID, SegmenT seg)
2378 {
2379 	Uint1Ptr color;
2380 	Int4 center;
2381 
2382 	color = get_seg_color(order);
2383 	AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, 0);
2384 
2385 	/*need to draw the rectangle line by line. Otherwise, the segments
2386 	will be incorrect*/
2387 	AddLine(seg, left, top, right, top, FALSE, itemID);
2388 	AddLine(seg, left, bottom, right, bottom, FALSE, itemID);
2389 	AddLine(seg, left, top, left, bottom, FALSE, itemID);
2390 	AddLine(seg, right, top, right, bottom, FALSE, itemID);
2391 
2392 	if(annot_db != NULL && annot_db[0] != '\0')
2393 	{
2394 		AddAttribute (seg, COLOR_ATT, BLACK_COLOR, 0, 0, 0, 0);
2395 		center = (left + right)/2;
2396 		AddTextLabel(seg, center, top, annot_db, programFont, 0, MIDDLE_CENTER, itemID);
2397 	}
2398 }
2399 
2400 
2401 
is_featnode_lod_score(ValNodePtr fnp_list)2402 static Boolean is_featnode_lod_score (ValNodePtr fnp_list)
2403 {
2404 	FeatNodePtr fnp;
2405 
2406 	while(fnp_list)
2407 	{
2408 		if(fnp_list->choice == OBJ_SEQFEAT || fnp_list->choice == OBJ_BIOSEQ_MAPFEAT)
2409 		{
2410 			fnp = fnp_list->data.ptrvalue;
2411 			if(fnp != NULL)
2412 			{
2413 				if((fnp->extra_data) & EXTRA_LOD_SCORE)
2414 					return TRUE;
2415 				else
2416 					return FALSE;
2417 			}
2418 		}
2419 
2420 		fnp_list = fnp_list->next;
2421 	}
2422 
2423 	return FALSE;
2424 }
2425 
2426 
GetLodScoreBitColor(Uint1 bit_val)2427 static Uint1Ptr GetLodScoreBitColor(Uint1 bit_val)
2428 {
2429 	switch(bit_val)
2430 	{
2431 		case 1:
2432 			return BLUE_COLOR;
2433 		case 2:
2434 			return CYAN_COLOR;
2435 		case 3:
2436 			return GREEN_COLOR;
2437 		case 4:
2438 			return YELLOW_COLOR;
2439 		case 5:
2440 			return MAGENTA_COLOR;
2441 		case 6:
2442 			return RED_COLOR;
2443 		default:
2444 			return BLACK_COLOR;
2445 	}
2446 }
2447 
DrawLODScore(ValNodePtr t_node,SegmenT seg,Int4 scale,Int4 top)2448 static Int4 DrawLODScore(ValNodePtr t_node, SegmenT seg, Int4 scale, Int4 top)
2449 {
2450 	Int4 height;
2451 	FeatNodePtr fnp;
2452 	Uint1Ptr color;
2453 	Int4 space;
2454 
2455 	height = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT);
2456 	space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
2457 	top -= space;
2458 
2459 	while(t_node)
2460 	{
2461 		fnp = t_node->data.ptrvalue;
2462 		if(fnp != NULL)
2463 		{
2464 			color = GetLodScoreBitColor((Uint1)(fnp->bin_order));
2465 			AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, 0);
2466 			AddRectangle (seg, fnp->extremes.left, top,
2467 				fnp->extremes.right, top-height, FALSE, TRUE, 0);
2468 		}
2469 
2470 		t_node = t_node->next;
2471 	}
2472 
2473 	return (top - space - height);
2474 }
2475 
2476 
DrawFeatureWithAnnot(ValNodePtr PNTR t_head,Int4 top,Int4 scale,Boolean flat,Int4 group_num,Boolean order_group,Int4 left,Int4 right,GeneDataPtr gdata,SegmenT seg,ValNodePtr PNTR image_list)2477 static Int4 DrawFeatureWithAnnot(ValNodePtr PNTR t_head, Int4 top, Int4 scale, Boolean flat, Int4 group_num, Boolean order_group, Int4 left, Int4 right, GeneDataPtr gdata, SegmenT seg, ValNodePtr PNTR image_list)
2478 {
2479 	Char annot_db[100];
2480 	Int4 g_top = 0, g_bottom;
2481 	Int4 group_font_height;
2482 	Boolean draw_annot_group;
2483 	Int2 annot_order;
2484 	ValNodePtr t_node;
2485 
2486 	SelectFont(programFont);
2487 	group_font_height = FontHeight();
2488 
2489 	annot_order = 0;
2490 	while((t_node = group_feature_by_annot_label(t_head, annot_db)) != NULL)
2491 	{
2492 		if(*t_head  == NULL && annot_order == 0 && annot_db[0] == '\0')
2493 			draw_annot_group = FALSE;
2494 		else
2495 			draw_annot_group = TRUE;
2496 		if(draw_annot_group )
2497 		{
2498 			if(annot_db[0] == '\0')
2499 				g_top = top;
2500 			else
2501 			{
2502 				top -= group_font_height;
2503 				g_top = top + group_font_height/2;
2504 			}
2505 		}
2506 		if(is_featnode_lod_score (t_node))
2507 			top = DrawLODScore(t_node, seg, scale, top);
2508 		else
2509 		{
2510 			if(flat)
2511 			{
2512 				top = LayoutNodeFlat(&t_node, scale, top, UPPER_LABEL, TRUE);
2513 				if(image_list != NULL)
2514 					load_align_label_rectangle(t_node, image_list, scale, TRUE);
2515 				DrawFlatNode(t_node, seg, UPPER_LABEL, scale, gdata);
2516 			}
2517 			else
2518 			{
2519 				if(order_group)
2520 					/* GroupFeatNode(&t_node); */
2521 					t_node = OrderCdsmRNA(&t_node);
2522 				else
2523 					t_node= SortFeatNode(t_node, NULL, NULL);
2524 				top = DrawOneFeatNode(t_node, top, seg, scale, (Int2)group_num, gdata, image_list);
2525 			}
2526 		}
2527 		t_node= FreeFeatureList(t_node);
2528 		g_bottom = top;
2529 
2530 		if(draw_annot_group)
2531 		{
2532 			g_bottom -= group_font_height/2;
2533 			AddAnnotGroup(left, g_top, right, g_bottom, annot_order, annot_db, 0, seg);
2534 			top = g_bottom;
2535 		}
2536 		++annot_order;
2537 	}
2538 
2539 	return top;
2540 }
2541 
2542 /***********************************************************************
2543 *
2544 *	DrawFeatures(features, mpp, pic, flat, simple, compact,
2545 *	scale)
2546 *
2547 *	Draw the features in the a sequence
2548 *	features: the FeatNdoe contains the features
2549 *	mpp: the graphic position of the current sequence
2550 *	pic: the drawing segment
2551 *	flat: if TRUE, stack features on top
2552 *	simple: if TRUE, draw the feature intervals as line
2553 *	compact: if TRUE, does not distinguish subtype of different features
2554 *	scale: the maximum scale for drawing
2555 *       image_list: the list of AlignRect to store the image information
2556 *
2557 *********************************************************************/
DrawFeatures(ValNodePtr g_node,MapPosPtr mpp,SegmenT pic,Boolean flat,Uint1Ptr featureOrder,Uint1Ptr groupOrder,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR image_list)2558 Boolean DrawFeatures(ValNodePtr g_node, MapPosPtr mpp, SegmenT pic, Boolean flat, Uint1Ptr featureOrder, Uint1Ptr groupOrder, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR image_list)
2559 {
2560 	ValNodePtr t_node, t_head;
2561 	Int4 top;
2562 	Int4 left, right;
2563 	Int2 entityID;
2564 	SegmenT seg;
2565 	Uint1 i, j, k, maxGroup;
2566 	Boolean is_end = FALSE;
2567 	Boolean order_group;	/*need to show the order of the group*/
2568 
2569 	if(g_node == NULL)
2570 		return FALSE;
2571 	left = mpp->left;
2572 	right = mpp->right;
2573 	top = mpp->bottom;
2574 	entityID = mpp->entityID;
2575 	seg = CreateSegment(pic, OBJ_SEQFEAT, 0);
2576 
2577 	if(flat)	/*show the features first*/
2578 	{
2579 		mpp->bottom = DrawFeatureWithAnnot(&g_node, top, scale, TRUE, 0, FALSE, left, right, gdata, seg, image_list);
2580 	}
2581 	else
2582 	{
2583 		maxGroup= 0;
2584 		for(k = 0; k<FEATDEF_ANY; ++k)
2585 			maxGroup = MAX(maxGroup, groupOrder[k]);
2586 
2587 		is_end = FALSE;
2588 		order_group = FALSE;
2589 
2590 		for(k =1; k<=maxGroup && !is_end; ++k)
2591 		{
2592 			order_group = ck_ordered_group(k, groupOrder);
2593 			t_head = NULL;
2594 			for(i =1; i<FEATDEF_ANY && !is_end; ++i)	/*this is the order of features*/
2595 			{
2596 				for(j = 1; j<FEATDEF_ANY && !is_end; ++j)
2597 				{
2598 					if(groupOrder[j] == k && featureOrder[j] == i)
2599 					{
2600 						t_node = extract_node_list(&g_node, OBJ_SEQFEAT, 0, j, ALL_LABEL);
2601 						if(t_node != NULL)
2602 						{
2603 							ValNodeLink(&t_head, t_node);
2604 							is_end = (g_node == NULL);
2605 						}
2606 					}
2607 				}
2608 			}
2609 
2610 			top = DrawFeatureWithAnnot(&t_head, top, scale, FALSE, k,order_group, left, right, gdata, seg, image_list);
2611 		}
2612 		mpp->bottom = top;
2613 		if(g_node != NULL)
2614 			FreeFeatureList(g_node);
2615 	}
2616 
2617 	return TRUE;
2618 }
2619 
2620 
2621 
DrawHistory(ValNodePtr aligns,MapPosPtr mpp,Int4 seq_label_len,SegmenT pic,Int4 scale,ValNodePtr PNTR image_list)2622 Boolean DrawHistory(ValNodePtr aligns, MapPosPtr mpp, Int4 seq_label_len, SegmenT pic, Int4 scale, ValNodePtr PNTR image_list)
2623 {
2624 
2625 	Boolean retval;
2626 	Uint1 label_align;
2627 	Int4 left, right;
2628 	Int4 offset;
2629 
2630 	if(aligns)
2631 	{
2632 		(mpp->bottom) -= 20;
2633 
2634 		offset = scale * (MAX(seq_label_len, 8));
2635 		label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
2636 
2637 		left = mpp->left;
2638 		right = mpp->right;
2639 		switch(label_align)
2640 		{
2641 			case MSM_LABEL_RIGHT:
2642 				left -= (8 * scale);
2643 				right += offset;
2644 				break;
2645 
2646 			case MSM_LABEL_TOP:
2647 			case MSM_LABEL_BOTTOM:
2648 				left -= (8*8*scale);
2649 				right += (8*8*scale);
2650 				break;
2651 
2652 			case MSM_LABEL_LEFT:
2653 				left -=offset;
2654 				right += (8 * scale);	/*8 is the size of a symbol*/
2655 				break;
2656 
2657 			default:
2658 				break;
2659 		}
2660 		retval = DrawMPAlignment(aligns, left, right, NULL, mpp->entityID, scale, &(mpp->bottom), MSM_SEQHIST, FALSE, pic);
2661 		if(image_list != NULL)
2662 			load_align_label_rectangle (aligns, image_list, scale, FALSE);
2663 		FreeAlignNode(aligns);
2664 		return retval;
2665 	}
2666 	else
2667 		return FALSE;
2668 }
2669 
2670 
get_next_ypos(MapLayoutPtr mlp,Int4Ptr top)2671 static MapLayoutPtr get_next_ypos(MapLayoutPtr mlp, Int4Ptr top)
2672 {
2673 	MapPosPtr mpp;
2674 
2675 	if(mlp == NULL)
2676 	{
2677 		*top = -20;
2678 		return NULL;
2679 	}
2680 	else
2681 	{
2682 		while(mlp->next != NULL)
2683 			mlp = mlp->next;
2684 		mpp = mlp->data.ptrvalue;
2685 		*top = mpp->bottom -MAX(10, GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT));
2686 		return mlp;
2687 	}
2688 }
2689 
2690 
2691 
set_seq_collect_option(CollectSeqOptionPtr csop,Int4 scale)2692 static Boolean set_seq_collect_option(CollectSeqOptionPtr csop, Int4 scale)
2693 {
2694 	Int4 topstyle;
2695 	Int4 ends;
2696 	Int2 i;
2697 
2698 	if(csop == NULL || scale <= 0)
2699 		return FALSE;
2700 
2701 	topstyle = GetMuskCParam(MSM_TOPSTYLE, 0, MSM_STYLE);
2702 
2703 	/*collect the features, maps, and features*/
2704 	csop->seglevels = (topstyle & MSM_SEGMENTS) ? 1:0;
2705 	ends = GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE);
2706 	csop->nointerval = (ends < scale);
2707 	csop->slabel_format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
2708 	for(i =0; i<FEATDEF_ANY; ++i)
2709 		csop->flabel_format[i] = (Uint1)GetMuskCParam(i, MSM_FLABEL, MSM_STYLE);
2710 	csop->label_size = (Int2)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_NUM);
2711 	csop->filter_level = 0;
2712 
2713 	for( i =0; i<FEATDEF_ANY; ++i)	/*for checking the features to load*/
2714 		csop->features[i] = (GetMuskCParam(i, MSM_FORDER, MSM_NUM) !=0);
2715 
2716 	return TRUE;
2717 }
2718 
2719 
2720 /*add the label to draw the sequence*/
add_seq_label_for_map(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic)2721 static Int4 add_seq_label_for_map(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic)
2722 {
2723 	ValNodePtr c_node;
2724 	FeatNodePtr fnp;
2725 	FonT font;
2726 	Int4 c_val;
2727 	Uint1 label_color[3];
2728 	SegmenT seg, pseg;
2729 	Uint1 label_align;
2730 	Int4 label_len;
2731 
2732 	label_len = 0;
2733 	c_node = extract_node_list(features, OBJ_BIOSEQ, mpp->entityID, 0, ALL_LABEL);
2734 	if(c_node == NULL)
2735 		return 0;
2736 	fnp = c_node->data.ptrvalue;
2737 
2738 	if(fnp->label != NULL)
2739 	{
2740 
2741 		font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_FONT);
2742 			SelectFont(font);
2743 
2744 		label_len = StringWidth(fnp->label);
2745 		label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
2746 		if(label_align != MSM_LABEL_RIGHT)
2747 			label_align = MSM_LABEL_LEFT;
2748 		c_val = GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_COLOR);
2749 		convert_color(c_val, label_color);
2750 		pseg = CreateSegment(pic, OBJ_BIOSEQ, 0);
2751 		seg = CreateSegment(pseg, mpp->entityID, 0);
2752 		AddAttribute (seg, COLOR_ATT, &label_color[0], 0, 0, 0, 0);
2753 
2754 		AddLabelWithAlign(seg, label_align, mpp->left, mpp->left, mpp->seq_top, mpp->seq_bottom, fnp->label, font, fnp->itemID);
2755 	}
2756 	FreeFeatureList(c_node);
2757 	return label_len;
2758 }
2759 
2760 
set_lolli_pop_feature(Uint1Ptr l_feature)2761 static void set_lolli_pop_feature(Uint1Ptr l_feature)
2762 {
2763 	Int2 i;
2764 	Int4 segstyle;
2765 
2766 	for(i =0; i<FEATDEF_ANY; ++i)
2767 	{
2768 		segstyle = GetMuskCParam(i, MSM_SEGMENT, MSM_STYLE);
2769 		switch (segstyle & MSM_SEG_FORM)
2770 		{
2771 			case MSM_SEG_SYM_RECT:
2772 			case MSM_SEG_SYM_DIAMOND:
2773 			case MSM_SEG_SYM_OVAL:
2774 			case MSM_SEG_SYM_TRIANGLE:
2775 				l_feature[i] = TRUE;
2776 				break;
2777 			default:
2778 				l_feature[i]= FALSE;
2779 		}
2780 	}
2781 }
2782 
load_feature_class(ValNodePtr PNTR type_list,Int2 _class)2783 static void load_feature_class(ValNodePtr PNTR type_list, Int2 _class)
2784 {
2785 	ValNodePtr curr;
2786 
2787 	for(curr = *type_list; curr != NULL; curr = curr->next)
2788 	{
2789 		if(curr->data.intvalue == (Int4)_class)
2790 			return;
2791 	}
2792 	ValNodeAddInt(type_list, 0, (Int4)_class);
2793 }
2794 
2795 /*******************************************************************
2796 *
2797 *	from the list of FeatNode, load the feature types contained
2798 *	for this seq-loc. It will be used to draw the legend
2799 *
2800 *******************************************************************/
load_feature_type(ValNodePtr fnp_list,ValNodePtr PNTR type_list)2801 static void load_feature_type (ValNodePtr fnp_list, ValNodePtr PNTR type_list)
2802 {
2803 	FeatNodePtr fnp;
2804 	Int2 _class;
2805 
2806 	if(type_list == NULL)
2807 		return;
2808 	while(fnp_list)
2809 	{
2810 		if(fnp_list->choice == OBJ_SEQFEAT)
2811 		{
2812 			fnp = fnp_list->data.ptrvalue;
2813 			if(fnp != NULL)
2814 			{
2815 				_class = get_current_class(fnp);
2816 				load_feature_class(type_list, _class);
2817 			}
2818 		}
2819 
2820 		fnp_list = fnp_list->next;
2821 	}
2822 }
2823 
2824 
2825 
2826 /*********************************************************************
2827 *
2828 *	from the list of AlignNode, extract all the alignments
2829 *	that were considered as the bins of the FISH maps
2830 *	since the alignment of the FISH map is displayed at the
2831 *	top, those were extracted at the first
2832 *
2833 *********************************************************************/
extract_fish_align(ValNodePtr PNTR anp_list)2834 static ValNodePtr extract_fish_align(ValNodePtr PNTR anp_list)
2835 {
2836 	ValNodePtr curr, prev, next;
2837 	ValNodePtr fish_list;
2838 	AnnotInfoPtr info;
2839 	AlignNodePtr anp;
2840 	Boolean is_fish;
2841 
2842 	if(*anp_list == NULL)
2843 		return NULL;
2844 	fish_list = NULL;
2845 	prev = NULL;
2846 	curr = *anp_list;
2847 
2848 	is_fish = FALSE;
2849 	while(curr)
2850 	{
2851 		next = curr->next;
2852 		if(curr->choice == OBJ_SEQANNOT)
2853 		{
2854 			info = (AnnotInfoPtr)(curr->data.ptrvalue);
2855 			is_fish = info->is_fish_align;
2856 		}
2857 		else
2858 		{
2859 			anp = curr->data.ptrvalue;
2860 			if(is_fish)
2861 				anp->label = MemFree(anp->label);
2862 		}
2863 		if(is_fish)
2864 		{
2865 			if(prev == NULL)
2866 				*anp_list = next;
2867 			else
2868 				prev->next = next;
2869 			curr->next = NULL;
2870 			if(curr->choice == OBJ_SEQANNOT)
2871 				FreeAlignNode(curr);
2872 			else
2873 				ValNodeLink(&fish_list, curr);
2874 		}
2875 		else
2876 			prev = curr;
2877 		curr = next;
2878 	}
2879 
2880 	return fish_list;
2881 }
2882 
2883 
add_fish_align(Int4 top,Uint2 entityID,ValNodePtr fish_align,Int4 scale,SegmenT pic)2884 static Int4 add_fish_align (Int4 top, Uint2 entityID, ValNodePtr fish_align,
2885 	Int4 scale, SegmenT pic)
2886 {
2887 	Int4 bottom;
2888 	SegmenT pseg, seg;
2889 	AlignNodePtr anp;
2890 	Int4 middle;
2891 	ValNodePtr curr;
2892 	Int4 space = 4;
2893 	Int4Ptr y_pos;
2894 	Int2 num;
2895 	Int4 line;
2896 
2897 	num = get_vnp_num(fish_align);
2898 	y_pos = MemNew((size_t)(2*num) * sizeof(Int4));
2899 	for(curr = fish_align; curr != NULL; curr = curr->next)
2900 	{
2901 		anp = curr->data.ptrvalue;
2902 		if(anp->extremes.right - anp->extremes.left >= 5* scale)
2903 			anp->line = find_f_pos(anp->extremes.left,
2904 				anp->extremes.right, y_pos, scale, num);
2905 	}
2906 	MemFree(y_pos);
2907 
2908 							/* 1 is the pen-width */
2909 	pseg = CreateSegment(pic, OBJ_SEQALIGN, 0);
2910 	seg = CreateSegment(pseg, entityID, 0);
2911 
2912 	AddAttribute (seg, COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
2913 	top -= 8;
2914 	bottom = top;
2915 	while(fish_align)
2916 	{
2917 		anp = fish_align->data.ptrvalue;
2918 		if(anp->extremes.right - anp->extremes.left >= 5* scale)
2919 		{
2920 			line = top - space * (anp->line +1);
2921 			bottom = MIN(bottom, line);
2922 			AddLine(seg, anp->extremes.left, line, anp->extremes.right,
2923 				line, FALSE, anp->itemID);
2924 			middle = (anp->extremes.left + anp->extremes.right)/2;
2925 			AddLine(seg, middle, line, middle, top, FALSE, anp->itemID);
2926 			AddSymbol(seg, middle, top, UP_TRIANGLE_SYMBOL, TRUE, UPPER_CENTER, anp->itemID);
2927 		}
2928 		fish_align = fish_align->next;
2929 	}
2930 
2931 	return bottom-4;
2932 }
2933 
extract_sts_search_node(ValNodePtr PNTR features,ValNodePtr PNTR g_node)2934 static void extract_sts_search_node(ValNodePtr PNTR features, ValNodePtr PNTR g_node)
2935 {
2936 	ValNodePtr curr, prev, next;
2937 	FeatNodePtr fnp;
2938 	ValNodePtr g_prev;
2939 	Boolean found;
2940 
2941 	if(features == NULL || *features == NULL)
2942 		return;
2943 	g_prev = NULL;
2944 	if(*g_node != NULL)
2945 	{
2946 		g_prev = *g_node;
2947 		while(g_prev->next != NULL)
2948 			g_prev = g_prev->next;
2949 	}
2950 
2951 	curr = *features;
2952 	prev = NULL;
2953 	while(curr)
2954 	{
2955 		next = curr->next;
2956 		fnp = curr->data.ptrvalue;
2957 		found = FALSE;
2958 		if(fnp->annotDB[0] != '\0')
2959 		{
2960 			if(StringCmp(fnp->annotDB, "STS Search") == 0)
2961 			{
2962 				curr->next = NULL;
2963 				if(g_prev == NULL)
2964 					*g_node = curr;
2965 				else
2966 					g_prev->next = curr;
2967 				g_prev = curr;
2968 
2969 				if(prev == NULL)
2970 					*features = next;
2971 				else
2972 					prev->next = next;
2973 				found = TRUE;
2974 			}
2975 		}
2976 		if(!found)
2977 			prev = curr;
2978 		curr = next;
2979 	}
2980 }
2981 
2982 
2983 /**********************************************************************
2984 *
2985 *	DrawOneSeqLoc(slp, left, scale, pic, mlp, gdata, priority)
2986 *	draw the current Seq-loc picture
2987 *
2988 *   slp:   the location on a Sequence, can be a list of Seq-loc for a
2989 *          circular molecule
2990 *   left:  the leftmost position on the graph
2991 *   scale: the scale for the current picture
2992 *   pic:   the current picture
2993 *   mlp:   to obtain the layout information
2994 *   gdata: the selected gene symbols for display
2995 *   priority: the priority of search for the current sequence
2996 *   ftype_list: return a list of type of features for the current
2997 *   Seq-loc. This is going to be used for drawing the legend
2998 *   image_list: the list to store the image mapping information
2999 *   align_num: the top number of alignment for display
3000 *
3001 ***********************************************************************/
DrawOneSeqLoc(SeqLocPtr slp,Int4 left,Int4 scale,SegmenT pic,MapLayoutPtr PNTR mlp,GeneDataPtr gdata,Uint2 priority,ValNodePtr PNTR ftype_list,ValNodePtr PNTR image_list,Boolean forceSeglevelsTo1,ValNodePtr extraEntityList)3002 static Boolean DrawOneSeqLoc(SeqLocPtr slp, Int4 left, Int4 scale, SegmenT pic, MapLayoutPtr PNTR mlp,
3003 GeneDataPtr gdata, Uint2 priority, ValNodePtr PNTR ftype_list, ValNodePtr PNTR image_list,
3004 Boolean forceSeglevelsTo1, ValNodePtr extraEntityList)
3005 {
3006 	ValNodePtr aligns = NULL, features = NULL;
3007 	ValNodePtr g_node;
3008 	Uint2 entityID;
3009 	Boolean ends;
3010 	CollectSeqOption cs_option;
3011 	CollectAlignOption ca_option;
3012 	SeqIdPtr sip;
3013 	BioseqPtr bsp;
3014 	Uint1 bsptype;
3015 	Char buf[41];
3016 	Int2 i;
3017 	MapPosPtr mpp;
3018 	Int4 top;
3019 	Int4 topstyle;
3020 	Boolean show_seq_label = TRUE;	/*show the label of a sequence*/
3021 	Boolean is_raw_seq;	/*is it a raw sequence*/
3022 	Boolean show_segment = TRUE;	/*draw each segments in a segmented sequence?*/
3023 	Boolean is_aa;
3024 	SeqIdPtr maybe_mapid;	/*a possible map-id*/
3025 	Boolean is_map;
3026 
3027 	Uint1 featureOrder[FEATDEF_ANY];
3028 	Uint1 groupOrder[FEATDEF_ANY];
3029 	Boolean lolli_feature[FEATDEF_ANY]; /*identify the lollipop features*/
3030 	Int4 groupNum;
3031 	Int4 top_ends;
3032 	Int4 seq_label_len;
3033 	SeqIntPtr sint;
3034 	Boolean has_align;
3035 	ValNodePtr fish_align;
3036 	Int4 fish_top;
3037 	ValNodePtr cyto_node;
3038 	ValNodePtr vnp1, vnp2;
3039 	DeltaSeqPtr dsp;
3040 	SeqLocPtr loc;
3041 
3042 
3043 	if(slp == NULL || pic == NULL || scale <=0)
3044 		return FALSE;
3045 
3046 	/*set up the option for collecting sequences and features*/
3047 	if(!set_seq_collect_option(&cs_option, scale))
3048 		return FALSE;
3049 	ends = cs_option.nointerval;	/*only show the two-ends of a feature*/
3050 
3051 	/*fetch the current Bioseq*/
3052 	sip = SeqLocId(slp);
3053 	bsp = BioseqLockById(sip);
3054 	if(bsp == NULL)
3055 	{
3056 		SeqIdWrite(sip, buf, PRINTID_TEXTID_ACCESSION, 40);
3057 		Message(MSG_ERROR, "fail to get the sequence %s", buf);
3058 		return FALSE;
3059 	}
3060 	/* adjust the interval */
3061 	if(slp->choice == SEQLOC_INT)
3062 	{
3063 		sint = slp->data.ptrvalue;
3064 		if(sint->from < 0)
3065 			sint->from = 0;
3066 		if(sint->to <0 || sint->to > bsp->length-1)
3067 			sint->to = bsp->length-1;
3068 	}
3069 	entityID = ObjMgrGetEntityIDForPointer((Pointer)bsp);
3070 	if(entityID == 0)
3071 	{
3072 		BioseqUnlock(bsp);
3073 		Message(MSG_ERROR, "Fail to find the entityID");
3074 		return FALSE;
3075 	}
3076 	if(bsp->repr == Seq_repr_seg)
3077 		maybe_mapid = figure_map_seqid((SeqLocPtr)(bsp->seq_ext));
3078 	else if (bsp->repr == Seq_repr_delta && bsp->seq_ext_type == 4)
3079 	{
3080 		dsp = (DeltaSeqPtr) bsp->seq_ext;
3081 		loc = DeltaSeqsToSeqLocs (dsp);
3082 		maybe_mapid = figure_map_seqid(loc);
3083 		SeqLocFree (loc);
3084 	}
3085 	else
3086 		maybe_mapid = NULL;
3087 
3088 	if(bsp->repr == Seq_repr_seg || bsp->repr == Seq_repr_delta)
3089 	{
3090 		/* cs_option.seglevels = 0; */
3091 		/* cs_option.seglevels = 1; */
3092 		if (forceSeglevelsTo1) {
3093 			cs_option.seglevels = 1;
3094 		} else
3095 			if(BioseqHasFeature(bsp))
3096 		{
3097 			if(maybe_mapid !=NULL)
3098 				cs_option.seglevels = 0;
3099 			if(!BioseqHasLandMark(bsp))
3100 				cs_option.seglevels = 0;
3101 			if(cs_option.seglevels == 1)
3102 				cs_option.filter_level = 1;
3103 		}
3104 		else
3105 			cs_option.seglevels = 1;
3106 	}
3107 	else
3108 		cs_option.seglevels = 0;
3109 
3110 
3111 
3112 	/*collecting the features + sequence segments*/
3113 	bsptype = get_Bioseq_type(bsp);
3114 	cs_option.bsp_type = bsptype;
3115 	is_aa = (bsp->mol == Seq_mol_aa);
3116 	features  = CollectItemForSeqLocEx(slp, entityID, left, is_aa, maybe_mapid, &cs_option, gdata, priority, forceSeglevelsTo1);
3117 	for (vnp1 = extraEntityList; vnp1 != NULL; vnp1 = vnp1->next) {
3118 	  if ((Uint2) (vnp1->data.intvalue) != entityID) {
3119 	    vnp2  = CollectItemForSeqLocEx(slp, (Uint2) (vnp1->data.intvalue), left, is_aa, maybe_mapid, &cs_option, gdata, priority, forceSeglevelsTo1);
3120 	    ValNodeLink (&features, vnp2);
3121 	  }
3122 	}
3123 	if(features == NULL)
3124 	{
3125 		return FALSE;
3126 	}
3127 	/*load the type of the features to draw the legend for the features*/
3128 	load_feature_type (features, ftype_list);
3129 
3130 	/*collecting the history*/
3131 	topstyle = GetMuskCParam(MSM_TOPSTYLE, 0, MSM_STYLE);
3132 	has_align = FALSE;
3133 	if(topstyle & MSM_HISTORY)
3134 	{
3135 		set_option_for_collect_align(&ca_option, cs_option.label_size, COLLECT_HISTORY);
3136 		ca_option.only_history = FALSE;
3137 		ca_option.map_insert = TRUE;
3138 		ca_option.slabel_format = cs_option.slabel_format;
3139 		ca_option.nointerval = cs_option.nointerval;
3140 		ca_option.no_sort = FALSE;
3141 		ca_option.flat_insert = FALSE;
3142 		aligns = collect_anpnode_with_option(&ca_option, slp, entityID, COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
3143 	    for (vnp1 = extraEntityList; vnp1 != NULL; vnp1 = vnp1->next) {
3144 	      if ((Uint2) (vnp1->data.intvalue) != entityID) {
3145 		    vnp2 = collect_anpnode_with_option(&ca_option, slp, (Uint2) (vnp1->data.intvalue), COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
3146 	        ValNodeLink (&aligns, vnp2);
3147 	      }
3148 	    }
3149 		has_align = alignode_has_alignments(aligns);
3150 		if(has_align)
3151 		{
3152 			show_segment = FALSE;
3153 			/*for the alignment of STSs in SegMap*/
3154 			CollectSegMapSTSAlign(entityID, aligns, slp, left);
3155 		}
3156 	}
3157 	else
3158 		show_segment = FALSE;
3159 
3160 
3161 
3162 	/*set the layout for the current Seq-loc*/
3163 	get_next_ypos(*mlp, &top);
3164 	mpp = MemNew(sizeof(MapPos));
3165 	mpp->slp = slp;
3166 	mpp->left = left;
3167 	mpp->right = left + slp_list_len(slp);
3168 	mpp->top  = top;
3169 	mpp->bottom = top;
3170 	mpp->seq_top = top;
3171 	mpp->seq_bottom = top;
3172 	mpp->entityID = entityID;
3173 
3174 
3175 	/*display the alignment to the FISH map first */
3176 	fish_top = 99999;
3177 	if(get_FISH_align(bsp) != NULL && has_align)
3178 	{
3179 		fish_align = extract_fish_align(&aligns);
3180 		if(fish_align != NULL)
3181 		{
3182 			fish_top = top;
3183 			mpp->top = add_fish_align (top, entityID, fish_align, scale, pic);
3184 			mpp->bottom = mpp->top;
3185 			mpp->seq_top = mpp->top;
3186 			mpp->seq_bottom = mpp->top;
3187 			mpp->bottom = mpp->top;
3188 			FreeAlignNode(fish_align);
3189 		}
3190 	}
3191 
3192 	/*map the feature order and group order*/
3193 	for( i =0; i<FEATDEF_ANY; ++i)	/*for checking the features to load*/
3194 	{
3195 		featureOrder[i] = (Uint1)GetMuskCParam(i, MSM_FORDER, MSM_NUM);
3196 		groupNum = (Uint1)GetMuskCParam(i, MSM_FGROUP, MSM_NUM);
3197 		groupOrder[i] = (Uint1)GetMuskCParam(MSM_GROUPS, (Int2)groupNum, MSM_NUM);
3198 	}
3199 
3200 
3201 
3202 	g_node = NULL;
3203 	if(topstyle & MSM_STACKGENE)	/*draw the features on top of the sequence*/
3204 		g_node = extract_node_list(&features, OBJ_SEQFEAT, 0, 0, ALL_LABEL);
3205 	else
3206 	{
3207 
3208 		if((bsptype==SEG_SEQ && maybe_mapid == NULL)|| bsptype == RAW_SEQ)
3209 		{
3210 			set_lolli_pop_feature(lolli_feature);
3211 			g_node = extract_lollipop_feature(&features, 0, lolli_feature);
3212 		}
3213 
3214 		else
3215 		{
3216 			top_ends = GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE);
3217  			if(scale > top_ends)
3218  				g_node = extract_node_list(&features, OBJ_SEQFEAT, 0, 0, ALL_LABEL);
3219  			else
3220  				g_node = extract_lollipop_feature(&features, scale*10, NULL);
3221 
3222 			/*g_node = extract_lollipop_feature(&features, scale, NULL);*/
3223 		}
3224 	}
3225 
3226 	extract_sts_search_node(&features, &g_node);
3227 	if(g_node)
3228 		if(DrawFeatures(g_node, mpp, pic, TRUE, featureOrder, groupOrder, scale, gdata, image_list))
3229 			show_seq_label = FALSE;
3230 	mpp->seq_top = mpp->bottom;
3231 	mpp->seq_bottom = mpp->bottom;
3232 	is_map = TRUE;	/*map does not extract bioseqs*/
3233 	switch(bsptype)
3234 	{
3235 	   case GENETIC_MAP:
3236 		DrawGeneticMap(&features, mpp, pic, scale, gdata, image_list);
3237 		break;
3238 
3239 	   case PHYSICAL_MAP:
3240 		DrawPhysicalMap(&features, mpp, pic, scale, image_list);
3241 		break;
3242 
3243 	   case RESTRICTION_MAP:
3244 		DrawRestrictionMap(&features, mpp, pic, FALSE, SeqLocStrand(slp), scale);
3245 		break;
3246 
3247 	   case CYTO_MAP:
3248 		DrawCytoMap(&features, mpp, scale, pic);
3249 		break;
3250 
3251 	   default:
3252 		is_raw_seq = (bsptype == RAW_SEQ);
3253 		is_map = FALSE;
3254 		DrawSeqMap(&features, mpp, pic, scale, is_raw_seq, show_segment, image_list);
3255 		break;
3256 	}
3257 
3258 	if(is_map && bsptype != RESTRICTION_MAP)  /*need to extract from the Bioseq*/
3259 		seq_label_len = add_seq_label_for_map(&features, mpp, pic);
3260 	else
3261 		seq_label_len = 0;
3262 
3263 	/*add the label of the sequence*/
3264 
3265 
3266 	DrawHistory(aligns, mpp, seq_label_len, pic, scale, image_list);
3267 
3268 	if(bsptype == CYTO_MAP && gdata != NULL)
3269 	{
3270 		cyto_node = convert_gdata_to_featnode(gdata, mpp->slp, mpp->left);
3271 		if(cyto_node != NULL)
3272 			ValNodeLink(&features, cyto_node);
3273 	}
3274 
3275 
3276 	g_node = extract_node_list(&features, OBJ_SEQFEAT, 0, 0, ALL_LABEL);
3277 	DrawFeatures(g_node, mpp, pic, FALSE, featureOrder, groupOrder, scale, gdata, image_list);
3278 	FreeFeatureList(features);
3279 
3280 
3281 	if(fish_top != 99999)
3282 	{	/*there is a FISH mapping data */
3283 		mpp->seq_bottom = fish_top - (mpp->seq_top - mpp->seq_bottom);
3284 		mpp->seq_top = fish_top;
3285 	}
3286 	ValNodeAddPointer(mlp, 0, mpp);
3287 	BioseqUnlock(bsp);
3288 	return TRUE;
3289 
3290 }
3291 
3292 
3293 /*
3294 *	MakeCompressAlignList: Build the AlignNode for  a compact alignment
3295 *   view associated
3296 *	with a sequence
3297 *	query_bsp is the query sequence
3298 *	annot: the alignment data. If NULL, the alignment data will be extracted
3299 *			from sequence
3300 *	return the list of AlignNode
3301 */
MakeCompressAlignList(BioseqPtr query_bsp,SeqAnnotPtr annot,Uint2Ptr p_entityID)3302 ValNodePtr MakeCompressAlignList(BioseqPtr query_bsp, SeqAnnotPtr annot, Uint2Ptr p_entityID)
3303 {
3304 	SeqAnnotPtr sap;
3305 	SeqLocPtr slp;
3306 	CollectAlignOption ca_option;
3307 	CollectSeqOption cs_option;
3308 	Uint2 entityID, t_entityID;
3309 
3310 	ValNodePtr aligns = NULL, h_aligns, t_aligns;
3311 
3312 
3313 	if(query_bsp == NULL)
3314 		return NULL;
3315 
3316 	entityID = ObjMgrGetEntityIDForPointer((Pointer)query_bsp);
3317 	if(entityID == 0)
3318 	{
3319 		Message(MSG_ERROR, "Fail to find the entityID for the Bioseq");
3320 		return NULL;
3321 	}
3322 
3323 	if(!set_seq_collect_option(&cs_option, 200))
3324 		return NULL;
3325 
3326 
3327 	slp = SeqLocIntNew(0, query_bsp->length-1, 0, query_bsp->id);
3328 	set_option_for_collect_align(&ca_option, 0, COLLECT_HISTORY);
3329 	ca_option.only_history = FALSE;
3330 	ca_option.map_insert = TRUE;
3331 	ca_option.slabel_format = cs_option.slabel_format;
3332 	ca_option.nointerval = TRUE;
3333 	ca_option.no_sort = FALSE;
3334 	ca_option.flat_insert = FALSE;
3335 	ca_option.align_num = -1;
3336 	ca_option.csop = &cs_option;
3337 	aligns = collect_anpnode_with_option(&ca_option, slp, entityID, COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
3338 	if(!alignode_has_alignments(aligns))
3339 	{
3340 		FreeAlignNode(aligns);
3341 		aligns = NULL;
3342 	}
3343 
3344 	/*no alignment from the Bioseq, trying the Seq-annot*/
3345 	if(aligns == NULL)
3346 	{
3347 		for(sap = annot; sap != NULL; sap = sap->next)
3348 		{
3349 			if(sap->type == 2)
3350 			{
3351 				t_entityID = ObjMgrRegister(OBJ_SEQANNOT, (Pointer)sap);
3352 				if(t_entityID == 0)
3353 				{
3354 					Message(MSG_ERROR, "Fail to register the Seq-annot");
3355 				}
3356 				else
3357 				{
3358 					t_aligns = collect_anpnode_with_option(&ca_option, slp, t_entityID, COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, TRUE);
3359 					ValNodeLink(&aligns, t_aligns);
3360 				}
3361 				*p_entityID = t_entityID;
3362 				break;
3363 			}
3364 		}
3365 	}
3366 	else
3367 		*p_entityID = entityID;
3368 	if(aligns == NULL)
3369 	{
3370 		ErrPostEx(SEV_WARNING, 0, 0, "No alignment data");
3371 		SeqLocFree(slp);
3372 		return NULL;
3373 	}
3374 
3375 	/*collecting the alignment for the query sequence*/
3376 	cs_option.features[FEATDEF_repeat_region] = TRUE;
3377 	cs_option.features[FEATDEF_repeat_unit] = TRUE;
3378 	ca_option.show_feature = TRUE;
3379 	ca_option.nointerval = FALSE;
3380 	ca_option.label_size = cs_option.label_size;
3381 	h_aligns = collect_master_align_node(&ca_option, slp, OBJ_SEQALIGN, entityID);
3382 	SeqLocFree(slp);
3383 
3384 	ValNodeLink(&h_aligns, aligns);
3385 
3386 	return h_aligns;
3387 }
3388 
3389 
DrawCompressAlignment(ValNodePtr anp_list,SeqLocPtr m_loc,Int4 width,Int4Ptr p_scale,Int4Ptr p_maxwidth,Uint2 entityID,ValNodePtr PNTR arect_list)3390 SegmenT DrawCompressAlignment(ValNodePtr anp_list, SeqLocPtr m_loc, Int4 width, Int4Ptr p_scale, Int4Ptr p_maxwidth, Uint2 entityID, ValNodePtr PNTR arect_list)
3391 {
3392 	Int2 styleNum;
3393 	CharPtr old_style;
3394 	Int4 scale;
3395 	SegmenT pic;
3396 	ValNode vn;
3397 	Int4 max_width;
3398 	Int4 y_pos;
3399 
3400 
3401 	if(anp_list == NULL)
3402 		return NULL;
3403 	if(arect_list != NULL)
3404 		*arect_list = NULL;
3405 	vn.data.ptrvalue = m_loc;
3406 	vn.next = NULL;
3407 	max_width = CountMaxSeqLabel(&vn);
3408 	scale = FigureMaxScale(&vn, (Int2)width, max_width);
3409 	if(scale <=0)
3410 		return NULL;
3411 	pic = CreatePicture();
3412 
3413 	/*set up the sepcial style */
3414 	styleNum = GetMuskCurrentSt();
3415 	old_style = GetMuskStyleName(styleNum);
3416 	SetMuskCurrentSt("StyleX");
3417 
3418 	y_pos = 0;
3419 	DrawMPAlignment(anp_list, 0, SeqLocLen(m_loc)-1, m_loc, entityID, scale, &y_pos, MSM_SEQHIST, TRUE, pic);
3420 	if(arect_list != NULL)
3421     		load_align_label_rectangle(anp_list, arect_list, scale, FALSE);
3422 
3423 	*p_scale = scale;
3424 	*p_maxwidth = max_width;
3425 	SetMuskCurrentSt(old_style);
3426 	return pic;
3427 }
3428 
3429 
3430 /*************************************************************************
3431 *
3432 *	Label_GData(): Label the gene_data node specified by the user
3433 *
3434 *************************************************************************/
Label_GData(GeneDataPtr gdata,SeqLocPtr slp,Int4 left,Int4 top,SegmenT seg)3435 Boolean Label_GData(GeneDataPtr gdata, SeqLocPtr slp, Int4 left, Int4 top, SegmenT seg)
3436 {
3437 	SeqLocPtr c_slp;
3438 	Int4 c_left;
3439 	Boolean success = FALSE;
3440 	Int4 m_start, m_stop, t_start, t_stop;
3441 	Int4 g_pos;
3442 
3443 
3444 	if(slp == NULL ||gdata == NULL)
3445 		return FALSE;
3446 	while(gdata)
3447 	{
3448 		t_start = SeqLocStart(gdata->location);
3449 		t_stop = SeqLocStop(gdata->location);
3450 		for(c_slp = slp, c_left = left; slp!=NULL; c_slp=c_slp->next)
3451 		{
3452 			m_start = SeqLocStart(c_slp);
3453 			m_stop = SeqLocStop(c_slp);
3454 
3455 			if(!(t_start > m_stop || t_stop < m_start))
3456 			{
3457 				g_pos = MAX(0, (t_start - m_start)) + c_left;
3458 				AddSymbol(seg, g_pos, top, DIAMOND_SYMBOL, TRUE, LOWER_CENTER, 0);
3459 				success = TRUE;
3460 			}
3461 			c_left += SeqLocLen(c_slp);
3462 		}
3463 		gdata = gdata->next;
3464 	}
3465 
3466 	return TRUE;
3467 }
3468 
3469 
3470 
3471 
3472 
3473 
3474 
3475 /*************************************************************************
3476 *
3477 *	DrawVerticalAlign (align, pic, mlp)
3478 *	draw alignment among the sequences. (connecting aligned seg by line)
3479 *	align: the Seq-align which contains the alignment among sequence
3480 *	It is assumed to be a Std-seg
3481 *	pic: the drawing segment
3482 *	mlp: the list of the layout of the sequences
3483 *
3484 *************************************************************************/
3485 
draw_one_align(AlignPos ap,Int2 num,Int2 order,SegmenT seg)3486 void draw_one_align(AlignPos ap, Int2 num, Int2 order, SegmenT seg)
3487 {
3488 	Int4 x1, x2;
3489 	Int2 i;
3490 
3491 	for(i = 0; i<num-1; ++i)
3492 	{
3493 		x1 = (ABS(ap.left[i]) + ABS(ap.right[i]))/2;
3494 		x2 = (ABS(ap.left[i+1]) + ABS(ap.right[i+1]))/2;
3495 		AddLine(seg, x1, ap.top[i], x2, ap.bottom[i+1], FALSE, order);
3496 		if(ap.left[i] < 0)
3497 		{
3498 			AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLUE_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3499 			AddSymbol(seg, x1, ap.bottom[i], UP_TRIANGLE_SYMBOL, TRUE, MIDDLE_CENTER, 0);
3500 			AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3501 		}
3502 		if(ap.left[i+1] < 0)
3503 		{
3504 			AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLUE_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3505 			AddSymbol(seg, x2, ap.bottom[i], DOWN_TRIANGLE_SYMBOL, TRUE, MIDDLE_CENTER, 0);
3506 			AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3507 		}
3508 	}
3509 }
3510 
get_map_pos(MapLayoutPtr mlp,SeqIdPtr sip)3511 static MapPosPtr get_map_pos(MapLayoutPtr mlp, SeqIdPtr sip)
3512 {
3513 	MapPosPtr mpp;
3514 
3515 	while(mlp)
3516 	{
3517 		mpp = mlp->data.ptrvalue;
3518 		if(SeqIdMatch(sip, SeqLocId(mpp->slp)))
3519 			return mpp;
3520 		mlp = mlp->next;
3521 	}
3522 	return NULL;
3523 }
3524 
get_ith_arp(AlignRangePtr arp,Int2 i)3525 static AlignRangePtr get_ith_arp(AlignRangePtr arp, Int2 i)
3526 {
3527 	Int2 k = 0;
3528 
3529 	while(arp)
3530 	{
3531 		if(k == i)
3532 			return arp;
3533 		arp = arp->next;
3534 		++k;
3535 	}
3536 	return NULL;
3537 }
3538 
DrawVerticalAlign(SeqAlignPtr align,SegmenT pic,MapLayoutPtr mlp)3539 Boolean DrawVerticalAlign (SeqAlignPtr align, SegmenT pic, MapLayoutPtr mlp)
3540 {
3541 	StdSegPtr ssp;
3542 	SeqLocPtr locs;
3543 	MapLayoutPtr curr;
3544 	MapPosPtr mpp;
3545 	Int2 j;
3546 	GatherRange gr;
3547 	AlignPos ap;
3548 	SeqLoc sl_1;
3549 
3550 
3551 
3552 	sl_1.choice = SEQLOC_MIX;
3553 	sl_1.next = NULL;
3554 	j = 0;
3555 	if(align->segtype != 3)
3556 		return FALSE;
3557 	ssp= align->segs;
3558 	for(curr = mlp; curr != NULL; curr = curr->next)
3559 	{
3560 		mpp = (MapPosPtr)(curr->data.ptrvalue);
3561 		sl_1.data.ptrvalue = mpp->slp;
3562 		for(locs = ssp->loc; locs != NULL; locs = locs->next)
3563 		{
3564 			if(SeqLocOffset(&sl_1, locs, &gr, mpp->left))
3565 			{
3566 
3567 				ap.left[j] = gr.left;
3568 				ap.right[j] = gr.right;
3569 				ap.top[j] = mpp->seq_top;
3570 				ap.bottom[j] = mpp->seq_bottom;
3571 				++j;
3572 			}
3573 		}
3574 	}
3575 
3576 	if(j >1)
3577 	{
3578 		SortAlignPosition(&ap, j);
3579 		draw_one_align(ap, j, 0, pic);
3580 		return TRUE;
3581 	}
3582 	else
3583 		return FALSE;
3584 }
3585 
3586 
3587 
3588 
DrawEquivAlign(ValNodePtr e_align_list,SegmenT pic,MapLayoutPtr mlp)3589 static void DrawEquivAlign (ValNodePtr e_align_list, SegmenT pic, MapLayoutPtr mlp)
3590 {
3591 	SeqAlignPtr align;
3592 	SeqAnnotPtr annot;
3593 	Int2 type;
3594 	Uint1 my_gray_color[]={63, 63, 63};
3595 
3596 	/* AddAttribute (pic, WIDTH_ATT | COLOR_ATT, GREEN_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE); */
3597 	while(e_align_list)
3598 	{
3599 		annot = (SeqAnnotPtr)(e_align_list->data.ptrvalue);
3600 		type = GetEquivAlignType (annot);
3601 		add_attribute_pen(pic, MSM_ALIGNMENT, MSM_ALINE);
3602 		switch(type)
3603 		{
3604 			case 2:  /*it is inconsistent markers*/
3605 				AddAttribute(pic, COLOR_ATT|STYLE_ATT, RED_COLOR, DOTTED_LINE, 0, 0, 0);
3606 				break;
3607 			case 3:	/*it is unknown type*/
3608 			case 0:
3609 				AddAttribute(pic, COLOR_ATT|STYLE_ATT, CYAN_COLOR, SOLID_LINE, 0, 0, 0);
3610 				break;
3611 			case 4:  /*it is the alignment to the FISH map*/
3612 				AddAttribute(pic, COLOR_ATT|STYLE_ATT, BLACK_COLOR, SOLID_LINE, 0, 0, 0);
3613 				break;
3614 			default:
3615 				AddAttribute(pic, STYLE_ATT, 0, SOLID_LINE, 0, 0, 0);
3616 				break;
3617 		}
3618 		align = (SeqAlignPtr)(annot->data);
3619 		while(align)
3620 		{
3621 			DrawVerticalAlign (align, pic, mlp);
3622 			align = align->next;
3623 		}
3624 		e_align_list = e_align_list->next;
3625 	}
3626 }
3627 
3628 
3629 
3630 
3631 
3632 
3633 
3634 /*********************************************************************
3635 *
3636 *	DrawGenomeMap(slp_list, e_align_list, scale, mlp)
3637 *
3638 *	draw all the SeqLocs in the list and show their alignment (if any)
3639 *	slp_list: the list of Seq-locs
3640 *	e_align_list: the list of alignment among the Seq-locs
3641 *	scale: the scale for the picture
3642 *	mlp: store the layout of the current picture
3643 *	return the picture of the genome map
3644 *	ftype_list: return a list of type of features for the current
3645 *	Seq-loc. This is going to be used for drawing the legend
3646 *	image_list: the list to store the image mapping information
3647 *	align_num: number of the top alignment to show. -1 = show everything
3648 *
3649 *********************************************************************/
DrawGenomeMapEx(ValNodePtr slp_list,ValNodePtr e_align_list,Int4 scale,GeneDataPtr gdata,MapLayoutPtr PNTR mlp,ValNodePtr PNTR ftype_list,ValNodePtr PNTR image_list,Boolean forceSeglevelsTo1,ValNodePtr extraEntityList)3650 SegmenT DrawGenomeMapEx (ValNodePtr slp_list, ValNodePtr e_align_list, Int4 scale, GeneDataPtr gdata,
3651 MapLayoutPtr PNTR mlp, ValNodePtr PNTR ftype_list, ValNodePtr PNTR image_list,
3652 Boolean forceSeglevelsTo1, ValNodePtr extraEntityList)
3653 {
3654 	Boolean success = FALSE;
3655 	ValNodePtr curr;
3656 	SeqLocPtr slp;
3657 	MapLayoutPtr mlp_head= NULL;
3658 	SegmenT pic;
3659  	/* ValNodePtr t_image = NULL;  */
3660 
3661 	if(slp_list == NULL || scale <=0)
3662 		return NULL;
3663 
3664 	scale = MIN(scale, MAX_SCALE);
3665 	pic = CreatePicture();
3666 	if(ftype_list != NULL)
3667 		*ftype_list = NULL;
3668 	if(image_list != NULL)
3669 		*image_list = NULL;
3670 
3671 	for(curr = slp_list; curr !=NULL; curr = curr->next)
3672 	{
3673 		slp = curr->data.ptrvalue;
3674 		/* if(DrawOneSeqLoc(slp, 0, scale, pic, &mlp_head, gdata, (Uint2)(curr->choice), ftype_list, &t_image)) */
3675 	 	if(DrawOneSeqLoc(slp, 0, scale, pic, &mlp_head, gdata, (Uint2)(curr->choice), ftype_list,
3676 	 	                 image_list, forceSeglevelsTo1, extraEntityList))
3677 			success = TRUE;
3678 	}
3679 	/* ValNodeFreeData(t_image);  */
3680 	if(!success)
3681 	{
3682 		DeletePicture(pic);
3683 		return NULL;
3684 	}
3685 
3686 	DrawEquivAlign (e_align_list, pic, mlp_head);
3687 	if(mlp !=NULL)
3688 		*mlp = mlp_head;
3689 	else
3690 		MapLayoutFree(mlp_head);
3691 	return pic;
3692 }
3693 
DrawGenomeMap(ValNodePtr slp_list,ValNodePtr e_align_list,Int4 scale,GeneDataPtr gdata,MapLayoutPtr PNTR mlp,ValNodePtr PNTR ftype_list,ValNodePtr PNTR image_list)3694 SegmenT DrawGenomeMap (ValNodePtr slp_list, ValNodePtr e_align_list, Int4 scale, GeneDataPtr gdata, MapLayoutPtr PNTR mlp, ValNodePtr PNTR ftype_list, ValNodePtr PNTR image_list)
3695 {
3696 	return DrawGenomeMapEx (slp_list, e_align_list, scale, gdata, mlp, ftype_list, image_list, FALSE, NULL);
3697 }
3698 
3699 /**************************************************************************
3700 *
3701 *	DrawSequinMap(slp_list, sep, scale)
3702 *	return a picture with the interface defined by Jonathan K.
3703 *	slp_list: a ValNode list of Seq-loc
3704 *	sep: the Seq-entry pointer
3705 *	scale: the scale of the picture
3706 *
3707 **************************************************************************/
DrawSequinMapEx(ValNodePtr slp_list,SeqEntryPtr sep,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR ftype_list,Boolean forceSeglevelsTo1,ValNodePtr extraEntityList)3708 SegmenT DrawSequinMapEx (ValNodePtr slp_list, SeqEntryPtr sep, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR ftype_list, Boolean forceSeglevelsTo1, ValNodePtr extraEntityList)
3709 {
3710 	ValNodePtr e_align_list = NULL;
3711 	SegmenT pic;
3712 
3713 	if(slp_list == NULL || sep == NULL || scale <=0)
3714 		return NULL;
3715 
3716 	e_align_list = get_equiv_align(sep);
3717 	/*gdata = make_gene_data(g_list);*/
3718 
3719 	pic = DrawGenomeMapEx(slp_list, e_align_list, scale, gdata, NULL, ftype_list, NULL, forceSeglevelsTo1, extraEntityList);
3720 	/*GeneDataFree(gdata);*/
3721 	ValNodeFree(e_align_list);
3722 	return pic;
3723 }
3724 
DrawSequinMap(ValNodePtr slp_list,SeqEntryPtr sep,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR ftype_list)3725 SegmenT DrawSequinMap (ValNodePtr slp_list, SeqEntryPtr sep, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR ftype_list)
3726 {
3727 	return DrawSequinMapEx (slp_list, sep, scale, gdata, ftype_list, FALSE, NULL);
3728 }
3729 
load_align_option_for_graphic(CollectAlignOptionPtr caop,CollectSeqOptionPtr csop,Int4 style,Boolean flat_insert)3730 Boolean load_align_option_for_graphic(CollectAlignOptionPtr caop, CollectSeqOptionPtr csop, Int4 style, Boolean flat_insert)
3731 {
3732 	Int2 i;
3733 
3734 	if(style < MSM_SEQHIST || style > MSM_MDIM)
3735 		return FALSE;
3736 	MemSet((Pointer)caop, 0, sizeof(CollectAlignOption));
3737 	caop->graphic_offset = 0;
3738 	caop->only_history = FALSE;
3739 	caop->show_mismatch = (style == MSM_MPAIR);	/*can not show mismatch for MDIM for now*/
3740 	caop->label_size= (Int2)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_NUM);
3741 	caop->nointerval = FALSE;
3742 	caop->map_insert = (style== MSM_MPAIR || style == MSM_SEQHIST);
3743 	caop->flat_insert = (style == MSM_MPAIR && flat_insert);
3744 	caop->map_graphic = TRUE;
3745 	caop->show_feature = TRUE;
3746 	caop->slabel_format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
3747 	caop->align_num = DEFAULT_ALIGN_NUM;
3748 	/* caop->align_num = (Int4)GetMuskCParam(MSM_ALIGNMENT, MSM_NOSUBCLASS, MSM_SCALE); */
3749 
3750 	csop->seglevels = 0;
3751 	csop->nointerval = FALSE;
3752 	csop->slabel_format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
3753 	for(i =0; i<FEATDEF_ANY; ++i)
3754 		csop->flabel_format[i] = (Uint1)GetMuskCParam(i, MSM_FLABEL, MSM_STYLE);
3755 	csop->label_size = caop->label_size;
3756 	csop->filter_level = 0;
3757 	return TRUE;
3758 }
3759 
3760 
3761 
3762 /************************************************************
3763 *
3764 * collect_alignnode_from_alp(m_loc)
3765 * collect all the alignment stored as the history of the
3766 * master sequence
3767 * m_loc: the selected location of the master sequence
3768 * return a list of AlignNode
3769 *
3770 ************************************************************/
collect_alignnode_from_slp(SeqLocPtr m_loc,Uint2Ptr t_entityID,Boolean flat_insert)3771 ValNodePtr collect_alignnode_from_slp(SeqLocPtr m_loc, Uint2Ptr t_entityID, Boolean flat_insert)
3772 {
3773 	ValNodePtr anp_node;
3774 	CollectAlignOption ca_option;
3775 	CollectSeqOption cs_option;
3776 	BioseqPtr bsp;
3777 	Uint2 entityID;
3778 
3779 	if(m_loc == NULL)
3780 		return NULL;
3781 	bsp = BioseqLockById(SeqLocId(m_loc));
3782 	if(bsp == NULL)
3783 		return NULL;
3784 	entityID = ObjMgrGetEntityIDForPointer((Pointer)bsp);
3785 	if(entityID == 0)
3786 		return NULL;
3787 	if(t_entityID != NULL)
3788 		*t_entityID = entityID;
3789 	load_align_option_for_graphic(&ca_option, &cs_option, MSM_MPAIR, flat_insert);
3790 	ca_option.csop = &cs_option;
3791 	if(!BioseqHasFeature(bsp))
3792 		cs_option.seglevels = 1;
3793 	anp_node= collect_anpnode_with_option(&ca_option, m_loc, entityID, COLLECT_MP, OBJ_SEQHIST_ALIGN, NULL, NULL, FALSE);
3794 
3795 	BioseqUnlock(bsp);
3796 	return anp_node;
3797 }
3798 
3799 
3800 
3801 
3802 /************************************************************************
3803 *
3804 *
3805 ************************************************************************/
DrawSeqHistoryAlignment(SeqLocPtr m_loc,Int4 scale,ValNodePtr PNTR anp_list,Uint2Ptr seq_entityID,Boolean flat_insert)3806 SegmenT DrawSeqHistoryAlignment(SeqLocPtr m_loc, Int4 scale, ValNodePtr PNTR anp_list, Uint2Ptr seq_entityID, Boolean flat_insert)
3807 {
3808 	ValNodePtr anp_node;
3809 	SegmenT pic;
3810 	Int4 y_pos = 0;
3811 	Int4 len;
3812 	Uint2 entityID;
3813 
3814 	anp_node = collect_alignnode_from_slp(m_loc, &entityID, flat_insert);
3815 	if(anp_node == NULL)
3816 		return NULL;
3817 	pic = CreatePicture();
3818 	len = slp_list_len(m_loc);
3819 	DrawMPAlignment(anp_node, 0, len-1, m_loc, entityID, scale, &y_pos, MSM_MPAIR, FALSE, pic);
3820 
3821 	if(seq_entityID != NULL)
3822 		*seq_entityID = entityID;
3823 	if(anp_list != NULL)
3824 		*anp_list = anp_node;
3825 	else
3826 		FreeAlignNode(anp_node);
3827 	return pic;
3828 }
3829 
3830 /*draw something that looks like a folder for the un-aligned contigs in
3831   Eric Green's map
3832 */
3833 
draw_unknown_folder(SegmenT seg,Int4 left,Int4 right,Int4 y_pos,AnnotInfoPtr annot_info)3834 static Boolean draw_unknown_folder(SegmenT seg, Int4 left, Int4 right, Int4 y_pos, AnnotInfoPtr annot_info)
3835 {
3836 	Char label[101];
3837 	Int4 center, middle;
3838 	Int4 font_height;
3839 
3840 	if(annot_info->annotDB[0] == '\0')
3841 		return FALSE;
3842 	font_height = FontHeight();
3843 	middle = y_pos - font_height/2;
3844 	SelectFont(programFont);
3845 	sprintf(label, "[%s]", annot_info->annotDB);
3846 	center = (left + right)/2;
3847 
3848 	AddAttribute (seg, COLOR_ATT, YELLOW_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
3849 	AddRectangle (seg, left, y_pos, right, y_pos-font_height, FALSE, TRUE, annot_info->itemID);
3850 	AddAttribute (seg, COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
3851 	AddTextLabel(seg, center, middle, label, programFont, 0, MIDDLE_CENTER, annot_info->itemID);
3852 	return TRUE;
3853 }
3854 
3855 
get_master_alignnode_extremes(ValNodePtr anp_node,Int4Ptr m_left,Int4Ptr m_right)3856 static Boolean get_master_alignnode_extremes (ValNodePtr anp_node, Int4Ptr m_left, Int4Ptr m_right)
3857 {
3858 	AlignNodePtr anp;
3859 
3860 	while(anp_node != NULL)
3861 	{
3862 		if(anp_node->choice != OBJ_SEQANNOT)
3863 		{
3864 			anp = anp_node->data.ptrvalue;
3865 			if(anp->is_master)
3866 			{
3867 				*m_left = anp->extremes.left;
3868 				*m_right = anp->extremes.right;
3869 				return TRUE;
3870 			}
3871 		}
3872 
3873 		anp_node = anp_node->next;
3874 	}
3875 
3876 	return FALSE;
3877 }
3878 
3879 
DrawMPAlignment(ValNodePtr anp_node,Int4 left,Int4 right,SeqLocPtr m_loc,Uint2 entityID,Int4 scale,Int4Ptr cur_pos,Uint1 style,Boolean compress,SegmenT pic)3880 Boolean DrawMPAlignment(ValNodePtr anp_node, Int4 left, Int4 right, SeqLocPtr m_loc, Uint2 entityID, Int4 scale, Int4Ptr cur_pos, Uint1 style, Boolean compress, SegmenT pic)
3881 {
3882 	Int4 y_pos;
3883 	SegmenT pseg, seg;
3884 	Boolean ends = FALSE;
3885 	Int4 height, ends_scale;
3886 
3887 	Int4 g_top, g_bottom;
3888 	Int4 group_font_height;
3889 
3890 	ValNodePtr list, curr, prev, last, next;
3891 	ValNodePtr head;
3892 	AnnotInfoPtr annot_info;
3893 	Int4 space;
3894 	Int4 m_left = -1, m_right = -1;
3895 	Int4 offset;
3896 	SeqLocPtr last_loc;
3897 	SeqIntPtr sint;
3898 	Int4 len;
3899 	Boolean use_symbol_for_align;	/*for each alignment, only use
3900 					the diamond symbol to indicate
3901 					the alignment location*/
3902 
3903 
3904 	if(anp_node == NULL || pic == NULL || cur_pos == NULL)
3905 		return FALSE;
3906 	if(style > MSM_FIXED || style < MSM_SEQHIST)
3907 		return FALSE;
3908 	if(style == MSM_SEQHIST )
3909 	{
3910 		ends_scale = GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE);
3911 		if(ends_scale < scale)
3912 			ends = TRUE;
3913 	}
3914 	if(compress)
3915 		ends = TRUE;
3916 	if(ends)
3917 		height = GetMuskCParam(MSM_SEQUENCE, MSM_SEG_BORD, MSM_PENWIDTH);
3918 	else
3919 		height = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT);
3920 
3921 	y_pos = *cur_pos;
3922 	if(m_loc != NULL)
3923 		y_pos -= 40;	/*leaves enough space for drawing the ruler*/
3924 
3925 	pseg = CreateSegment(pic, anp_node->choice, 0);
3926 	seg = CreateSegment(pseg, entityID, 0);
3927 
3928 	if(!get_master_alignnode_extremes(anp_node, &m_left, &m_right))
3929 	{
3930 		m_left = left;
3931 		m_right = right;
3932 	}
3933 	if(m_loc != NULL)
3934 	{
3935 		len = SeqLocLen(m_loc);
3936 		last_loc = m_loc;
3937 		offset = 0;
3938 		sint = NULL;
3939 		while(last_loc->next != NULL)
3940 		{
3941 			len += SeqLocLen(last_loc->next);
3942 			last_loc = last_loc->next;
3943 		}
3944 		if(m_left != -1 && m_right != -1 && last_loc->choice == SEQLOC_INT)
3945 		{
3946 			offset = m_right - m_left + 1 - len;
3947 			if(offset > 0)
3948 			{
3949 				sint = last_loc->data.ptrvalue;
3950 				if(sint->strand == Seq_strand_minus)
3951 					sint->from -= offset;
3952 				else
3953 					sint->to += offset;
3954 			}
3955 		}
3956 		DrawSeqScale(seg, m_loc, 0, 0, scale, TRUE);
3957 		if(offset > 0 && sint != NULL)
3958 		{
3959 			if(sint->strand == Seq_strand_minus)
3960 				sint->from += offset;
3961 			else
3962 				sint->to -= offset;
3963 		}
3964 	}
3965 
3966 	SelectFont(programFont);
3967 	group_font_height = FontHeight();
3968 	space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
3969 
3970 
3971 	if(anp_node == NULL)
3972 		return FALSE;
3973 	list = anp_node;
3974 	prev = NULL;
3975 	head = NULL;
3976 	use_symbol_for_align = FALSE;
3977 	while(list != NULL)
3978 	{
3979 		annot_info = NULL;
3980 		/* if(prev != NULL)
3981 			prev->next = list; */
3982 		while(list && list->choice == OBJ_SEQANNOT)
3983 		{
3984 			annot_info = (AnnotInfoPtr)(list->data.ptrvalue);
3985 			if(annot_info != NULL && annot_info->consistent == ALIGN_UNKNOWN)
3986 			{
3987 				/*it is the folder like un-aligned thing*/
3988 				pseg = CreateSegment(pic, OBJ_SEQANNOT, 0);
3989 				seg = CreateSegment(pseg, annot_info->entityID, 0);
3990 				if(draw_unknown_folder(seg, m_left, m_right, y_pos, annot_info))
3991 				{
3992 					y_pos -= (group_font_height + space);
3993 					*cur_pos = y_pos;
3994 				}
3995 			}
3996 			if(head == NULL)
3997 				head = list;
3998 			prev = list;
3999 			list = list->next;
4000 		}
4001 		if(list != NULL)
4002 		{
4003 			use_symbol_for_align = FALSE;
4004 			curr = list;
4005 			last = NULL;
4006 			while(curr && curr->choice != OBJ_SEQANNOT)
4007 			{
4008 				last = curr;
4009 				curr = curr->next;
4010 			}
4011 			next = last->next;
4012 			last->next = NULL;
4013 			g_top = y_pos;
4014 			if(annot_info != NULL)	/*there is a Seq-annot wrapper*/
4015 			{
4016 				y_pos  -= group_font_height;
4017 				g_top -= group_font_height/2;
4018 				if(annot_info->annotDB[0] != '\0')
4019 				{
4020 					if(StringCmp(annot_info->annotDB, "UniGene") == 0)
4021 						use_symbol_for_align = TRUE;
4022 				}
4023 			}
4024 			if(use_symbol_for_align)
4025 				*cur_pos = LayoutAlignFlat(list, scale, y_pos);
4026 			else
4027 				*cur_pos = LayoutAlignNode(list, y_pos, scale, height);
4028 			g_bottom = *cur_pos;
4029 			y_pos = *cur_pos;
4030 
4031 			pseg = CreateSegment(pic, list->choice, 0);
4032 			seg = CreateSegment(pseg, entityID, 0);
4033 			if(use_symbol_for_align)
4034 				DrawFlatAlign(seg, list);
4035 			else
4036 				DrawAlignNode(list, scale, seg);
4037 
4038 			if(annot_info != NULL)
4039 			{
4040 				pseg = CreateSegment(pic, OBJ_SEQANNOT, 0);
4041 				seg = CreateSegment(pseg, annot_info->entityID, 0);
4042 				AddAnnotGroup(m_left, g_top, m_right, g_bottom, (Int2)(annot_info->displayOrder), annot_info->annotDB, annot_info->itemID, seg);
4043 				y_pos -= group_font_height;
4044 			}
4045 			/* last->next = next; */
4046 			if(prev != NULL)
4047 				prev->next = list;
4048 			last = list;
4049 			while(last->next != NULL)
4050 				last = last->next;
4051 			last->next = next;
4052 			prev = last;
4053 			list = next;
4054 		}
4055 	}
4056 	return TRUE;
4057 }
4058 
4059 
4060 
4061 
4062 
4063 
4064 /************************************************************************
4065 *
4066 *	DrawSeqScale(seg, slp, left, ypos, scaleX)
4067 *	draw a scale for the Seq-loc. It can be a list of Seq-loc
4068 *	seg: the drawing segment
4069 *	slp: the Seq-loc
4070 *	left: the left offset
4071 *	ypos: the top position
4072 *	scaleX: the current scale of the picture
4073 *
4074 ************************************************************************/
DrawSeqScale(SegmenT seg,SeqLocPtr slp,Int4 left,Int4 ypos,Int4 scaleX,Boolean add_x_line)4075 void DrawSeqScale(SegmenT seg, SeqLocPtr slp, Int4 left, Int4 ypos, Int4 scaleX, Boolean add_x_line)
4076 {
4077 
4078   Int4 ruler;
4079   Int4 r_start, r_stop, curpos;
4080   Int4 xpos;
4081   Char str[20];
4082   Int2 i;
4083   NumberingPtr np;
4084   Boolean use_kb;
4085   Int2 label_width = 0;
4086   Int2 c_width;
4087   Int4 pre_pos = -1;
4088   BioseqPtr bsp;
4089 
4090 
4091 
4092 	 ruler = calculate_ruler(scaleX);
4093 	 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
4094 	ypos -=2;
4095   	bsp = BioseqFind(SeqLocId(slp));
4096 	if(bsp == NULL)
4097 		np = NULL;
4098 	else
4099 		np = getBioseqNumbering(bsp);
4100 	use_kb = (scaleX >= 1000);
4101 	while(slp)
4102 	{
4103 		r_start = SeqLocStart(slp);
4104 		r_stop = SeqLocStop(slp);
4105 		if(add_x_line)
4106 			AddLine(seg, left, ypos, left+SeqLocLen(slp), ypos, FALSE, 0);
4107 		for(curpos = r_start; curpos <=r_stop; curpos +=ruler)
4108 		{
4109 			map_unit_label(curpos, np, str, use_kb);
4110 			xpos = left + curpos - r_start;
4111 			AddLine(seg, xpos, ypos, xpos, ypos-8, FALSE, 0);
4112 			c_width = StringWidth(str);
4113 			if(start_new_stack(pre_pos, xpos, scaleX, &label_width, c_width))
4114 			{
4115 				pre_pos = xpos;
4116 				AddLabel(seg, xpos, ypos-4, str, SMALL_TEXT, 5, LOWER_CENTER, 0);
4117 			}
4118 			for(i =1; i<10; ++i)
4119 			{
4120 				if(curpos + ruler/10*i <=r_stop)
4121 				{
4122 					xpos = left + curpos + ruler/10*i - r_start;
4123 					if(i ==5)
4124 						AddLine(seg, xpos, ypos, xpos, ypos-5, FALSE, 0);
4125 					else
4126 						AddLine(seg, xpos, ypos, xpos, ypos-3, FALSE, 0);
4127 				}
4128 			}
4129 		}
4130 		left += SeqLocLen(slp);
4131 		slp = slp->next;
4132 	}
4133 }
4134 
4135 
4136 
CountMaxSeqLabel(ValNodePtr slp_list)4137 Int4 CountMaxSeqLabel(ValNodePtr slp_list)
4138 {
4139 	FonT font;
4140 	SeqLocPtr slp;
4141 	BioseqPtr bsp;
4142 	Uint1 format;
4143 	Char label[100];
4144 	Int4 max_width = 0;
4145 
4146 
4147 	font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_FONT);
4148 	format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
4149 
4150 	SelectFont(font);
4151 
4152 	while(slp_list)
4153 	{
4154 		slp = slp_list->data.ptrvalue;
4155 		if(slp != NULL)
4156 		{
4157 			bsp = BioseqFind(SeqLocId(slp));
4158 			if(bsp != NULL)
4159 				MuskSeqIdWrite(bsp->id, label, 99, format, TRUE, FALSE);
4160 			else
4161 				MuskSeqIdWrite(SeqLocId(slp), label, 99, format, FALSE, FALSE);
4162 			max_width = MAX(StringWidth(label), max_width);
4163 		}
4164 		slp_list = slp_list->next;
4165 	}
4166 	return max_width;
4167 }
4168 
4169 
FigureMaxScale(ValNodePtr slp_list,Int2 view_width,Int4 max_label)4170 Int4 FigureMaxScale(ValNodePtr slp_list, Int2 view_width, Int4 max_label)
4171 {
4172 	Int4 width;
4173 	Int4 scale;
4174 
4175 	Int4 seq_len;
4176 	SeqLocPtr slp;
4177 	ValNodePtr curr;
4178 	Int4 len;
4179 
4180 	seq_len = 0;
4181 	for(curr = slp_list; curr !=NULL; curr = curr->next)
4182 	{
4183 		slp = (SeqLocPtr)(curr->data.ptrvalue);
4184 		len = slp_list_len(slp);
4185 		seq_len = MAX(len, seq_len);
4186 	}
4187 	if(seq_len == 0)
4188 		return -1;
4189 	width = (Int4)view_width- max_label;
4190 	if(width <=0)
4191 		width = view_width/2;
4192 	scale = seq_len/width + (((Int4)width%(Int4)view_width)>0);
4193 	return MIN(scale, MAX_SCALE);
4194 	/* return scale; */
4195 }
4196 
FigureMinScale(ValNodePtr slp_list,Int4 max_label)4197 Int4 FigureMinScale(ValNodePtr slp_list, Int4 max_label)
4198 {
4199 	Int4 seq_len;
4200 	SeqLocPtr slp;
4201 	ValNodePtr curr;
4202 
4203 	seq_len = 0;
4204 	for(curr = slp_list; curr !=NULL; curr = curr->next)
4205 	{
4206 		slp = (SeqLocPtr)(slp_list->data.ptrvalue);
4207 		seq_len = MAX(slp_list_len(slp), seq_len);
4208 	}
4209 	if(seq_len == 0)
4210 		return 1;
4211 	return MAX(1, (seq_len + max_label)/320000L);
4212 }
4213 
4214 
find_hot_link_gi(SeqIdPtr h_sip,Int4Ptr gi)4215 static Uint1 find_hot_link_gi(SeqIdPtr h_sip, Int4Ptr gi)
4216 {
4217 	DbtagPtr db_tag;
4218 	ObjectIdPtr oip;
4219 	SeqIdPtr sip;
4220 
4221 	*gi = 0;
4222 	sip = h_sip;
4223 	while(sip)
4224 	{
4225 		if(sip->choice == SEQID_GI)
4226 		{
4227 			*gi = sip->data.intvalue;
4228 			return ENTREZ_DB;
4229 		}
4230 		else if(sip->choice == SEQID_GENERAL)
4231 		{
4232 			db_tag = sip->data.ptrvalue;
4233 			if(db_tag && db_tag->db && StringCmp(db_tag->db, "THC") == 0)
4234 			{
4235 				oip = db_tag->tag;
4236 				if(oip && oip->id != 0)
4237 				{
4238 					*gi = oip->id;
4239 					return THC_DB;
4240 				}
4241 			}
4242 		}
4243 
4244 		sip = sip->next;
4245 	}
4246 
4247 	for(sip = h_sip; sip != NULL; sip = sip->next)
4248 	{
4249 		if(sip->choice == SEQID_GENERAL)
4250 		{
4251 			*gi = GetUniGeneIDForSeqId (sip);
4252 			if(*gi != 0)
4253 				return ENTREZ_KLUDGE_ID;
4254 		}
4255 	}
4256 
4257 
4258 	return 0;
4259 }
4260 
link_new_align_label(ValNodePtr PNTR head,ValNodePtr PNTR prev,Uint1 choice,AlignLabelRectPtr alrp)4261 static void link_new_align_label(ValNodePtr PNTR head, ValNodePtr PNTR prev, Uint1 choice, AlignLabelRectPtr alrp)
4262 {
4263 	ValNodePtr curr;
4264 
4265 	curr = ValNodeNew(NULL);
4266 	curr->choice = choice;
4267 	curr->data.ptrvalue = alrp;
4268 
4269 	if(*prev == NULL)
4270 		*head = curr;
4271 	else
4272 		(*prev)->next = curr;
4273 	*prev = curr;
4274 }
4275 
4276 
4277 /*
4278 *
4279 *	Add the rectangle for the label of the sequence
4280 *	width is the width of the label
4281 *
4282 */
add_label_rectangle(AlignLabelRectPtr alrp,Int4 width,Int4 label_height,Uint1 label_align,Int4 e_left,Int4 e_top,Int4 e_right,Int4 e_bottom)4283 static Boolean add_label_rectangle (AlignLabelRectPtr alrp, Int4 width, Int4 label_height,
4284 		Uint1 label_align, Int4 e_left, Int4 e_top, Int4 e_right, Int4 e_bottom)
4285 {
4286 	Int4 center, middle;
4287 
4288 	if(alrp == NULL || width == 0)
4289 		return FALSE;
4290 
4291 	switch(label_align)
4292 	{
4293 		case MSM_LABEL_TOP:
4294 			center = (e_left + e_right)/2;
4295 			alrp->left = center - width/2;
4296 			alrp->right = center + width/2;
4297 			alrp->bottom = e_top;
4298 			alrp->top = e_top + label_height;
4299 			break;
4300 
4301 		case MSM_LABEL_BOTTOM:
4302 			center = (e_left + e_right)/2;
4303 			alrp->left = center - width/2;
4304 			alrp->right = center + width/2;
4305 			alrp->top = e_bottom;
4306 			alrp->bottom = e_bottom - label_height;
4307 			break;
4308 
4309 		case MSM_LABEL_LEFT:
4310 			middle = (e_top + e_bottom)/2;
4311 			alrp->right= e_left;
4312 			alrp->left=  alrp->right - width;
4313 			alrp->bottom = middle - label_height/2;
4314 			alrp->top = middle + label_height/2;
4315 			break;
4316 
4317 		case MSM_LABEL_RIGHT:
4318 			middle = (e_top + e_bottom)/2;
4319 			alrp->left=e_right;
4320 			alrp->right =  alrp->left + width;
4321 			alrp->bottom = middle - label_height/2;
4322 			alrp->top = middle + label_height/2;
4323 			break;
4324 		default:
4325 			break;
4326 	}
4327 	return TRUE;
4328 }
4329 
4330 /************************************************************************
4331 *
4332 *	load the information for image mapping
4333 *
4334 ************************************************************************/
load_align_label_rectangle(ValNodePtr data_list,ValNodePtr PNTR arect_list,Int4 scale,Boolean flat)4335 Boolean load_align_label_rectangle(ValNodePtr data_list, ValNodePtr PNTR arect_list, Int4 scale, Boolean flat)
4336 {
4337 	AlignNodePtr anp;
4338 	FeatNodePtr fnp;
4339 	BioseqPtr bsp;
4340 	Uint1 label_align, t_label_align;
4341 	AlignLabelRectPtr alrp;
4342 	Int4 width;
4343 	Int4 e_left = 0, e_right = 0;
4344 	Int4 e_top = 0, e_bottom = 0;
4345 	Int4 font_height;
4346 	FonT font;
4347 	Uint1 link_db;
4348 	Int4 gi;
4349 	Int4 label_height = stdLineHeight;
4350 	ValNodePtr prev, curr;
4351 	Uint1 choice;
4352 	Boolean found_it;
4353 
4354 	if(data_list == NULL || arect_list == NULL)
4355 		return FALSE;
4356 	prev = NULL;
4357 	curr = *arect_list;
4358 	if(curr != NULL)
4359 	{
4360 		while(curr->next != NULL)
4361 		{
4362 			prev = curr;
4363 			curr = curr->next;
4364 		}
4365 	}
4366 
4367 	font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_FONT);
4368 	SelectFont(font);
4369 	font_height = FontHeight();
4370 	label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
4371 
4372 	while(data_list)
4373 	{
4374 		found_it = FALSE;
4375 		alrp = NULL;
4376 		/* t_label_align = label_align; */
4377 		if(flat)
4378 			t_label_align = MSM_LABEL_TOP;
4379 		else
4380 			t_label_align = label_align;
4381 		width = 0;
4382 		choice = 0;
4383 		/*process the intervals first */
4384 		switch(data_list->choice)
4385 		{
4386 			case OBJ_SEQALIGN:
4387 			case OBJ_SEQHIST_ALIGN:
4388 				anp = data_list->data.ptrvalue;
4389 				e_left = anp->extremes.left;
4390 				e_right = anp->extremes.right;
4391 				e_top = anp->top;
4392 				e_bottom = anp->bottom;
4393 				label_height = font_height;
4394 				if(anp->label != NULL)
4395 					width = StringWidth(anp->label) * scale;
4396 
4397 				bsp = BioseqFindCore(anp->sip);
4398 				gi = 0;
4399 				link_db = 0;
4400 				choice = 0;
4401 				if(bsp != NULL)
4402 				{
4403 					link_db = find_hot_link_gi(bsp->id, &gi);
4404 					choice = bsp->mol;
4405 				}
4406 				else
4407 				{
4408 					link_db = find_hot_link_gi(anp->sip, &gi);
4409 				}
4410 				if((e_right - e_left) /scale > 1)
4411 				{
4412 					alrp = MemNew(sizeof(AlignLabelRect));
4413 					alrp->itemID = anp->itemID;
4414 					alrp->itemType = data_list->choice;
4415 					if(link_db != UNKNOWN_DB && gi != 0)
4416 					{
4417 						alrp->link_db = link_db;
4418 						alrp->gi = gi;
4419 					}
4420 					alrp->left = e_left;
4421 					alrp->right = e_right;
4422 					alrp->top = e_top;
4423 					alrp->bottom = e_bottom;
4424 					link_new_align_label(arect_list, &prev, choice, alrp);
4425 				}
4426 				/*create the new one for the label*/
4427 				if(width > 0)
4428 				{
4429 					alrp = MemNew(sizeof(AlignLabelRect));
4430 					alrp->itemID = anp->itemID;
4431 					alrp->itemType = data_list->choice;
4432 					alrp->link_db = link_db;
4433 					alrp->gi = gi;
4434 				}
4435 
4436 				break;
4437 
4438 			case OBJ_SEQFEAT:
4439 			case OBJ_BIOSEQ:
4440 			case OBJ_BIOSEQ_SEG:
4441 				fnp = data_list->data.ptrvalue;
4442 				if((fnp->extremes.right - fnp->extremes.left)/scale > 1)
4443 				{
4444 					alrp = MemNew(sizeof(AlignLabelRect));
4445 					alrp->itemID = fnp->itemID;
4446 					alrp->itemType = data_list->choice;
4447 					alrp->right= fnp->extremes.right;
4448 					alrp->left=  fnp->extremes.left;
4449 					alrp->bottom = fnp->bottom;
4450 					alrp->top = fnp->top;
4451 					link_new_align_label(arect_list, &prev, choice, alrp);
4452 				}
4453 
4454 				if(fnp->label != NULL && fnp->labelHeight > 0 && fnp->label_len > 0)
4455 				{
4456 					e_left = fnp->extremes.left;
4457 					e_right = fnp->extremes.right;
4458 					e_top = fnp->top;
4459 					e_bottom = fnp->bottom;
4460 					label_height = fnp->labelHeight;
4461 					width = scale * (fnp->label_len);
4462 					alrp = MemNew(sizeof(AlignLabelRect));
4463 					alrp->itemID = fnp->itemID;
4464 					alrp->itemType = data_list->choice;
4465 				}
4466 				if(data_list->choice != OBJ_SEQFEAT)
4467 				{	/*it is a Bioseq or a segment of a Bioseq*/
4468 					if(label_align != MSM_LABEL_RIGHT)
4469 						t_label_align = MSM_LABEL_LEFT;
4470 					else
4471 						t_label_align = MSM_LABEL_RIGHT;
4472 				}
4473 				break;
4474 
4475 			case OBJ_BIOSEQ_MAPFEAT:
4476 				fnp = data_list->data.ptrvalue;
4477 				if(fnp->label != NULL && fnp->labelHeight > 0 && fnp->label_len > 0)
4478 				{
4479 					e_left = fnp->extremes.left;
4480 					e_right = fnp->extremes.right;
4481 					e_top = fnp->top;
4482 					e_bottom = fnp->bottom;
4483 					label_height = fnp->labelHeight;
4484 					width = scale * (fnp->label_len);
4485 					t_label_align = MSM_LABEL_TOP;
4486 					alrp = MemNew(sizeof(AlignLabelRect));
4487 					alrp->itemID = fnp->itemID;
4488 					alrp->itemType = data_list->choice;
4489 
4490 				}
4491 				break;
4492 			default:
4493 				break;
4494 		}
4495 
4496 		/*process the labels*/
4497 		if(width > 0)
4498 		{
4499 
4500 			add_label_rectangle (alrp, width, label_height, t_label_align,
4501 				e_left, e_top, e_right, e_bottom);
4502 			link_new_align_label(arect_list, &prev, choice, alrp);
4503 		}
4504 
4505 		data_list = data_list->next;
4506 	}
4507 
4508 	return TRUE;
4509 }
4510 
4511 /*
4512 *	for the contig maps, the real contig length may not correspond
4513 *	with the mapped interval on the graphics. Need a way to find the
4514 *	store the interval mapped in proportion to what is in the graphic
4515 *	the intervals are mapped by the function: FindContigList
4516 */
AddIntervalForImage(ValNodePtr contig_list,ValNodePtr image_list)4517 void AddIntervalForImage(ValNodePtr contig_list, ValNodePtr image_list)
4518 {
4519 	SeqLocPtr contig_slp;
4520 	SeqIdPtr sip;
4521 	ObjectIdPtr oip;
4522 	DbtagPtr db_tag;
4523 	ValNodePtr curr, vnp;
4524 	AlignLabelRectPtr alrp;
4525 	Uint1 db_type;
4526 
4527 
4528 	for(vnp = contig_list; vnp != NULL; vnp = vnp->next)
4529 	{
4530 		contig_slp = vnp->data.ptrvalue;
4531 		sip = SeqLocId(contig_slp);
4532 		if(sip != NULL && (db_type = FindContigDB(sip)) != 0)
4533 		{
4534 			db_tag = sip->data.ptrvalue;
4535 			oip = db_tag->tag;
4536 			for(curr = image_list; curr != NULL; curr = curr->next)
4537 			{
4538 				alrp = curr->data.ptrvalue;
4539 				if(alrp->link_db == db_type &&
4540 					StringCmp(alrp->label, oip->str) == 0)
4541 				{
4542 					alrp->from = SeqLocStart(contig_slp);
4543 					alrp->to = SeqLocStop(contig_slp);
4544 				}
4545 			}
4546 		}
4547 	}
4548 }
4549 
4550 
4551 
4552 
PicForAlignNode(ValNodePtr anp_list,SeqLocPtr m_loc,Int4 width,Int4Ptr p_scale,Int4Ptr p_maxwidth,ValNodePtr PNTR arect_list)4553 SegmenT PicForAlignNode(ValNodePtr anp_list, SeqLocPtr m_loc, Int4 width, Int4Ptr p_scale, Int4Ptr p_maxwidth, ValNodePtr PNTR arect_list)
4554 {
4555 	Int4 scale;
4556 	SegmenT pic;
4557 	ValNode vn;
4558 	Int4 max_width, min_scale;
4559 	Int4 y_pos;
4560 	Uint2 entityID;
4561 	BioseqPtr bsp;
4562 
4563 
4564 	if(anp_list == NULL)
4565 		return NULL;
4566 	if(arect_list != NULL)
4567 		*arect_list = NULL;
4568 	vn.data.ptrvalue = m_loc;
4569 	vn.next = NULL;
4570 	max_width = CountMaxSeqLabel(&vn);
4571 	scale = FigureMaxScale(&vn, (Int2)width, max_width);
4572 	min_scale = FigureMinScale (&vn, max_width);
4573 	if(scale <=0)
4574 		return NULL;
4575 	pic = CreatePicture();
4576 	y_pos = 0;
4577 	bsp = BioseqFind(SeqLocId(m_loc));
4578 	entityID = ObjMgrGetEntityIDForPointer((Pointer)bsp);
4579 	DrawMPAlignment(anp_list, 0, SeqLocLen(m_loc)-1, m_loc, entityID, scale, &y_pos, MSM_MPAIR, FALSE, pic);
4580         load_align_label_rectangle(anp_list, arect_list, scale, FALSE);
4581         /* ObjMgrClearHold(); */
4582         SeqMgrFreeCache();
4583 
4584 	*p_scale = scale;
4585 	*p_maxwidth = max_width;
4586 	return pic;
4587 }
4588 
4589 
setup_option_for_cytomap(CollectSeqOptionPtr csop)4590 static void setup_option_for_cytomap(CollectSeqOptionPtr csop)
4591 {
4592 	Int2 i;
4593 
4594 	csop->nointerval = TRUE;
4595 	csop->slabel_format = PRINTID_TEXTID_ACCESSION;
4596 	csop->seglevels = 0;
4597 	csop->label_size = 20;
4598 	csop->filter_level = 0;
4599 	csop->bsp_type = CYTO_MAP;
4600 
4601 	for(i = 0; i<FEATDEF_ANY; ++i)
4602 	{
4603 		csop->flabel_format[i] = OM_LABEL_CONTENT;
4604 		csop->features[i] = FALSE;
4605 	}
4606 }
4607 
CleanUnanchoredContig(ValNodePtr PNTR anp_list)4608 static void CleanUnanchoredContig(ValNodePtr PNTR anp_list)
4609 {
4610 	ValNodePtr vnp, prev, next;
4611 	AnnotInfoPtr info;
4612 	Boolean clean = FALSE;
4613 
4614 	vnp = *anp_list;
4615 	prev = NULL;
4616 	while(vnp != NULL)
4617 	{
4618 		next = vnp->next;
4619 		if(vnp->choice == OBJ_SEQANNOT)
4620 		{
4621 			info = vnp->data.ptrvalue;
4622 			if(info && info->consistent == ALIGN_UNKNOWN)
4623 				clean = TRUE;
4624 			else
4625 				clean = FALSE;
4626 		}
4627 		if(clean)
4628 		{
4629 			if(prev == NULL)
4630 				*anp_list = next;
4631 			else
4632 				prev->next = next;
4633 			vnp->next = NULL;
4634 			FreeAlignNode(vnp);
4635 		}
4636 		else
4637 			prev = vnp;
4638 		vnp = next;
4639 	}
4640 }
4641 
AddAlignNodeOffset(ValNodePtr anp_list,Int4 offset)4642 static void AddAlignNodeOffset(ValNodePtr anp_list, Int4 offset)
4643 {
4644 	AlignNodePtr anp;
4645 	AlignSegPtr asp;
4646 
4647 	while(anp_list)
4648 	{
4649 		if(anp_list->choice != OBJ_SEQANNOT)
4650 		{
4651 			anp = anp_list->data.ptrvalue;
4652 			anp->extremes.left += offset;
4653 			anp->extremes.right += offset;
4654 
4655 			for(asp = anp->segs; asp != NULL; asp = asp->next)
4656 			{
4657 				asp->gr.left += offset;
4658 				asp->gr.right += offset;
4659 			}
4660 		}
4661 
4662 		anp_list = anp_list->next;
4663 	}
4664 }
4665 
AddYACAnnotInfo(ValNodePtr PNTR anp_list,Uint1 type)4666 static void AddYACAnnotInfo(ValNodePtr PNTR anp_list, Uint1 type)
4667 {
4668 	AnnotInfoPtr info;
4669 	ValNodePtr vnp;
4670 
4671 	vnp = *anp_list;
4672 	if(vnp->choice == OBJ_SEQANNOT)
4673 	{
4674 		info = vnp->data.ptrvalue;
4675 		if(type == YAC_MIT)
4676 			StringCpy(info->annotDB, "Contigs from WI/MIT");
4677 		else
4678 			StringCpy(info->annotDB, "Contigs from NHGRI");
4679 		return;
4680 	}
4681 
4682 	info = MemNew(sizeof(AnnotInfo));
4683 	if(type == YAC_MIT)
4684 		StringCpy(info->annotDB, "Contigs from WI/MIT");
4685 	else
4686 		StringCpy(info->annotDB, "Contigs from NHGRI");
4687 	vnp = ValNodeNew(NULL);
4688 	vnp->choice = OBJ_SEQANNOT;
4689 	vnp->data.ptrvalue = info;
4690 	vnp->next = *anp_list;
4691 	*anp_list = vnp;
4692 }
4693 
4694 
find_anp_for_image(AlignLabelRectPtr alrp,ValNodePtr anp_list)4695 static AlignNodePtr find_anp_for_image(AlignLabelRectPtr alrp, ValNodePtr anp_list)
4696 {
4697 	AlignNodePtr anp;
4698 
4699 	while(anp_list)
4700 	{
4701 		if(anp_list->choice != OBJ_SEQANNOT)
4702 		{
4703 			anp = anp_list->data.ptrvalue;
4704 			if(anp->itemID == alrp->itemID && anp_list->choice == alrp->itemType)
4705 				return anp;
4706 		}
4707 		anp_list = anp_list->next;
4708 	}
4709 
4710 	return NULL;
4711 }
4712 
4713 
add_label_to_image(ValNodePtr PNTR image_list,ValNodePtr anp_list)4714 static void add_label_to_image(ValNodePtr PNTR image_list, ValNodePtr anp_list)
4715 {
4716 	AlignLabelRectPtr alrp;
4717 	AlignNodePtr anp;
4718 	ValNodePtr prev, next, curr;
4719 	Uint1 db_type;
4720 	DbtagPtr db_tag;
4721 	ObjectIdPtr oip;
4722 
4723 	curr = *image_list;
4724 	prev = NULL;
4725 	while(curr)
4726 	{
4727 		next = curr->next;
4728 		alrp = curr->data.ptrvalue;
4729 		anp = find_anp_for_image(alrp, anp_list);
4730 		if(anp == NULL || anp->sip == NULL ||
4731 			(db_type = FindContigDB(anp->sip)) == 0)
4732 		{
4733 			if(prev == NULL)
4734 				*image_list = next;
4735 			else
4736 				prev->next = next;
4737 			curr->next = NULL;
4738 			ValNodeFreeData(curr);
4739 		}
4740 		else
4741 		{
4742 			prev = curr;
4743 			alrp->link_db = db_type;
4744 			db_tag = anp->sip->data.ptrvalue;
4745 			oip = db_tag->tag;
4746 			alrp->label = StringSave(oip->str);
4747 		}
4748 
4749 		curr = next;
4750 	}
4751 }
4752 
4753 
4754 
4755 /*produce a picture which shows the contigs that align to the
4756 * cytogenetic band. It will expand left to the half band size and
4757 *	right to the half band size. pic_width is the width of the picture
4758 * in the image map, use link_db to do MIT_YAC or NHGRI_YAC and use
4759 *	label to load oip->str. that should give enough information to
4760 *	re-produce the seq-id
4761 */
DrawCytoContigMap(ValNodePtr slp_list,BioseqPtr cyto_bsp,Int4 pic_width,Int4Ptr pscale,ValNodePtr PNTR image_list)4762 SegmenT DrawCytoContigMap (ValNodePtr slp_list, BioseqPtr cyto_bsp,
4763 			Int4 pic_width, Int4Ptr pscale, ValNodePtr PNTR image_list)
4764 {
4765 	ValNodePtr curr;
4766 	SeqLocPtr cyto_slp;
4767 	SeqLocPtr slp, t_slp;
4768 	Int4 off_start = 0, off_stop = 0;
4769 	SeqIntPtr sint;
4770 	Int4 len;
4771 
4772 	SegmenT pic;
4773 	CollectSeqOption cs_option;
4774 	CollectAlignOption ca_option;
4775 
4776 	ValNodePtr features;
4777 	Uint2 entityID;
4778 	Int4 max_label;
4779 
4780 	MapPosPtr mpp;
4781 	Int4 scale;
4782 	Int4 left;
4783 
4784 	BioseqPtr bsp;
4785 	ValNodePtr aligns;
4786 	ValNodePtr anp_list;
4787 	Uint1 db_type;
4788 
4789 	ValNodePtr contig_slp_list, list;	/*stores the mapped loc for each contig*/
4790 
4791 
4792 	if(slp_list == NULL || cyto_bsp == NULL || pic_width < 100)
4793 		return NULL;
4794 	entityID = ObjMgrGetEntityIDForPointer((Pointer)cyto_bsp);
4795 	if(entityID == 0)
4796 		return NULL;
4797 
4798 	if(image_list != NULL)
4799 		*image_list = NULL;
4800 	cyto_slp = NULL;
4801 	for(curr = slp_list; curr != NULL; curr = curr->next)
4802 	{
4803 		slp = curr->data.ptrvalue;
4804 		if(BioseqMatch(cyto_bsp, SeqLocId(slp)))
4805 		{
4806 			cyto_slp = SeqLocIntNew(SeqLocStart(slp), SeqLocStop(slp),
4807 				Seq_strand_plus, SeqLocId(slp));
4808 			len = SeqLocLen(cyto_slp);
4809 			sint = cyto_slp->data.ptrvalue;
4810 			sint->from = MAX(0, sint->from - len/2);
4811 			sint->to = MIN(cyto_bsp->length-1, sint->to + len/2);
4812 			off_start = SeqLocStart(slp) - sint->from;
4813 			off_stop = sint->to - SeqLocStop(slp);
4814 			break;
4815 		}
4816 	}
4817 
4818 	if(cyto_slp == NULL)
4819 		return NULL;
4820 
4821 	/*calculate the scale for the picture*/
4822 	SelectFont(systemFont);
4823 	max_label = StringWidth("XXXXXXXXXX");
4824 	pic_width -= max_label;
4825 	if(pic_width < 50)
4826 	{
4827 		SeqLocFree(cyto_slp);
4828 		return NULL;
4829 	}
4830 	len = SeqLocLen(cyto_slp);
4831 	scale = len/pic_width;
4832 	if(len%pic_width > 0)
4833 		scale += 1;
4834 
4835 	/*collect information about the cytogenetic band*/
4836 	setup_option_for_cytomap(&cs_option);
4837 	features = CollectItemForSeqLoc(cyto_slp, entityID, 0, FALSE, NULL,
4838 		&cs_option, NULL, 0);
4839 	if(features == NULL)
4840 	{
4841 		SeqLocFree(cyto_slp);
4842 		return NULL;
4843 	}
4844 
4845 	pic = CreatePicture();
4846 	/*draw the cytogenetic map*/
4847 	mpp = MemNew(sizeof(MapPos));
4848 	mpp->slp = cyto_slp;
4849 	mpp->left = 0;
4850 	mpp->right = len;
4851 	mpp->top  = 0;
4852 	mpp->bottom = 0;
4853 	mpp->seq_top = 0;
4854 	mpp->seq_bottom = 0;
4855 	mpp->entityID = entityID;
4856 	if(!DrawCytoMap(&features, mpp, scale, pic))
4857 	{
4858 		FreeFeatureList(features);
4859 		MemFree(mpp);
4860 		SeqLocFree(cyto_slp);
4861 		DeletePicture(pic);
4862 		return NULL;
4863 	}
4864 	add_seq_label_for_map(&features, mpp, pic);
4865 	FreeFeatureList(features);
4866 	SeqLocFree(cyto_slp);
4867 
4868 	/*draw the contigs */
4869 	*pscale = scale;
4870 	set_option_for_collect_align(&ca_option, cs_option.label_size, COLLECT_HISTORY);
4871 	ca_option.only_history = FALSE;
4872 	ca_option.map_insert = TRUE;
4873 	ca_option.slabel_format = cs_option.slabel_format;
4874 	ca_option.nointerval = cs_option.nointerval;
4875 	ca_option.no_sort = FALSE;
4876 	ca_option.flat_insert = FALSE;
4877 
4878 	anp_list = NULL;
4879 	contig_slp_list = NULL;
4880 	for(curr = slp_list; curr != NULL; curr = curr->next)
4881 	{
4882 		slp = curr->data.ptrvalue;
4883 		/*check if it is the WI map or the Eric Green map*/
4884 		if((db_type = FindContigDB(SeqLocId(slp))) != 0)
4885 		{
4886 			sint = slp->data.ptrvalue;
4887 			left = 0;
4888 			bsp = BioseqFind(sint->id);
4889 			if(bsp != NULL)
4890 			{
4891 				t_slp = SeqLocIntNew(SeqLocStart(slp), SeqLocStop(slp),
4892 					Seq_strand_plus, SeqLocId(slp));
4893 				sint = t_slp->data.ptrvalue;
4894 				if(off_start > 0)
4895 				{
4896 					sint->from -= off_start;
4897 					if(sint->from < 0)
4898 					{
4899 						left = ABS(sint->from);
4900 						sint->from = 0;
4901 					}
4902 				}
4903 				if(off_stop > 0)
4904 				{
4905 					sint->to += off_stop;
4906 					if(sint->to > bsp->length -1 )
4907 						sint->to = bsp->length;
4908 				}
4909 
4910 				aligns = collect_anpnode_with_option(&ca_option, t_slp, entityID,
4911 					COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
4912 				if(aligns != NULL)
4913 					CleanUnanchoredContig(&aligns);
4914 				if(aligns != NULL)
4915 				{
4916 					list = FindContigList(t_slp);
4917 					ValNodeLink(&contig_slp_list, list);
4918 					if(left > 0)
4919 						AddAlignNodeOffset(aligns, left);
4920 					AddYACAnnotInfo(&aligns, db_type);
4921 					ValNodeLink(&anp_list, aligns);
4922 				}
4923 				SeqLocFree(t_slp);
4924 			}
4925 		}
4926 	}
4927 
4928 	if(anp_list != NULL)
4929 	{
4930 		len = StringWidth("XXXXXX");
4931 		DrawMPAlignment(anp_list, mpp->left-len*scale, mpp->right + 8*scale, NULL, mpp->entityID, scale, &(mpp->bottom), MSM_SEQHIST, FALSE, pic);
4932 		if(image_list != NULL)
4933 		{
4934 			load_align_label_rectangle(anp_list, image_list, scale, FALSE);
4935 			/*add the label so that a Seq-id can be made from link_db+label*/
4936 			add_label_to_image(image_list,anp_list);
4937 			/*add the real interval in a contig sequence*/
4938 			AddIntervalForImage(contig_slp_list, *image_list);
4939 		}
4940 		FreeAlignNode(anp_list);
4941 	}
4942 	MemFree(mpp);
4943 	free_slp_list(contig_slp_list);
4944 
4945 	return pic;
4946 }
4947 
4948 
4949 
4950 
4951 
4952 
4953 
4954 
4955