NCBI C Toolkit Cross Reference

C/desktop/drawseq.c


  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);
 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 *************************************************************************/
 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 **********************************************************************/
 65 Uint1Ptr get_enz_color(Int2 enzID)
 66 {
 67         return get_seg_color(enzID);
 68 }
 69 
 70 
 71 /**********************************************************************
 72 *
 73 *
 74 *
 75 ***********************************************************************/
 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 
 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 
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 
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 
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 
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 
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 
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*/
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 
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 
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 
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 
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         
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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                         
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 
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 
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 
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 
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 
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 
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 
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 
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 
1354 static Boolean is_repeat_feature (Uint1 feattype)
1355 {
1356         return (feattype == FEATDEF_repeat_region ||feattype == FEATDEF_repeat_unit);
1357 }
1358 
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 
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 
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 
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 **********************************************************************/
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 
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 *************************************************************************/
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 *************************************************************************/
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 
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 ***********************************************************************/
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 ***********************************************************************/
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 
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         
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 *********************************************************************/
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 
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 *******************************************************************/
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 
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 
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                         
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 
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 
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 
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 
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 *********************************************************************/
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 
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 
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 
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*/
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 
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 
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 *******************************************************************/
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 *********************************************************************/
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 
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         
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 ***********************************************************************/                
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 */
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 
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 *************************************************************************/
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 
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 
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 
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 
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 
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 *********************************************************************/
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 
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 **************************************************************************/
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 
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 
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 ************************************************************/
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 ************************************************************************/
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 
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         
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 
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 ************************************************************************/
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 
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 
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 
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 
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 
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 */
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 ************************************************************************/
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 */
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 
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 
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 
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 
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 
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 
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 
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 */
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 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.