1 /*   salpanel.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *            National Center for Biotechnology Information (NCBI)
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government do not place any restriction on its use or reproduction.
13 *  We would, however, appreciate having the NCBI and the author cited in
14 *  any work or product based on this material
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name:  salpanel.c
27 *
28 * Author:  Colombe Chappey
29 *
30 * Version Creation Date:   1/27/96
31 *
32 * $Revision: 6.104 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date     Name        Description of modification
39 * -------  ----------  -----------------------------------------------------
40 *
41 *
42 * ==========================================================================
43 */
44 #include <saledit.h>
45 #include <salpanel.h>
46 #include <salutil.h>
47 #include <salfiles.h>
48 #include <salstruc.h>
49 #include <fstyle.h>
50 #include <salmedia.h>
51 #include <sequtil.h>
52 #include <alignmgr.h>
53 #include <alignmgr2.h>
54 #include <edutil.h>
55 #include <dlogutil.h>
56 #include <import.h>
57 #include <seqpanel.h>
58 #include <cdrgn.h>
59 
60 #define OBJ_VIRT 254
61 
62 static Uint1 rectSym [] = {
63   0xFE, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFE, 0x00
64 };
65 static Uint1 diamondSym [] = {
66   0x10, 0x28, 0x44, 0x82, 0x44, 0x28, 0x10, 0x00
67 };
68 static Uint1 ovalSym [] = {
69   0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00
70 };
71 static Uint1 leftTriSym [] = {
72   0x06, 0x1A, 0x62, 0x82, 0x62, 0x1A, 0x06, 0x00
73 };
74 static Uint1 rightTriSym [] = {
75   0xC0, 0xB0, 0x8C, 0x82, 0x8C, 0xB0, 0xC0, 0x00
76 };
77 static Uint1 upTriSym [] = {
78   0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0xFE, 0x00
79 };
80 static Uint1 downTriSym [] = {
81   0xFE, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00
82 };
83 static Uint1 rectFillSym [] = {
84   0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x00
85 };
86 static Uint1 diamondFillSym [] = {
87   0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00
88 };
89 static Uint1 ovalFillSym [] = {
90   0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x00
91 };
92 static Uint1 leftTriFillSym [] = {
93   0x06, 0x1E, 0x7E, 0xFE, 0x7E, 0x1E, 0x06, 0x00
94 };
95 static Uint1 rightTriFillSym [] = {
96   0xC0, 0xF0, 0xFC, 0xFE, 0xFC, 0xF0, 0xC0, 0x00
97 };
98 static Uint1 upTriFillSym [] = {
99   0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00
100 };
101 static Uint1 downTriFillSym [] = {
102   0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00
103 };
104 static Uint1 rightOvalSym [] = {
105   0x18, 0x14, 0x12, 0x12, 0x12, 0x14, 0x18, 0x00
106 };
107 static Uint1 leftOvalSym [] = {
108   0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00
109 };
110 static Uint1 rightOvalFillSym [] = {
111   0x18, 0x1C, 0x1E, 0x1E, 0x1E, 0x1C, 0x18, 0x00
112 };
113 static Uint1 leftOvalFillSym [] = {
114   0x30, 0x50, 0x90, 0x90, 0x90, 0x50, 0x30, 0x00
115 };
116 
117 /*######################################################################
118 #
119 #       functions for setting up the color for different object
120 #
121 ######################################################################*/
122 #define RGB_B(x) (Uint1)((x)&255);
123 #define RGB_G(x) (Uint1)(((x)>>8)&255);
124 #define RGB_R(x) (Uint1)(((x)>>16)&255);
125 
convert_color(Int4 val,Uint1Ptr color)126 static Boolean convert_color(Int4 val, Uint1Ptr color)
127 {
128 
129         if(val<0 || color == NULL)
130                 return FALSE;
131         color[0] = RGB_R(val);
132         color[1] = RGB_G(val);
133         color[2] = RGB_B(val);
134         return TRUE;
135 }
136 
getcolor_fromstyles(Uint2 itemsubtype)137 static Uint4 getcolor_fromstyles (Uint2 itemsubtype)
138 {
139   Int4 c_val;
140   Uint1 color [3];
141 
142   c_val = GetMuskCParam (itemsubtype, MSM_SEGMENT, MSM_COLOR);
143   if ( convert_color (c_val, color) )
144      return GetColorRGB (color[0], color[1], color[2]);
145   return GetColorRGB (0, 0, 0);
146 }
147 
getcolorforvirtfeat(Uint2 item)148 static Uint4 getcolorforvirtfeat (Uint2 item)
149 {
150   return GetColorRGB ((Uint1)((item % 3) * 40),
151                       (Uint1)(255-(item % 3) * 40),
152                       (Uint1)((item % 3) * 40));
153 }
154 
155 /**********************************************
156 ***   GetAlignEditData
157 **********************************************/
getwindow_frompanel(PaneL pnl)158 extern WindoW getwindow_frompanel (PaneL pnl)
159 {
160 /*
161 #ifdef WIN_MAC
162   w = FrontWindow ();
163 #else
164   w = ParentWindow (pnl);
165 #endif
166 */
167   return ParentWindow (pnl);
168 }
169 
GetPanelFromWindow(WindoW w)170 extern PaneL GetPanelFromWindow (WindoW w)
171 {
172   SeqEditViewFormPtr wdp;
173 
174   wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
175   if (wdp == NULL) {
176     return NULL;
177   }
178   if ( wdp->pnl == NULL ) {
179     return NULL;
180   }
181   return wdp->pnl;
182 }
183 
GetAlignEditData(WindoW w)184 extern EditAlignDataPtr GetAlignEditData (WindoW w)
185 {
186   PaneL            pnl;
187   EditAlignDataPtr adp;
188 
189   pnl = GetPanelFromWindow (w);
190   if (pnl == NULL) return NULL;
191   GetPanelExtra (pnl, &adp);
192   if ( adp == NULL )
193      return NULL;
194   if ( adp->firstssp == NULL )
195      return NULL;
196   return adp;
197 }
198 
GetAlignDataPanel(PaneL pnl)199 extern EditAlignDataPtr GetAlignDataPanel (PaneL pnl)
200 {
201   EditAlignDataPtr adp;
202 
203   if ( pnl == NULL )
204      return NULL;
205   GetPanelExtra (pnl, &adp);
206   if ( adp == NULL )
207      return NULL;
208   if ( adp->firstssp == NULL )
209      return NULL;
210   return adp;
211 }
212 
213 /**********************************************
214 ***   AlignDataSet_Restore
215 ***     Inval Rect
216 ***     RestorePort
217 **********************************************/
get_client_rect(PaneL p,RectPtr prc)218 static void get_client_rect (PaneL p, RectPtr prc)
219 {
220   ObjectRect (p, prc);
221   InsetRect (prc, HRZ_BORDER_WIDTH, VER_BORDER_WIDTH);
222 }
223 
get_client_rectxy(PaneL p,RectPtr prc,Int2 x,Int2 y)224 static void get_client_rectxy (PaneL p, RectPtr prc, Int2 x, Int2 y)
225 {
226   ObjectRect (p, prc);
227   InsetRect (prc, x, y);
228 }
229 
230 /**************************************************************
231 ***
232 ***
233 **************************************************************/
get_firstline(SelEdStructPtr sesp1,SelStructPtr buffer)234 static SelStructPtr get_firstline (SelEdStructPtr sesp1, SelStructPtr buffer)
235 {
236   SelEdStructPtr sesp;
237   SelStructPtr   buf;
238 
239   if (buffer == NULL) {
240          ErrPostEx (SEV_ERROR, 0, 0, "fail in get_firstline [25]");
241          return NULL;
242   }
243   if (sesp1 == NULL) {
244          return buffer;
245   }
246   for (buf=buffer; buf!=NULL; buf=buf->next)
247   {
248          sesp = (SelEdStructPtr) buf->region;
249          if (is_sameId (sesp1->entityID, sesp1->itemID, sesp1->itemtype, 255, sesp->entityID, sesp->itemID, sesp->itemtype, 255) )
250             break;
251   }
252   if (buf == NULL) {
253          return buffer;
254   }
255   return buf;
256 }
257 
258 /*********************************************************************
259 ***  FindNextSegment
260 *********************************************************************/
FindNextSegment(SelEdStructPtr current)261 static SelEdStructPtr FindNextSegment (SelEdStructPtr current)
262 {
263   Uint2  ei, ii;
264   if ( current->next == NULL ) return NULL;
265   ei = current->entityID;
266   ii = current->itemID;
267   current = current->next;
268   while ( current != NULL )
269   {
270      if (current->entityID == ei &&  current->itemID == ii) break;
271      current = current->next;
272   }
273   return current;
274 }
275 
get_substring(CharPtr str,Int4 drw_start,Int4 drw_width)276 static CharPtr get_substring (CharPtr str, Int4 drw_start, Int4 drw_width)
277 {
278   Int4            width;
279   Int4            stringlens;
280   CharPtr         strp;
281 
282   if (str == NULL )
283      return NULL;
284   if (str[0]=='\0')
285      return NULL;
286   stringlens = StringLen (str);
287   if ( drw_start >= stringlens ) {
288      return NULL; }
289   strp = str + drw_start;
290   stringlens = StringLen (strp);
291   if (stringlens == 0)
292      return NULL;
293   width = MIN ((Int4) drw_width, (Int4) stringlens);
294   if ( !not_empty_string (strp, width) )
295      return NULL;
296   return strp;
297 }
298 
go_to_next_to_draw(EditAlignDataPtr adp,Boolean next,Int4 offset)299 static SelStructPtr go_to_next_to_draw (EditAlignDataPtr adp, Boolean next, Int4 offset)
300 {
301   TextAlignBufPtr  curtdp;
302   SelStructPtr     curvnp;
303   SelEdStructPtr   curssp = NULL;
304   ValNodePtr       vnp = NULL;
305   Int4             from_inbuf;  /* alignment coordinates in buffer */
306   Int4             from_inseq;  /* alignment coordinates in buffer */
307   Int4             drw_width;   /* length of drw_str */
308   Uint2            itemsubtype;
309   CharPtr          curstr = NULL;
310   Int4             offsettmp;
311 
312   if (adp->voffset == 0)
313      return adp->buffer;
314   if (offset == 0)
315      return adp->firstssp;
316   from_inseq = adp->hoffset;
317   from_inbuf = adp->hoffset - adp->bufferstart;
318   drw_width = MIN ((Int4) adp->visibleWidth, (Int4) (adp->bufferlength - from_inbuf));
319   if ( drw_width <= 0 ) {
320          return NULL;
321   }
322   curvnp = adp->buffer;
323   offsettmp = 0;
324   while (offsettmp < offset && from_inseq < adp->length)
325   {
326          curssp = (SelEdStructPtr) curvnp->region;
327          itemsubtype = curvnp->itemtype;
328          if (itemsubtype == EDITDEF_SCA)
329                 offsettmp++;
330          else if (itemsubtype == EDITDEF_SCB)
331                 offsettmp;
332          else if (curssp->itemtype ==OBJ_BIOSEQ) /*&&itemsubtype==FEATDEF_BAD)*/
333 
334          {
335                 vnp = (ValNodePtr) curssp->data;
336                 curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
337                 curstr = get_substring(curtdp->buf, from_inbuf, drw_width);
338                 if ( curstr != NULL )
339                    offsettmp++;
340          }
341          if (offsettmp < offset) {
342             if (next)
343                curvnp = curvnp->next;
344             else
345                curvnp = curvnp->prev;
346          }
347          if (offsettmp < offset && curvnp == NULL)
348          {
349             if (next) {
350                curvnp = adp->buffer;
351                adp->hoffset += adp->visibleWidth;
352                from_inbuf += drw_width;
353                from_inseq += drw_width;
354             } else {
355                curvnp = adp->buffertail;
356                adp->hoffset -= adp->visibleWidth;
357                from_inbuf -= drw_width;
358                from_inseq -= drw_width;
359             }
360             if (from_inseq >= adp->length) break;
361             if (from_inseq <= 0 || from_inbuf <= 0 || adp->hoffset<=0) break;
362             drw_width = MIN ((Int4) adp->visibleWidth,
363                 (Int4)(adp->bufferlength -(adp->hoffset -adp->bufferstart)));
364          }
365   }
366   if (from_inseq < 0 || from_inbuf < 0 || adp->hoffset<0)  {
367      adp->hoffset = adp->bufferstart;
368      return adp->buffer;
369   }
370   if (from_inseq >= adp->length)
371      return NULL;
372   return curvnp;
373 }
374 
375 
next_to_draw(EditAlignDataPtr adp,Boolean next)376 static SelStructPtr next_to_draw (EditAlignDataPtr adp, Boolean next)
377 {
378   TextAlignBufPtr  curtdp;
379   SelStructPtr     curvnp;
380   SelStructPtr     ssptmp;
381   SelEdStructPtr   curssp = NULL;
382   ValNodePtr       vnp = NULL;
383   SeqLocPtr        curslp;
384   SeqIdPtr         sip;
385   CharPtr          curstr = NULL;
386   Int4             start, stop;
387   Int4             start2, stop2;
388   Int4             from_inbuf;  /* alignment coordinates in buffer */
389   Int4             from_inseq;  /* alignment coordinates in buffer */
390   Int4             drw_width;   /* length of drw_str */
391   Int4             chklocp;
392   Uint2            itemsubtype;
393   SeqAlignPtr      salp = (SeqAlignPtr) adp->sap_align->data;
394   Boolean          empty_line;
395 
396   if (next) {
397      if ( adp->firstssp->next == NULL)
398      {
399          adp->hoffset += adp->visibleWidth;
400          return adp->buffer;
401      }
402      else {
403          ssptmp = adp->firstssp->next;
404      }
405   }
406   if (!next) {
407      if ( adp->firstssp->prev == NULL)
408      {
409          if (adp->hoffset == 0) {
410             adp->voffset = 0;
411             return adp->buffer;
412          }
413          adp->hoffset -= adp->visibleWidth;
414          ssptmp = adp->buffertail;
415      }
416      else ssptmp = adp->firstssp->prev;
417   }
418   from_inseq = adp->hoffset;
419   from_inbuf = adp->hoffset - adp->bufferstart;
420   drw_width = MIN ((Int4) adp->visibleWidth,
421                    (Int4) (adp->bufferlength - from_inbuf));
422   if ( drw_width <= 0 ) {
423          return NULL;
424   }
425   empty_line = FALSE;
426   curvnp = ssptmp;
427   while ( from_inseq < adp->length )
428   {
429          curssp = (SelEdStructPtr) curvnp->region;
430          itemsubtype = curvnp->itemtype;
431          if (itemsubtype == EDITDEF_SCA)
432                 return curvnp;
433          if (itemsubtype == EDITDEF_SCB)
434                 return curvnp;
435          if (itemsubtype == FEATDEF_TRSL)
436          {
437             if (!empty_line ) {
438              while (curssp!=NULL)
439              {
440                if (curssp->region !=NULL) {
441                   curslp = (SeqLocPtr) curssp->region;
442                   sip = SeqLocId (curslp);
443                   start2=SeqLocStart(curslp);
444                   chklocp =chkloc(sip, start2, adp->sqloc_list, &start2);
445                   start= SeqCoordToAlignCoord(start2, sip, salp, 0, chklocp);
446                   stop2=SeqLocStop(curslp);
447                   chklocp =chkloc(sip, stop2, adp->sqloc_list, &stop2);
448                   stop = SeqCoordToAlignCoord(stop2, sip, salp, 0, chklocp);
449                   if (start<=stop && start<from_inseq+drw_width && stop>from_inseq)
450                      return curvnp;
451                }
452                curssp = FindNextSegment (curssp);
453              }
454             }
455          }
456          else if (itemsubtype>=EDITDEF_RF1 && itemsubtype<=EDITDEF_RF6)
457          {
458             if (curssp->region !=NULL && !empty_line) {
459                 curslp = (SeqLocPtr) curssp->region;
460                 if ( SeqLocStop (curslp) > from_inseq && curssp->data != NULL)
461                    return curvnp;
462             }
463          }
464          else if (curssp->itemtype ==OBJ_BIOSEQ) /*&&itemsubtype==FEATDEF_BAD)*/
465 
466          {
467             if (curssp->data !=NULL) {
468                 vnp = (ValNodePtr) curssp->data;
469                 curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
470                 curstr = get_substring(curtdp->buf, from_inbuf, drw_width);
471                 if ( curstr != NULL )
472                    if (adp->draw_emptyline || (!adp->draw_emptyline && !stringhasnochar(curstr, 0, drw_width) )) {
473                       empty_line = FALSE;
474                       return curvnp;
475                    }
476                    else
477                       empty_line = TRUE;
478             }
479          }
480          else if (curssp->itemtype==OBJ_SEQFEAT && itemsubtype==FEATDEF_PROT)
481          {
482             if (curssp->data !=NULL && !empty_line) {
483                 vnp = (ValNodePtr) curssp->data;
484                 curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
485                 curstr = get_substring(curtdp->buf, from_inbuf, drw_width);
486                 if ( curstr != NULL )
487                    return curvnp;
488             }
489          }
490          else if (curssp->itemtype ==OBJ_SEQFEAT)
491          {
492             if ( !empty_line ) {
493              while (curssp!=NULL)
494              {
495                if (curssp->region !=NULL) {
496                   curslp = (SeqLocPtr) curssp->region;
497                   sip = SeqLocId (curslp);
498                   start2=SeqLocStart(curslp);
499                   chklocp =chkloc(sip, start2, adp->sqloc_list, &start2);
500                   start= SeqCoordToAlignCoord(start2, sip, salp, 0, chklocp);
501                   stop2=SeqLocStop(curslp);
502                   chklocp =chkloc(sip, stop2, adp->sqloc_list, &stop2);
503                   stop = SeqCoordToAlignCoord(stop2, sip, salp, 0, chklocp);
504                   if (start<=stop && start<from_inseq+drw_width && stop>=from_inseq)
505                      return curvnp;
506                }
507                curssp = FindNextSegment (curssp);
508              }
509             }
510          }
511          else if (itemsubtype == EDITDEF_CPL)
512          {
513             if (curssp->data !=NULL && !empty_line) {
514                 vnp = (ValNodePtr) curssp->data;
515                 curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
516                 curstr = get_substring (curtdp->buf, from_inbuf, drw_width);
517                 if ( curstr != NULL )
518                    return curvnp;
519             }
520          }
521 
522          else if( itemsubtype==SEQFEAT_GENE || itemsubtype==SEQFEAT_RNA
523               ||  itemsubtype==SEQFEAT_CDREGION)
524          {
525             if ( !empty_line ) {
526              while (curssp!=NULL)
527              {
528                if (curssp->region !=NULL) {
529                   curslp = (SeqLocPtr) curssp->region;
530                   sip = SeqLocId (curslp);
531                   start2=SeqLocStart(curslp);
532                   chklocp =chkloc(sip, start2, adp->sqloc_list, &start2);
533                   start= SeqCoordToAlignCoord(start2, sip, salp, 0, chklocp);
534                   stop2=SeqLocStop(curslp);
535                   chklocp =chkloc(sip, stop2, adp->sqloc_list, &stop2);
536                   stop = SeqCoordToAlignCoord(stop2, sip, salp, 0, chklocp);
537                   if (start<=stop && start<from_inseq+drw_width && stop>from_inseq)
538                      return curvnp;
539                }
540                curssp = FindNextSegment (curssp);
541              }
542             }
543          }
544          else {
545 /**
546             ErrPostEx (SEV_ERROR, 0, 0, "fail in next_to_draw [46] subtype %ld type %ld", (long) itemsubtype, (long) curssp->itemtype);
547 **/
548             return NULL;
549          }
550          if (next)
551             curvnp = curvnp->next;
552          else
553             curvnp = curvnp->prev;
554          if (curvnp == NULL)
555          {
556             if (next) {
557                curvnp = adp->buffer;
558                adp->hoffset += adp->visibleWidth;
559                from_inbuf += drw_width;
560                from_inseq += drw_width;
561             } else {
562                curvnp = adp->buffertail;
563                adp->hoffset -= adp->visibleWidth;
564                from_inbuf -= drw_width;
565                from_inseq -= drw_width;
566             }
567             if (from_inseq >= adp->length) break;
568             drw_width = MIN ((Int4) adp->visibleWidth,
569                 (Int4)(adp->bufferlength -(adp->hoffset -adp->bufferstart)));
570          }
571   }
572   return NULL;
573 }
574 
575 /********************************************************
576 ***  SetupScrollBar
577 ***
578 ***
579 *********************************************************/
SeqEdGetSlateScrollBar(PaneL pnl)580 extern BaR SeqEdGetSlateScrollBar (PaneL pnl)
581 {
582   EditAlignDataPtr   adp;
583 
584   if (pnl)
585   {
586      adp=GetAlignDataPanel (pnl);
587      if(adp!=NULL)
588      {
589         if (adp->vscrollbar_mode) {
590            return GetSlateVScrollBar ((SlatE)pnl);
591         }
592         return GetSlateHScrollBar ((SlatE)pnl);
593      }
594   }
595   return NULL;
596 }
597 
SeqEdGetValueScrollBar(PaneL pnl)598 extern Int4 SeqEdGetValueScrollBar (PaneL pnl)
599 {
600   return GetBarValue(SeqEdGetSlateScrollBar(pnl));
601 }
602 
SeqEdSetValueScrollBar(PaneL pnl,Int4 value)603 extern void SeqEdSetValueScrollBar (PaneL pnl, Int4 value)
604 {
605   SetBarValue(SeqEdGetSlateScrollBar(pnl), value);
606 }
607 
SeqEdCorrectBarPage(PaneL pnl,Int4 page1,Int4 page2)608 extern void SeqEdCorrectBarPage (PaneL pnl, Int4 page1, Int4 page2)
609 {
610   BaR sb;
611 
612   sb = SeqEdGetSlateScrollBar (pnl);
613   CorrectBarPage (sb, page1, page2);
614 }
615 
SeqEdCorrectBarValue(PaneL pnl,Int4 value)616 extern void SeqEdCorrectBarValue (PaneL pnl, Int4 value)
617 {
618   BaR sb;
619 
620   sb = SeqEdGetSlateScrollBar (pnl);
621   CorrectBarValue (sb, value);
622 }
623 
SeqEdCorrectBarMax(PaneL pnl,Int4 value)624 extern void SeqEdCorrectBarMax (PaneL pnl, Int4 value)
625 {
626   BaR sb;
627 
628   sb = SeqEdGetSlateScrollBar (pnl);
629   CorrectBarMax (sb, value);
630 }
631 
SeqEdSetCorrectBarMax(PaneL pnl,EditAlignDataPtr adp,float hratio)632 extern void SeqEdSetCorrectBarMax (PaneL pnl, EditAlignDataPtr adp, float hratio)
633 {
634   BaR          sb;
635   Int4         cbm = 0;
636 
637   if (adp->nlines < 11) {
638      adp->voffset = 0;
639      adp->hoffset = 0;
640      adp->firstssp = get_firstline (NULL, adp->buffer);
641   }
642   else {
643      adp->hoffset = (Int4)(hratio * (float)adp->length);
644      adp->voffset = hoffset2voffset (adp, adp->anp_list, adp->visibleWidth, 0, adp->length-1, adp->hoffset);
645   }
646 
647   if (adp->nlines < 0)
648      cbm = 0;
649   else
650      cbm = MAX ((Int4) 0, (Int4) (adp->nlines -1));
651   sb = SeqEdGetSlateScrollBar (pnl);
652   CorrectBarMax (sb, cbm);
653   SetBarValue (sb, (Int4)(adp->voffset));
654 }
655 
count_feature_buf_line(ValNodePtr fnp_list,Int4 g_left,Int4 g_right,ValNodePtr PNTR feature_line)656 static void count_feature_buf_line (ValNodePtr fnp_list, Int4 g_left, Int4 g_right, ValNodePtr PNTR feature_line)
657 {
658         FeatNodePtr fnp;
659         Int4 c_left, c_right;
660         ValNodePtr vnp;
661         Boolean found;
662 
663         if(fnp_list == NULL)
664                 return;
665 
666         while(fnp_list)
667         {
668            fnp = (FeatNodePtr)fnp_list->data.ptrvalue;
669            c_left = fnp->extremes.left;
670            c_right = fnp->extremes.right;
671            if(!(c_left > g_right || c_right < g_left))
672            {
673                 found = FALSE;
674                 for(vnp = *feature_line; vnp != NULL && !found; vnp = vnp->next)
675                 {
676                         if(vnp->data.intvalue == (Int4)(fnp->itemID))
677                                 found = TRUE;
678                 }
679                 if(!found)
680                         ValNodeAddInt(feature_line, 0, (Int4)(fnp->itemID));
681            }
682            fnp_list = fnp_list->next;
683         }
684 }
685 
CountTextAlignNodeNum(AlignNodePtr anp,Int4 m_left,Int4 m_right)686 static Int4 CountTextAlignNodeNum(AlignNodePtr anp, Int4 m_left, Int4 m_right)
687 {
688         Int4 num_line = 0;
689         Int4 g_left, g_right;
690 
691         AlignSegPtr asp;
692         ValNodePtr feature_line, curr;  /*the number of lines for a feature*/
693 
694         g_left = anp->extremes.left;
695         g_right = anp->extremes.right;
696         if(m_left > g_right || m_right < g_left)
697                 return 0;
698 
699         num_line = 1;
700         feature_line = NULL;
701 
702         /*process  the GAPs and the DIAGs segs*/
703         for(asp = anp->segs; asp !=NULL; asp = asp->next)
704         {
705            g_left = asp->gr.left;
706            g_right = asp->gr.right;
707            if(!(g_left > m_right || g_right < m_left))
708            {
709               switch(asp->type)
710               {
711                 case GAP_SEG:
712                    break;
713 
714                 case REG_SEG:
715                 case DIAG_SEG:
716                    g_left = MAX(m_left, g_left);
717                    g_right = MIN(m_right, g_right);
718                    count_feature_buf_line (asp->cnp, g_left, g_right, &feature_line);
719                    break;
720                 default:
721                    break;
722               }
723            }
724            if(g_left > m_right)
725                 break;
726         }
727         if(feature_line != NULL)
728         {
729            for(curr = feature_line; curr != NULL; curr = curr->next)
730                 ++num_line;
731            ValNodeFree(feature_line);
732         }
733 
734         return num_line;
735 }
addline_perblock(EditAlignDataPtr adp,Int4 diffs)736 static Int4 addline_perblock (EditAlignDataPtr adp, Int4 diffs)
737 {
738   Int4        line = 0;
739   ValNodePtr  vnp;
740   SeqParamPtr prm;
741   Int1        j;
742 
743   if (adp->draw_scale) line += (Int4) diffs;
744   if (adp->draw_bars)  line += (Int4) diffs;
745   for (vnp = adp->params; vnp != NULL; vnp = vnp->next)
746   {
747      prm = (SeqParamPtr) vnp->data.ptrvalue;
748      if ( prm->complement ) line += (Int4) diffs;
749      for (j=0; j<=6; j++)
750         if (prm->rf[j]) line += (Int4) diffs;
751   }
752   return line;
753 }
754 
feat_linenum(Int4 slp_start,Int4 slp_stop,Int4 line_len,Int4 left,Int4 right)755 static Int4 feat_linenum (Int4 slp_start, Int4 slp_stop, Int4 line_len, Int4 left,
756 Int4 right)
757 {
758   Int4         modstart;
759   Int4         modstop;
760 
761   slp_start = MAX (slp_start, left);
762   modstart = slp_start % line_len;
763   if ( modstart > 0) slp_start -= modstart;
764 
765   slp_stop = MIN (slp_stop, right);
766   modstop = slp_stop % line_len;
767   if ( modstop > 0) slp_stop += line_len;
768 
769   return (Int4)((slp_stop - slp_start) / line_len);
770 }
771 
CountFeatNum(ValNodePtr adpfeat,Int4 line_len,Int4 left,Int4 right)772 static Int4 CountFeatNum (ValNodePtr adpfeat, Int4 line_len, Int4 left, Int4 right){
773   ValNodePtr   vnp;
774   SelEdStructPtr sesp;
775   SeqLocPtr    slp;
776   Int4         line = 0;
777 
778   for (vnp = adpfeat; vnp != NULL; vnp = vnp->next)
779   {
780      sesp = (SelEdStructPtr) vnp->data.ptrvalue;
781      for (; sesp != NULL; sesp = sesp->next)
782      {
783         if (vnp->choice ==FEATDEF_CDS && sesp->regiontype ==OM_REGION_SEQLOC
784         && sesp->region !=NULL)
785         {
786            slp = (SeqLocPtr) sesp->region;;
787            if (SeqLocStart(slp) > right || SeqLocStop(slp) < left)
788               line+=0;
789            else {
790               line+= feat_linenum (SeqLocStart(slp), SeqLocStop(slp), line_len, left, right);
791            }
792         }
793      }
794   }
795   return line;
796 }
count_nline(EditAlignDataPtr adp,ValNodePtr anp_list,Int4 line_len,Int4 left,Int4 right,Int4 voffset)797 static Int4 count_nline (EditAlignDataPtr adp, ValNodePtr anp_list, Int4 line_len, Int4 left, Int4 right, Int4 voffset)
798 {
799         AlignNodePtr anp;
800         Int4 c_start, c_stop;
801         Int4 line_num = 0;
802         Int4 h_block = 0;
803         ValNodePtr curr;
804 
805         if(anp_list == NULL)
806                 return h_block;
807         if(voffset == 0)
808                 return h_block;
809         anp = (AlignNodePtr)anp_list->data.ptrvalue;
810         if(left == -1)
811                 left = anp->extremes.left;
812         if(right == -1)
813                 right = anp->extremes.right;
814         if(left > anp->extremes.right || right < anp->extremes.left)
815                 return h_block;
816         left = MAX(left, anp->extremes.left);
817         right = MIN(right, anp->extremes.right);
818         if (left >= right)
819                 return h_block;
820         c_start = left;
821         while(line_num < voffset)
822         {
823                 c_stop = MIN(right, (c_start+line_len-1));
824                 for(curr = anp_list; curr != NULL; curr = curr->next)
825                 {
826                         anp = (AlignNodePtr)curr->data.ptrvalue;
827                         line_num += CountTextAlignNodeNum(anp, c_start, c_stop);
828                 }
829                 line_num += (Int4) addline_perblock (adp, 1);
830                 line_num += (Int4) CountFeatNum (adp->feat, line_len, c_start, c_stop);
831                 line_num += (Int4) CountFeatNum (adp->seqfeat, line_len, c_start, c_stop);
832                 if (line_num > voffset) break;
833                 ++h_block;
834                 c_start = c_stop+1;
835         }
836   return c_start;
837 }
838 
hoffset2voffset(EditAlignDataPtr adp,ValNodePtr anp_list,Int4 line_len,Int4 left,Int4 right,Int4 hoffset)839 extern Int4 hoffset2voffset (EditAlignDataPtr adp, ValNodePtr anp_list, Int4 line_len, Int4 left, Int4 right, Int4 hoffset)
840 {
841         AlignNodePtr anp;
842         Int4 c_start, c_stop;
843         Int4 line_num = 0;
844         Int4 preline;
845         Int4 h_block = 0;
846         ValNodePtr curr;
847 
848         if(anp_list == NULL)
849                 return h_block;
850         if(hoffset == 0)
851                 return h_block;
852         anp = (AlignNodePtr)anp_list->data.ptrvalue;
853         if(left == -1)
854                 left = anp->extremes.left;
855         if(right == -1)
856                 right = anp->extremes.right;
857         if(left > anp->extremes.right || right < anp->extremes.left)
858                 return h_block;
859         left = MAX(left, anp->extremes.left);
860         right = MIN(right, anp->extremes.right);
861         if (left >= right)
862                 return h_block;
863         c_start = left;
864         while(c_start<hoffset)
865         {
866                 preline = line_num;
867                 c_stop = MIN(right, (c_start+line_len-1));
868                 for(curr = anp_list; curr != NULL; curr = curr->next)
869                 {
870                         anp = (AlignNodePtr)curr->data.ptrvalue;
871                         line_num += CountTextAlignNodeNum(anp, c_start, c_stop);
872                 }
873                 line_num += (Int4) addline_perblock (adp, 1);
874                 line_num += (Int4) CountFeatNum (adp->feat, line_len, c_start, c_stop);
875                 line_num += (Int4) CountFeatNum (adp->seqfeat, line_len, c_start, c_stop);
876                 ++h_block;
877                 c_start = c_stop+1;
878         }
879 
880 preline = line_num;
881   return preline;
882 }
883 
884 
885 /*******************************************
886 ***   Scrolling functions
887 ***
888 *** function test whether in/out buffer:
889 ***          not used
890 ***
891 ********************************************/
VscrlProc(BaR sb,SlatE s,Int4 newval,Int4 oldval)892 extern void VscrlProc (BaR sb, SlatE s, Int4 newval, Int4 oldval)
893 {
894   EditAlignDataPtr adp;
895   RecT         r;
896   Int4         pixels;
897   WindoW       tempPort;
898   Int4         temp;
899   Int4         x;
900   Int4         oldhoffset;
901 
902   if ( s == NULL ) {
903     return;
904   }
905   if ( (adp = GetAlignDataPanel ((PaneL) s)) == NULL )
906      return;
907   if ( adp->seqnumber == 0 )
908      return;
909   tempPort = SavePort ((PaneL) s);
910   Select ((PaneL) s);
911   ObjectRect ((PaneL) s, &r);
912   if ((newval > oldval && newval - oldval <= adp->vPage )
913    || (newval < oldval && oldval - newval <= adp->vPage ))
914   {
915      InsetRect (&r, HRZ_BORDER_WIDTH, VER_BORDER_WIDTH);
916      pixels = (oldval - newval) * adp->lineheight;
917      r.bottom = r.top + adp->pnlLine * adp->lineheight +1;
918      r.top = r.top + 1;
919      ScrollRect (&r, 0, pixels);
920   }
921   adp->voffset = GetBarValue (sb);
922   if (abs(newval - oldval) == 1)
923   {
924      oldhoffset = adp->hoffset;
925      temp = oldhoffset  + adp->visibleWidth + adp->visibleLength;
926      temp = MIN (temp, adp->bufferstart + adp->bufferlength);
927      if ((oldhoffset + adp->visibleWidth > adp->bufferstart
928      && temp < adp->bufferstart + adp->bufferlength)
929      || temp == adp->length)
930      {
931          adp->firstssp = next_to_draw (adp, (Boolean)((newval-oldval)>0));
932      }
933      else {
934          data_collect_arrange (adp, TRUE);
935          if (temp < adp->length)
936             InvalRect (&r);
937      }
938      if (adp->hoffset == 0 && adp->firstssp->prev == NULL && adp->voffset != 0)
939      {
940          adp->voffset = 0;
941          CorrectBarValue (sb, (Int4) 0);
942      }
943      if (adp->seqnumber == 1
944          && adp->hoffset+adp->visibleWidth>adp->length
945          && adp->voffset<adp->nlines)
946      {
947         adp->voffset = adp->nlines;
948         CorrectBarValue (sb, (Int4) adp->nlines);
949      }
950   }
951   else {
952   	 Int4 tmp;
953      x = adp->seqnumber;
954      if (adp->draw_scale) x++;
955      if (adp->draw_bars) x++;
956 
957      if (adp->showfeat)
958      {
959 	     adp->hoffset = count_nline (adp, adp->anp_list, adp->visibleWidth, 0, adp->length-1, (Int4)((FloatLo)adp->voffset));
960      }
961      else
962      {
963          if (adp->seqnumber > 1)
964      	     adp->hoffset = adp->visibleWidth * (Int4)((FloatLo)adp->voffset / (adp->seqnumber + 2));
965          else
966              adp->hoffset = adp->visibleWidth * (Int4)((FloatLo)adp->voffset);
967      }
968 
969      /* Use adp->int4value2 to disable line number counting when scrolling */
970      tmp = adp->int4value2;
971      adp->int4value2 = -1;
972      if (adp->hoffset > adp->bufferstart
973      && adp->hoffset+adp->visibleLength+ adp->visibleWidth < adp->bufferstart +adp->bufferlength)
974      {
975          data_collect_arrange (adp, FALSE);
976      } else {
977          data_collect_arrange (adp, TRUE);
978      }
979      adp->int4value2 = tmp;
980 
981      if (x == 0) {
982         adp->firstssp=go_to_next_to_draw(adp, TRUE, (Int4)0);
983      } else {
984         adp->firstssp=go_to_next_to_draw(adp, TRUE, (Int4)(adp->voffset%x));
985      }
986      InvalRect (&r);
987   }
988   RestorePort(tempPort);
989   Update ();
990 }
991 
HscrlProc(BaR sb,SlatE s,Int4 newval,Int4 oldval)992 extern void HscrlProc (BaR sb, SlatE s, Int4 newval, Int4 oldval)
993 {
994   EditAlignDataPtr adp;
995   RecT         r;
996   Int4         pixels;
997   WindoW       tempPort;
998 
999   if ( s == NULL ) {
1000     return;
1001   }
1002   if ( (adp = GetAlignDataPanel ((PaneL) s)) == NULL ) return;
1003   if ( adp->seqnumber == 0 ) return;
1004   tempPort = SavePort ((PaneL) s);
1005   Select ((PaneL) s);
1006   ObjectRect ((PaneL) s, &r);
1007   if ((newval > oldval && newval - oldval <= adp->hPage )
1008    || (newval < oldval && oldval - newval <= adp->hPage ))
1009   {
1010      InsetRect (&r, HRZ_BORDER_WIDTH, VER_BORDER_WIDTH);
1011      pixels = (oldval - newval) * adp->charw +1;
1012      ScrollRect (&r, pixels, 0);
1013   } else {
1014      InvalRect (&r);
1015   }
1016   adp->hoffset = GetBarValue (sb);
1017   RestorePort(tempPort);
1018   Update ();
1019 }
1020 
1021 /*******************************************************************
1022 ***
1023 ***    do_resize
1024 ***
1025 *******************************************************************/
do_resize_panel(PaneL pnl,EditAlignDataPtr adp,Int4 width,Int4 height,Boolean rearrange)1026 extern void do_resize_panel (PaneL pnl, EditAlignDataPtr adp, Int4 width, Int4 height, Boolean rearrange)
1027 {
1028   Int4         old_voffset;
1029   Int4         new_buffer;
1030   Int4         j;
1031   Int4         lg;
1032   Int4         old_visibleWidth;
1033   Int4         x, y;
1034   float hratio;
1035 
1036   x = (width - adp->margin.right) / adp->charw;
1037   if (x < 0)
1038      x = 0;
1039   hratio = (float)adp->hoffset / (float)adp->length;
1040   adp->pnlWidth = x;
1041   if (adp->pnlWidth < adp->marginleft + 10) {
1042      adp->firstssp = NULL;
1043      return;
1044   }
1045   x = (height - adp->margin.bottom) / adp->lineheight;
1046   if (x < 0)
1047      x = 0;
1048   adp->pnlLine = x;
1049   if (adp->pnlLine < 3) {
1050      adp->firstssp = NULL;
1051      return;
1052   }
1053   y = 0; x = 0;
1054   if (adp->columnpcell > 0) {
1055      y = (Int4) (adp->pnlWidth -adp->marginleft) / (Int4) adp->columnpcell;
1056      x = (Int4) (adp->pnlWidth -adp->marginleft -y) % (Int4)(adp->columnpcell);
1057      if (x == 9)
1058         x = -1;
1059   }
1060   old_visibleWidth = adp->visibleWidth;
1061   adp->visibleWidth = (Int4) (adp->pnlWidth -adp->marginleft -y -x);
1062   if (adp->visibleWidth < 10) {
1063      adp->firstssp = NULL;
1064      return;
1065   }
1066   if ( adp->seqnumber == 0 )
1067      return;
1068   if (old_visibleWidth != adp->visibleWidth) {
1069      old_voffset = adp->voffset;
1070      adp->voffset = (Int4)(((float)old_visibleWidth/(float)adp->visibleWidth) * (float)old_voffset);
1071   }
1072   new_buffer = adp->pnlLine * adp->visibleWidth;
1073   if (new_buffer * 3 > adp->minbufferlength)
1074   {
1075      adp->minbufferlength = new_buffer * 3;
1076      if ( adp->colonne != NULL )
1077         MemFree (adp->colonne);
1078      adp->colonne = NULL;
1079      lg = adp->minbufferlength + adp->editbuffer + 4;
1080      adp->colonne = (Int4Ptr) MemNew ((size_t) (lg * sizeof(Int4)));
1081      for (j=0; j<adp->minbufferlength +adp->editbuffer; j++) adp->colonne[j] = -1;
1082      rearrange = TRUE;
1083   }
1084   adp->vPage = /* adp->pnlLine - 1; */ 1;
1085   adp->hPage = adp->visibleWidth - 1;
1086   data_collect_arrange (adp, rearrange);
1087   SeqEdSetCorrectBarMax (pnl, adp, hratio);
1088   SeqEdCorrectBarPage (pnl, adp->vPage, adp->vPage);
1089   SeqEdCorrectBarValue (pnl, SeqEdGetValueScrollBar (pnl));
1090 }
1091 
do_resize_window(PaneL pnl,EditAlignDataPtr adp,Boolean rearrange)1092 extern void do_resize_window (PaneL pnl, EditAlignDataPtr adp, Boolean rearrange)
1093 {
1094   SeqEditViewFormPtr wdp;
1095   WindoW       w;
1096   RecT         rw;    /* window rect        */
1097   RecT         rp;    /* panel rect         */
1098   RecT         rb;    /* buttons rect       */
1099   RecT         rct;   /* new rect for panel */
1100   Int4         buttonwidth,
1101                buttonheight;
1102   Int4         x, y;
1103 
1104   w = getwindow_frompanel (pnl);
1105   wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
1106   if (wdp == NULL)
1107      return;
1108   ObjectRect (w, &rw);
1109   get_client_rect (pnl, &rp);
1110   GetPosition (pnl, &rp);
1111   x = adp->xoff;
1112   y = rw.bottom - rw.top;
1113   LoadRect ( &rct, x, adp->yoff, (Int4)(rw.right - rw.left - adp->x),
1114                                  (Int4)(y - adp->y));
1115   SetPosition (pnl, &rct );
1116   AdjustPrnt (pnl, &rct, FALSE);
1117   ObjectRect (pnl, &rp );
1118 
1119   GetPosition ((GrouP) wdp->btngp, &rb);
1120   buttonwidth  = rb.right  - rb.left;
1121   buttonheight = rb.bottom - rb.top;
1122   LoadRect (&rb, x, (Int4)(y -buttonheight - adp->ybutt - 1),
1123                      (Int4)(x+ buttonwidth), (Int4)(y-adp->ybutt-1));
1124   SetPosition(wdp->btngp, &rb);
1125   AdjustPrnt (wdp->btngp, &rb, FALSE);
1126 
1127   ResetClip ();
1128   Update ();
1129   InsetRect (&rp, 4, 4);
1130   do_resize_panel (pnl, adp, (Int4)(rp.right - rp.left), (Int4)(rp.bottom - rp.top), rearrange);
1131   return;
1132 }
1133 
1134 /***********************************************************************/
1135 /***********************************************************************/
1136 /***********************************************************************/
1137 
1138 /***********************************************************************/
1139 /***********************************************************************/
1140 /***********************************************************************/
1141 /***********************************************************************
1142 ***  Draw Scale
1143 ***         draw_scale
1144 ***         draw_bars
1145 ***
1146 ***********************************************************************/
draw_scale(EditAlignDataPtr adp,Int4 hoffset,Int4 scalelength,PoinT * ptlh)1147 static void draw_scale (EditAlignDataPtr adp, Int4 hoffset, Int4 scalelength, PoinT *ptlh)
1148 {
1149   Char   str[128];
1150   Int4   scal;
1151   Int4   ptx, pty;
1152   Int4   j;
1153   Int4   marqueediff;
1154 
1155   if ( !adp->draw_scale ) return;
1156   SetColor (adp->colorRefs[COLOR_SCALE]);
1157   ptx = ptlh->x + adp->margin.left + (Int4)(adp->charw * 0.5) - 2;
1158   pty = ptlh->y + adp->ascent;
1159   marqueediff = (Int4)( 2.00 / 6.00 * adp->lineheight);
1160   for ( j = hoffset; j < hoffset + scalelength; j++)
1161   {
1162          if ( adp->colonne[j] > -1)
1163          {
1164                 scal = (Int4)(adp->gr.left + 1 + adp->colonne[j]);
1165                 if (scal % 10 == 0)
1166                 {
1167                        sprintf (str, "%d", (int)scal);
1168                        MoveTo ((Int4)(ptx - StringWidth(str) + (adp->charw/2) +1),
1169                                (Int4)(pty + marqueediff));
1170                        PaintString (str);
1171                 }
1172          }
1173          if (adp->columnpcell > 0 && j > hoffset)
1174             if ((Int4) j % (Int4) adp->columnpcell == 0) ptx += adp->charw;
1175          ptx += adp->charw;
1176   }
1177   Black();
1178   return ;
1179 }
1180 
draw_bars(EditAlignDataPtr adp,Int4 hoffset,Int4 scalelength,PoinT * ptlh)1181 static void draw_bars (EditAlignDataPtr adp, Int4 hoffset, Int4 scalelength, PoinT *ptlh)
1182 {
1183   Int4   scal;
1184   Int4   ptx;
1185   Int4   y;
1186   Int4   j;
1187   Int4   marqueelong, marqueeshort, marqueediff;
1188 
1189   if ( !adp->draw_bars ) return;
1190   SetColor (adp->colorRefs[COLOR_SCALE]);
1191   ptx = ptlh->x + adp->margin.left + (Int4)(adp->charw * 0.5) - 1;
1192   y = ptlh->y + (Int4) (2.00 / 6.00 * adp->lineheight);
1193   marqueelong = (Int4) (4.00 / 6.00 * adp->lineheight);
1194   marqueeshort= (Int4) (2.00 / 6.00 * adp->lineheight);
1195   marqueediff = (Int4) (2.00 / 6.00 * adp->lineheight);
1196   for ( j = hoffset; j < hoffset + scalelength; j++)
1197   {
1198          if ( adp->colonne[j] > -1)
1199          {
1200                 scal = (Int4)(adp->gr.left + 1 + adp->colonne[j]);
1201                 if (scal % 10 == 0)
1202                 {
1203                        MoveTo (ptx , y );
1204                        LineTo (ptx , (Int4)(y + marqueelong));
1205                 }
1206                 else if (scal % 5 == 0)
1207                 {
1208                        MoveTo (ptx , (Int4)(y + marqueediff));
1209                        LineTo (ptx , (Int4)(y + marqueediff + marqueeshort));
1210                 }
1211          }
1212          if (adp->columnpcell > 0 && j > hoffset)
1213             if ((Int4) j % (Int4) adp->columnpcell == 0) ptx += adp->charw;
1214          ptx += adp->charw;
1215   }
1216   Black();
1217   return ;
1218 }
1219 
1220 /***********************************************************************
1221 ***  draw_id
1222 ************************************************************************/
draw_id(EditAlignDataPtr adp,PoinT * pt,Int4 index,CharPtr strid,Uint1 strand,Int4 pos,Uint2 itemtype,Boolean idselected,Boolean is_master,Int4 group)1223 static void draw_id (EditAlignDataPtr adp, PoinT *pt, Int4 index, CharPtr strid, Uint1 strand, Int4 pos, Uint2 itemtype, Boolean idselected, Boolean is_master, Int4 group)
1224 {
1225   Char     str[128], str1[128];
1226   RecT     rct;
1227   CharPtr  tmp;
1228   Int4     stringlens;
1229   Int4     j;
1230   Int4     total = 0;
1231   Int4     posspace;
1232 
1233   /*!!!!!!!!!!!!!!!!!!!!!!!!!!*/ idselected = FALSE;
1234 
1235   if (adp->length < 1000) { posspace = 4;
1236   } else if (adp->length < 10000) { posspace = 5;
1237   } else if (adp->length < 100000) { posspace = 6;
1238   } else if (adp->length < 1000000) { posspace = 7;
1239   } else { posspace = 8;
1240   }
1241 
1242   if (adp->marginwithindex) total += 3;
1243   if (adp->marginwithgroup) total += 4;
1244   if (adp->marginwithpos) total += posspace;
1245   total += 2;
1246 
1247   str[0] = '\0';
1248   tmp = str;
1249   if (adp->marginwithindex && index > 0) {
1250      sprintf (str1, "%3d ",(int) index);
1251   } else {
1252      sprintf (str1, " ");
1253   }
1254   tmp = StringMove (tmp, str1);
1255   tmp[0] = '\0';
1256 
1257   adp->marginwithgroup = FALSE;
1258   if (adp->marginwithgroup) {
1259      if (group >= 0)
1260         sprintf (str1, "%4d ",(int) group);
1261      else sprintf (str1, "    ");
1262      tmp = StringMove (tmp, str1);
1263      tmp[0] = '\0';
1264   }
1265 
1266   if (strid != NULL && strid[0]!='\0') {
1267      stringlens = (Int4)(StringLen (strid));
1268 /******!!!!!!!!!!!!!!!
1269      if (stringlens > 4) {
1270          if (strid[0] == 'l' && strid[1] == 'c' && strid[2] == 'l') {
1271             strid += 4;
1272             stringlens -= 4;
1273          }
1274      }
1275 !!!!!!!!!!!!!!!!!*********/
1276      for (j=0; j<stringlens; j++)
1277         str1 [j] = strid [j];
1278      str1 [j] = '\0';
1279      if (stringlens < adp->size_labels) {
1280         for (j=stringlens; j<adp->size_labels; j++)
1281               str1 [j] = ' ';
1282         str1 [j] = '\0';
1283         stringlens = (Int4)(StringLen (str1));
1284      }
1285      stringlens = MIN (adp->marginleft - total, stringlens);
1286      str1 [stringlens] = '\0';
1287      tmp = StringMove (tmp, str1);
1288   }
1289   else if (adp->marginleft > 20) {
1290      sprintf (str1, "          ");
1291      tmp = StringMove (tmp, str1);
1292   }
1293 /*
1294   symbol[0] = ' ';
1295   if (strand == Seq_strand_minus)
1296      symbol[1] = '<';
1297   else
1298      symbol[1] = '>';
1299   symbol[2] = '\0';
1300   tmp = StringMove (tmp, symbol);
1301 */
1302   if (adp->marginwithpos) {
1303      if (posspace <= 4) {
1304         if (pos > 0)
1305            sprintf (str1, "%4ld ", (long) pos);
1306         else sprintf (str1, "     ");
1307      } else if (posspace == 5) {
1308         if (pos > 0)
1309            sprintf (str1, "%5ld ", (long) pos);
1310         else sprintf (str1, "      ");
1311      } else if (posspace == 6) {
1312         if (pos > 0)
1313            sprintf (str1, "%6ld ", (long) pos);
1314         else sprintf (str1, "       ");
1315      } else {
1316         if (pos > 0)
1317            sprintf (str1, "%7ld ", (long) pos);
1318         else sprintf (str1, "        ");
1319      }
1320      tmp = StringMove (tmp, str1);
1321   }
1322   *tmp = '\0';
1323 
1324   stringlens = (Int4)(StringLen(str));
1325   if (stringlens < adp->marginleft -1)
1326          for (j = stringlens; j < adp->marginleft; j++, tmp++)
1327             *tmp = ' ';
1328   str [adp->marginleft -1] = ' ';
1329   str [adp->marginleft] = '\0';
1330   if ( itemtype != OBJ_BIOSEQ && adp->displaytype )
1331          SelectColor (162, 163, 82);
1332   else if (is_master && !adp->all_sequences)
1333          SetColor (adp->colorRefs[COLOR_ID_MASTER]);
1334   else
1335          SetColor (adp->colorRefs[COLOR_ID]);
1336   if ( !idselected )
1337   {
1338 Black();
1339          MoveTo (pt->x, (Int4)(pt->y + adp->ascent));
1340          PaintString (str);
1341   }
1342   else  {
1343          InvertColors ();
1344          LoadRect(&rct, pt->x, pt->y, (Int4)(pt->x +stringlens *adp->charw -2),
1345                          (Int4)(pt->y + adp->lineheight));
1346          EraseRect (&rct);
1347          MoveTo (pt->x, (Int4)(pt->y +adp->ascent));
1348          PaintString (str);
1349          InvertColors();
1350   }
1351   Black();
1352   return;
1353 }
1354 
1355 /******************************************************************
1356 ***      paint_caret,  draw caret : draws caret
1357 ***
1358 *** Now caret is a T between basis of letters
1359 *** Before it was a bar between letters:
1360 
1361   pt1.x = pt.x + ( column + marginleft ) * charw -1;
1362   pt1.y = pt.y;
1363   pt2.x = pt1.x;
1364   pt2.y = pt1.y + lineheight -2;
1365 ***
1366 *******************************************************************/
paint_caret(PoinT pt,Int4 column,Int4 charw,Int4 lineheight,Int4 marginleft)1367 static void paint_caret (PoinT pt, Int4 column, Int4 charw, Int4 lineheight, Int4 marginleft)
1368 {
1369   PoinT pt1, pt2;
1370   Int4  lenv = 3;
1371   Int4  lenh = 2;
1372   Int4  row;
1373 
1374   Red ();
1375   WidePen (2);
1376   row = pt.x + ( column + marginleft ) * charw -1;
1377   pt1.x = row;
1378   pt1.y = pt.y  + lineheight -1;
1379   pt2.x = row;
1380   pt2.y = pt1.y  -lenv;
1381   DrawLine (pt1, pt2);
1382   pt2.x = row +lenh;
1383   pt2.y = pt1.y;
1384   DrawLine (pt1, pt2);
1385   pt2.x = row -lenh;
1386   pt2.y = pt1.y;
1387   DrawLine (pt1, pt2);
1388   WidePen (1);
1389   Black ();
1390 }
1391 
draw_caret(EditAlignDataPtr adp,SelEdStructPtr sesp,PoinT pt,Int4 line)1392 static void draw_caret (EditAlignDataPtr adp, SelEdStructPtr sesp, PoinT pt, Int4 line)
1393 {
1394   SeqLocPtr    slp;
1395   Int4         column;
1396 
1397   if (!adp->display_panel)
1398   {
1399      if ( is_samess_ses (&(adp->caret), sesp))
1400      {
1401         slp = (SeqLocPtr) adp->caret.region;
1402         if(SeqPosInLineColumn (SeqLocStart(slp), adp->alignline[line], &column, adp->hoffset, adp) )
1403         {
1404            paint_caret (pt, column, adp->charw, adp->lineheight, adp->marginleft);
1405         }
1406      }
1407   }
1408 }
1409 
1410 /*********************************************************************
1411 ***      PaintSubseq : paint visible sequence
1412 **********************************************************************/
1413 /*browse a structure to find out the colour number idx (zero-based)
1414  seq_color is a field in MediaInfo structure; see cn3dmsg.h*/
1415 
GiveClrFromIdx(Int4 idx,ValNodePtr seq_color)1416 static ResidueColorCellPtr GiveClrFromIdx(Int4 idx,ValNodePtr seq_color)
1417 {
1418 Int4  i;
1419 
1420 	i=0;
1421 	while(seq_color){
1422 		if (i==idx) {
1423 			return((ResidueColorCellPtr)seq_color->data.ptrvalue);
1424 		}
1425 		seq_color=seq_color->next;
1426 		i++;
1427 	}
1428 
1429    return NULL;
1430 }
1431 
PaintSubseq(Int4 k,Int4 lg,Int4 from,PoinT * pt,CharPtr vstr,Boolean invert,EditAlignDataPtr adp,Boolean draw_diff,CharPtr * masterstr,Boolean cmplt,ValNodePtr seq_color,SeqIdPtr sip)1432 static void PaintSubseq (Int4 k, Int4 lg, Int4 from, PoinT *pt, CharPtr vstr, Boolean invert, EditAlignDataPtr adp, Boolean draw_diff, CharPtr *masterstr, Boolean cmplt, ValNodePtr seq_color,SeqIdPtr sip)
1433 {
1434   CharPtr      strPtr;
1435   Char         str[512];
1436   Uint4        curColor;
1437   Int4         to = k + lg;
1438   Int4         caret_color = 0;
1439   CharPtr      masterstrptr = NULL;
1440   RecT         rct;
1441   Uint4        blackColor = GetColorRGB(0,0,0), whiteColor = GetColorRGB(255, 255, 255),
1442                newColor;
1443 
1444   Boolean      pretty = (Boolean) (seq_color!=NULL);
1445   ResidueColorCellPtr rgb;
1446   Int4 from2;
1447 
1448   dashedstring ((CharPtr) str, 512);
1449   strPtr = str;
1450 
1451   if (pretty) {
1452   	from2=AlignCoordToSeqCoord (from, sip,
1453 			(SeqAlignPtr)adp->sap_align->data, adp->sqloc_list, 0);
1454 
1455 	if (from2!=GAP_RESIDUE)
1456 		rgb=GiveClrFromIdx(from2,seq_color);
1457 	else rgb=NULL;
1458 
1459 
1460 	if(rgb != NULL ){
1461 	   curColor = GetColorRGB (rgb->rgb[0], rgb->rgb[1],rgb->rgb[2]);
1462     }
1463     else curColor =blackColor;
1464   }
1465   else {
1466      curColor = adp->colorRefs[(Uint1)(vstr[k] - '*')];
1467   }
1468   if (curColor == (Uint4)172)
1469      curColor = blackColor;
1470 
1471   if (masterstr != NULL) {
1472      if (*masterstr != NULL)
1473         masterstrptr = *masterstr;
1474   }
1475 
1476   while ( k < to )
1477   {
1478      if (pretty) {
1479 		from2=AlignCoordToSeqCoord (k+from, sip,
1480 				(SeqAlignPtr)adp->sap_align->data, adp->sqloc_list, 0);
1481 
1482 		if (from2!=GAP_RESIDUE)
1483 			rgb=GiveClrFromIdx(from2,seq_color);
1484 		else rgb=NULL;
1485 
1486     	if(rgb != NULL ){
1487 		   newColor= GetColorRGB (rgb->rgb[0], rgb->rgb[1],rgb->rgb[2]);
1488     	}
1489     	else newColor=blackColor ;
1490 		if (vstr[k] == '-') newColor=blackColor ;
1491      }
1492      else {
1493         newColor = adp->colorRefs[(Uint1)(vstr[k] - '*')];
1494      }
1495 /*   if (newColor == (Uint4)172)
1496         newColor = blackColor; */
1497                              /* yanli comment it out so that residues */
1498                             /* with magenta color can be seen in salsa */
1499      if (newColor == whiteColor) newColor = blackColor;
1500                             /* yanli added this so that residues colored with white */
1501        /* in Cn3D(with color by Domain) are drawn as black in salsa to be visible */
1502 
1503      if ( adp->colonne [from +k -adp->bufferstart] < 0 )
1504      {
1505         *strPtr = 0;
1506         strPtr = str;
1507         if (cmplt)
1508            strPtr = complement_string (strPtr);
1509         MoveTo ((Int4)(pt->x +adp->margin.left), (Int4)(pt->y + adp->ascent));
1510 	PaintString (strPtr);
1511         pt->x += caret_color * adp->charw;
1512         caret_color = 1;
1513         strPtr = str;
1514         Black();
1515         if ((from +k -adp->bufferstart) > adp->length)
1516            return;
1517         pt->x += adp->intersalpwidth * adp->charw;
1518         k += adp->intersalpwidth;
1519         SetColor (curColor);
1520      }
1521      else if (curColor != newColor)
1522      {
1523         *strPtr = 0;
1524         strPtr = str;
1525         if (cmplt)
1526            strPtr = complement_string (strPtr);
1527         MoveTo ((Int4)(pt->x +adp->margin.left), (Int4)(pt->y +adp->ascent));
1528         if (invert)
1529         {
1530            SetColor (adp->colorRefs[COLOR_SELECT]);
1531            InvertColors ();
1532            LoadRect (&rct, (Int4)(pt->x+adp->margin.left), pt->y, (Int4)(pt->x +adp->margin.left+ caret_color*adp->charw), (Int4)(pt->y +adp->lineheight -1));
1533            EraseRect (&rct);
1534            InvertColors ();
1535            if (adp->colorRefs[COLOR_SELECT]==blackColor)
1536               White();
1537            else  {
1538               Black ();
1539            }
1540         }
1541         else {
1542            SetColor (curColor);
1543         }
1544         PaintString (strPtr);
1545         pt->x += caret_color *adp->charw;
1546         caret_color = 1;
1547         strPtr = str;
1548         if ( draw_diff && masterstrptr != NULL )
1549         {
1550            if (vstr[k] !='-') {
1551               if (ISA_na(adp->mol_type)) {
1552                  if ((*masterstrptr == vstr[k]) && (vstr[k]<65 || vstr[k]>91))
1553                     *strPtr = '.';
1554                  else
1555                    *strPtr = vstr[k];
1556               }
1557               else {
1558                  if (TO_LOWER(*masterstrptr) == TO_LOWER(vstr[k])) {
1559                     *strPtr = '.';
1560                  } else {
1561                     *strPtr = vstr[k];
1562                  }
1563               }
1564            }
1565            else
1566               *strPtr = vstr[k];
1567            masterstrptr++;
1568         }
1569         else
1570            *strPtr = vstr[k];
1571         strPtr++;
1572         if (adp->columnpcell > 0)
1573         {
1574            if ((Int4) (k+1) % (Int4) adp->columnpcell == 0) {
1575               *strPtr = ' ';
1576               strPtr++;
1577               caret_color++;
1578            }
1579         }
1580         curColor = newColor;
1581         k++;
1582      }
1583      else {
1584         if ( draw_diff && masterstrptr != NULL )
1585         {
1586            if (vstr[k] !='-') {
1587               if (ISA_na(adp->mol_type)) {
1588                  if ((*masterstrptr == vstr[k]) && (vstr[k]<65 || vstr[k]>91))
1589                     *strPtr = '.';
1590                  else
1591                     *strPtr = vstr[k];
1592               }
1593               else {
1594                  if (TO_LOWER(*masterstrptr) == TO_LOWER(vstr[k])) {
1595                     *strPtr = '.';
1596                  } else {
1597                     *strPtr = vstr[k];
1598                  }
1599               }
1600            }
1601            else
1602               *strPtr = vstr[k];
1603            masterstrptr++;
1604         }
1605         else
1606            *strPtr = vstr[k];
1607         strPtr++;
1608         caret_color++;
1609         if (adp->columnpcell > 0)
1610         {
1611            if ((Int4) (k+1) % (Int4) adp->columnpcell == 0)
1612            {
1613               *strPtr = ' ';
1614               strPtr++;
1615               caret_color++;
1616            }
1617         }
1618         k++;
1619      }
1620   }
1621   *strPtr = 0;
1622   strPtr = str;
1623   if (cmplt)
1624      strPtr = complement_string (strPtr);
1625   MoveTo ((Int4)(pt->x +adp->margin.left), (Int4)(pt->y +adp->ascent));
1626   if (invert)
1627   {
1628      SetColor (adp->colorRefs[COLOR_SELECT]);
1629      InvertColors ();
1630      LoadRect (&rct, (Int4)(pt->x+adp->margin.left), pt->y, (Int4)(pt->x +adp->margin.left+ caret_color*adp->charw), (Int4)(pt->y +adp->lineheight -1));
1631      EraseRect (&rct);
1632      InvertColors ();
1633      if(adp->colorRefs[COLOR_SELECT]==blackColor)
1634         White();
1635      else {
1636         Black ();
1637      }
1638   }
1639   else {
1640      SetColor (curColor);
1641   }
1642   PaintString (strPtr);
1643   Black ();
1644   pt->x += caret_color *adp->charw;
1645   *masterstr = masterstrptr;
1646   return;
1647 }
1648 
1649 /*****************************************************************
1650 ***  draw_seq
1651 ******************************************************************/
deleteseqloc(ValNodePtr head,ValNodePtr delp)1652 static ValNodePtr deleteseqloc (ValNodePtr head,  ValNodePtr delp)
1653 {
1654   ValNodePtr next = NULL,
1655              pre = NULL,
1656              tmp = NULL;
1657 
1658   tmp = head;
1659   while (tmp!=NULL)
1660   {
1661      next = tmp->next;
1662      if (tmp == delp)
1663      {
1664         if (pre==NULL) {
1665            head = next;
1666         }
1667         else {
1668            pre->next = next;
1669         }
1670         tmp->next = NULL;
1671         SeqLocFree ((SeqLocPtr)tmp->data.ptrvalue);
1672         tmp->data.ptrvalue = NULL;
1673         ValNodeFree (tmp);
1674      }
1675      else
1676         pre = tmp;
1677      tmp = next;
1678   }
1679   return head;
1680 }
1681 
1682 
simplifySeqLocList(ValNodePtr valnode)1683 static ValNodePtr simplifySeqLocList (ValNodePtr valnode)
1684 {
1685   ValNodePtr   vnpa = NULL,
1686                vnpb = NULL;
1687   SeqLocPtr    slpa,
1688                slpb;
1689   SeqIntPtr    sint;
1690   Boolean      check = TRUE,
1691                loopin = TRUE;
1692 
1693   while (check)
1694   {
1695      check = FALSE;
1696      loopin = TRUE;
1697      vnpa = valnode;
1698      while (vnpa != NULL && loopin)
1699      {
1700            for (vnpb = vnpa->next; vnpb != NULL; vnpb = vnpb->next)
1701            {
1702                  slpa = (SeqLocPtr)vnpa->data.ptrvalue;
1703                  slpb = (SeqLocPtr)vnpb->data.ptrvalue;
1704                  if (SeqLocCompare (slpa, slpb) == SLC_A_IN_B) {
1705                     valnode = deleteseqloc (valnode, vnpa);
1706                     check = TRUE;
1707                     loopin = FALSE;
1708                     break;
1709                  }
1710                  else if (SeqLocCompare (slpa, slpb) == SLC_B_IN_A) {
1711                     valnode = deleteseqloc (valnode, vnpb);
1712                     check = TRUE;
1713                     loopin = FALSE;
1714                     break;
1715                  }
1716                  else if (SeqLocCompare (slpa, slpb) == SLC_A_EQ_B) {
1717                     valnode = deleteseqloc (valnode, vnpb);
1718                     check = TRUE;
1719                     loopin = FALSE;
1720                     break;
1721                  }
1722                  else if (SeqLocCompare (slpa, slpb) == SLC_A_OVERLAP_B) {
1723                     sint = (SeqIntPtr) slpa->data.ptrvalue;
1724                     if (SeqLocStart(slpa) < SeqLocStart(slpb)) {
1725                        sint->to = SeqLocStop(slpb);
1726                     }
1727                     else {
1728                        sint = (SeqIntPtr) slpa->data.ptrvalue;
1729                        sint->from = SeqLocStart(slpb);
1730                     }
1731                     valnode = deleteseqloc (valnode, vnpb);
1732                     check = TRUE;
1733                     loopin = FALSE;
1734                     break;
1735                  }
1736                  else if (SeqLocStop(slpa) == SeqLocStart(slpb)-1) {
1737                     sint = (SeqIntPtr) slpa->data.ptrvalue;
1738                     sint->to = SeqLocStop(slpb);
1739                     valnode = deleteseqloc (valnode, vnpb);
1740                     check = TRUE;
1741                     loopin = FALSE;
1742                     break;
1743                  }
1744                  else if (SeqLocStart(slpa) == SeqLocStop(slpb)+1) {
1745                     sint = (SeqIntPtr) slpa->data.ptrvalue;
1746                     sint->from = SeqLocStart(slpb);
1747                     valnode = deleteseqloc (valnode, vnpb);
1748                     check = TRUE;
1749                     loopin = FALSE;
1750                     break;
1751                  }
1752            }
1753            if (loopin && vnpa != NULL)
1754               vnpa = vnpa->next;
1755      }
1756   }
1757   return valnode;
1758 }
1759 
1760 
getnextpos(ValNodePtr vnp,Int4 * stop)1761 static Int4 getnextpos (ValNodePtr vnp, Int4 *stop)
1762 {
1763   ValNodePtr tmp;
1764   SeqLocPtr  slp;
1765   SeqIntPtr  sint;
1766   Int4       valmin = (Int4)(INT4_MAX-2),
1767              val = (Int4)-1,
1768              val2 = (Int4)-1;
1769 
1770   for (tmp=vnp; tmp!=NULL; tmp=tmp->next)
1771   {
1772      slp = (SeqLocPtr) tmp->data.ptrvalue;
1773      if (SeqLocStart(slp) < valmin) {
1774         valmin = SeqLocStart(slp);
1775      }
1776   }
1777   if (valmin < (Int4)(INT4_MAX-2))
1778   {
1779      for (tmp=vnp; tmp!=NULL; tmp=tmp->next)
1780      {
1781         slp = (SeqLocPtr) tmp->data.ptrvalue;
1782         if (SeqLocStart(slp) == valmin) {
1783            val = SeqLocStart(slp);
1784            val2 = SeqLocStop (slp);
1785            sint = (SeqIntPtr) slp->data.ptrvalue;
1786            sint->from = INT4_MAX;
1787            sint->to = INT4_MAX;
1788            break;
1789         }
1790      }
1791   }
1792   *stop = val2;
1793   return val;
1794 }
1795 
draw_seq(EditAlignDataPtr adp,SelEdStructPtr sesp,Int4 from,Int4 drw_width,PoinT ptlh,CharPtr drw_str,Boolean draw_diff,CharPtr masterstr,Boolean cplmt,Uint2 itemtype,Boolean check_selection)1796 static void draw_seq (EditAlignDataPtr adp, SelEdStructPtr sesp, Int4 from, Int4 drw_width, PoinT ptlh, CharPtr drw_str, Boolean draw_diff, CharPtr masterstr, Boolean cplmt, Uint2 itemtype, Boolean check_selection)
1797 {
1798   SelStructPtr  ssptmp;
1799   SeqIdPtr      sip;
1800   Int4          start, stop;
1801   Int4          left, right;
1802   Int4          seg_lg;
1803   Int4          k,
1804                 k1;
1805   Int4          chklocp;
1806   Int4          iCount = 0;
1807   SeqLocPtr     slp;
1808   ValNodePtr    startp = NULL;
1809 
1810 SeqIdPtr sesp_sip= NULL;
1811 SeqIntPtr sinp = NULL;
1812 
1813 	SeqEditViewProcsPtr svpp;
1814 	ValNodePtr          vnp_seqinfo;
1815 	ValNodePtr          vnp_color = NULL;
1816 	SeqIdPtr            vnpcn3d_sip = NULL;
1817 	MediaInfoPtr        MIPtr;
1818 
1819 
1820   adp->start_select = -1;
1821   start = stop = -1;
1822   ssptmp = NULL;
1823   if (check_selection)
1824   {
1825     ssptmp = ObjMgrGetSelected ();
1826     for (; ssptmp != NULL; ssptmp = ssptmp->next)
1827     {
1828      if ( checkssp_for_editor (ssptmp) && is_samess_ses (ssptmp, sesp) )
1829      {
1830          sip = SeqLocId ((SeqLocPtr) ssptmp->region);
1831          start = SeqLocStart ((SeqLocPtr) ssptmp->region);
1832          adp->start_select = start;
1833          chklocp =chkloc(sip, start, adp->sqloc_list, &start);
1834          start = SeqCoordToAlignCoord (start, sip, (SeqAlignPtr) adp->sap_align->data, 0, chklocp);
1835          stop  = SeqLocStop  ((SeqLocPtr) ssptmp->region);
1836          chklocp =chkloc(sip, stop, adp->sqloc_list, &stop);
1837          stop = SeqCoordToAlignCoord (stop, sip, (SeqAlignPtr) adp->sap_align->data, 0, chklocp);
1838 /******
1839          if (start<=stop && (start < from + drw_width && (stop + 1) > from))
1840 ******/
1841          if ((start < from + drw_width && (stop + 1) > from))
1842          {
1843             if(start<=stop)
1844                slp = SeqLocIntNew (start, stop, Seq_strand_plus, sip);
1845             else
1846                slp = SeqLocIntNew (stop, start, Seq_strand_plus, sip);
1847             ValNodeAddPointer (&startp, 0, (Pointer)slp);
1848             iCount ++;
1849          }
1850      }
1851     }
1852   }
1853 
1854 
1855   svpp = (SeqEditViewProcsPtr) GetAppProperty ("SeqEditDisplayForm");
1856 
1857   if(sesp->regiontype == 1){
1858      slp = (SeqLocPtr)sesp->region;
1859      sinp = (SeqIntPtr)slp->data.ptrvalue;
1860      sesp_sip = sinp->id;
1861   }
1862   if (svpp) {
1863      if (svpp->Cn3D_On && sesp_sip) {
1864 	vnp_seqinfo = svpp->seqinfo;
1865 
1866 	while(vnp_seqinfo){
1867 		MIPtr=(MediaInfoPtr)vnp_seqinfo->data.ptrvalue;
1868 /*      if (MIPtr->entityID==sesp->entityID && MIPtr->itemID==sesp->itemID){
1869 			vnp_color=MIPtr->seq_color;
1870                         vnpcn3d_sip = MIPtr->sip;
1871   	        break;
1872 		}         */    /* yanli comment it out, instead doing the following */
1873 
1874         if(SeqIdForSameBioseq(sesp_sip, MIPtr->sip)){
1875            vnp_color=MIPtr->seq_color;
1876            vnpcn3d_sip = MIPtr->sip;
1877                      /* do not break so as to get the latest one */
1878         }
1879 		vnp_seqinfo=vnp_seqinfo->next;
1880 	}
1881      }
1882   }
1883   if (iCount > 0) {
1884      k = 0;
1885      k1 = from;
1886      startp = simplifySeqLocList (startp);
1887      start = getnextpos (startp, &stop);
1888      while ( k < drw_width && start >= 0) {
1889         if ( k + from < start )
1890         {
1891            left = (Int4) k1;
1892            right= start;
1893            seg_lg = MIN (right - left, drw_width);
1894            PaintSubseq (k, seg_lg, from, &ptlh, drw_str, FALSE, adp, draw_diff, &masterstr, cplmt, vnp_color,vnpcn3d_sip);
1895            k += seg_lg;
1896         }
1897         else if ( k +from >= start && k +from < stop + 1)
1898         {
1899            left = (Int4) MAX (k1, start);
1900            right= (Int4) MIN (from + drw_width, stop + 1);
1901            seg_lg = MIN (right - left, drw_width);
1902            PaintSubseq (k, seg_lg, from,  &ptlh, drw_str, TRUE, adp, draw_diff, &masterstr, cplmt, vnp_color,vnpcn3d_sip);
1903            k += seg_lg;
1904            k1 = stop + 1;
1905            start = getnextpos (startp, &stop);
1906         }
1907      }
1908      if ( k < drw_width)
1909      {
1910         left = (Int4) k1;
1911         right= (Int4) from + drw_width;
1912         seg_lg = MIN (right - left, drw_width);
1913         PaintSubseq (k, seg_lg, from,  &ptlh, drw_str, FALSE, adp, draw_diff, &masterstr, cplmt, vnp_color,vnpcn3d_sip);
1914      }
1915   }
1916   else {
1917      PaintSubseq (0, drw_width, from, &ptlh, drw_str, FALSE, adp, draw_diff, &masterstr, cplmt, vnp_color,vnpcn3d_sip);
1918   }
1919   if (startp != NULL)
1920      ValNodeFree (startp);
1921   return;
1922 }
1923 
1924 /*****************************************************************
1925 ***  draw_line
1926 ******************************************************************/
draw_line(EditAlignDataPtr adp,Int4 start,Int4 stop,Uint1 strand,PoinT * pt,Int4 from,Int4 drw_width,Int4 line,Int4 alignline,Uint4 color,Uint2 wideline,Boolean selected,Boolean partialstart,Boolean partialstop,BoolPtr gapline)1927 static void draw_line (EditAlignDataPtr adp, Int4 start, Int4 stop, Uint1 strand, PoinT *pt, Int4 from, Int4 drw_width, Int4 line, Int4 alignline, Uint4 color, Uint2 wideline, Boolean selected, Boolean partialstart, Boolean partialstop, BoolPtr gapline)
1928 {
1929   PoinT         pt1, pt2,
1930                 pttmp;
1931   PoinT         oldpt1, oldpt2;
1932   FloatLo       hgt = (FloatLo)(2.5 / 4.0);
1933   RecT          leftrct, rightrct;
1934   Int4          left, right;
1935   Int4          yline;
1936   Int4          column;
1937   Int4          above, below;
1938   Int4          j, k;
1939   Int4          col1;
1940   Uint1         startin, stopin;
1941   BoolPtr       gap;
1942 
1943   left = (Int4) MAX ((Int4) from, (Int4) start);
1944   SeqPosInLineColumn (left, alignline, &column, adp->hoffset, adp);
1945   yline = pt->y + (Int4) (hgt * adp->ascent);
1946   pt1.x = pt->x + (column + adp->marginleft) * adp->charw;
1947   pt1.y = yline;
1948 
1949   if (adp->columnpcell > 0) {
1950      col1 = column - (column-1)/adp->columnpcell;
1951   }
1952   right = (Int4) MIN ((Int4)from+drw_width-1, (Int4)stop);
1953   SeqPosInLineColumn (right, alignline, &column, adp->hoffset, adp);
1954   pt2.x = pt->x + (column + adp->marginleft + 1) * adp->charw;
1955   pt2.y = yline;
1956 
1957   startin = stopin = 0;
1958   if ( start >= from ) {
1959      if (strand == Seq_strand_minus)
1960         startin = 1;
1961      else
1962         startin = 2;
1963   }
1964   if (stop < from+drw_width && stop != start) {
1965      if (strand == Seq_strand_minus)
1966         stopin = 1;
1967      else
1968         stopin = 2;
1969   }
1970   oldpt1.x = pt1.x;
1971   oldpt1.y = pt1.y;
1972   oldpt2.x = pt2.x;
1973   oldpt2.y = pt2.y;
1974   if (start<stop) {
1975    if (startin)
1976      pt1.x += 5;
1977 
1978    SetColor (color);
1979    if (gapline == NULL) {
1980      if (stopin)
1981         pt2.x -= 5;
1982      WidePen (wideline);
1983      DrawLine (pt1, pt2);
1984    }
1985    else {
1986      pttmp.y = yline;
1987      j=k=left;
1988      for (j=0, gap=gapline; j<col1; j++)
1989         gap++;
1990      while (j<right) {
1991         if (*gap) {
1992            while (*gap && k<right) {
1993               gap++;
1994               k++;
1995            }
1996            WidePen (1);
1997            Dashed ();
1998         }
1999         else {
2000            while (!(*gap) && k<right) {
2001               gap++;
2002               k++;
2003            }
2004            WidePen (wideline);
2005         }
2006         SeqPosInLineColumn (k, alignline, &column, adp->hoffset, adp);
2007         if (k==right && stopin == 0)  {
2008            column++;
2009         }
2010         pttmp.x = pt->x + (column + adp->marginleft) * adp->charw;
2011         DrawLine (pt1, pttmp);
2012         Solid ();
2013         pt1.x = pttmp.x;
2014         j = k;
2015      }
2016    }
2017   }
2018   if (selected) {
2019 #ifdef WIN_MAC
2020          above = 2;
2021          below = 4;
2022 #endif
2023 #ifdef WIN_MSWIN
2024          above = 3;
2025          below = 3;
2026 #endif
2027 #ifdef WIN_MOTIF
2028          above = 3;
2029          below = 3;
2030 #endif
2031          WidePen (1);
2032          Black ();
2033          pt1.y = pt2.y = yline + below;
2034          DrawLine (pt1, pt2);
2035          pt1.y = pt2.y = yline - above;
2036          DrawLine (pt1, pt2);
2037          White ();
2038          pt1.y = pt2.y = yline + below - 1;
2039          DrawLine (pt1, pt2);
2040          pt1.y = pt2.y = yline - above + 1;
2041          DrawLine (pt1, pt2);
2042   }
2043   WidePen (1);
2044   SetColor (color);
2045   pt1.x = oldpt1.x;
2046   pt1.y = oldpt1.y;
2047   pt2.x = oldpt2.x;
2048   pt2.y = oldpt2.y;
2049   if (startin == 1) {
2050 #ifdef WIN_MAC
2051      LoadRect(&leftrct, pt1.x , (Int2)(pt1.y -3), (Int2)(pt1.x +7), (Int4)(pt1.y +4) );
2052      OffsetRect (&leftrct, 0, 1);
2053 #endif
2054 #ifdef WIN_MSWIN
2055      LoadRect(&leftrct, pt1.x , (Int2)(pt1.y -3), (Int2)(pt1.x +7), (Int2)(pt1.y +4) );
2056 #endif
2057 #ifdef WIN_MOTIF
2058      LoadRect(&leftrct, pt1.x , (Int2)(pt1.y -3), (Int2)(pt1.x +7), (Int2) (pt1.y +4) );
2059 #endif
2060      if (partialstart)
2061         CopyBits (&leftrct, leftTriSym);
2062      else
2063         CopyBits (&leftrct, leftTriFillSym);
2064   }
2065   else if (startin == 2) {
2066 #ifdef WIN_MAC
2067      LoadRect(&leftrct, pt1.x , (Int2)(pt1.y -3), (Int2)(pt1.x +7), (Int2)(pt1.y +4));
2068      OffsetRect (&leftrct, 0, 1);
2069 #endif
2070 #ifdef WIN_MSWIN
2071      LoadRect(&leftrct, pt1.x , (Int2)(pt1.y -3), (Int2)(pt1.x +7), (Int2)(pt1.y +4));
2072 #endif
2073 #ifdef WIN_MOTIF
2074      LoadRect(&leftrct, pt1.x , (Int2)(pt1.y -3), (Int2)(pt1.x +7), (Int2)(pt1.y +4));
2075 #endif
2076      if (partialstart)
2077         CopyBits (&leftrct, rectSym);
2078      else
2079         CopyBits (&leftrct, rectFillSym);
2080   }
2081   if (stopin == 1) {
2082 #ifdef WIN_MAC
2083      LoadRect(&rightrct, (Int2)(pt2.x -7), (Int2)(pt2.y -3), pt2.x, (Int2)(pt2.y +4));
2084      OffsetRect (&rightrct, 0, 1);
2085 #endif
2086 #ifdef WIN_MSWIN
2087      LoadRect(&rightrct, (Int2)(pt2.x -7), (Int2)(pt2.y -3), pt2.x, (Int2)(pt2.y +4));
2088 #endif
2089 #ifdef WIN_MOTIF
2090      LoadRect(&rightrct, (Int2)(pt2.x -7), (Int2)(pt2.y -3), pt2.x, (Int2)(pt2.y +4));
2091 #endif
2092      if (partialstop)
2093         CopyBits (&leftrct, rectSym);
2094      else
2095         CopyBits (&rightrct, rectFillSym);
2096   }
2097   else if (stopin == 2) {
2098 #ifdef WIN_MAC
2099      LoadRect (&rightrct, (Int2)(pt2.x -7), (Int2)(pt2.y -3), pt2.x, (Int2)(pt2.y +4));
2100      OffsetRect (&rightrct, 0, 1);
2101 #endif
2102 #ifdef WIN_MSWIN
2103      LoadRect (&rightrct, (Int2)(pt2.x -7), (Int2)(pt2.y -3), pt2.x, (Int2)(pt2.y +4));
2104 #endif
2105 #ifdef WIN_MOTIF
2106      LoadRect (&rightrct, (Int2)(pt2.x -7), (Int2)(pt2.y -3), pt2.x, (Int2)(pt2.y +4));
2107 #endif
2108      if (partialstop)
2109         CopyBits (&rightrct,rightTriSym);
2110      else
2111         CopyBits (&rightrct,rightTriFillSym);
2112   }
2113   Black ();
2114   WidePen (1);
2115 }
2116 
2117 /*********************************************************************
2118 ***  draw_cds
2119 *********************************************************************/
draw_trans(EditAlignDataPtr adp,SelEdStructPtr cds,CharPtr trans,PoinT * pt,Int4 from,Int4 drw_width,Uint2 offset)2120 static void draw_trans (EditAlignDataPtr adp, SelEdStructPtr cds, CharPtr trans, PoinT *pt, Int4 from, Int4 drw_width, Uint2 offset)
2121 {
2122   SeqLocPtr     slp;
2123   CharPtr       transtr;
2124   CharPtr       strPtr, transPtr;
2125   Int4          left, right;
2126   Int2          k;
2127 
2128   if ( trans == NULL || cds == NULL ) return;
2129   slp = (SeqLocPtr) cds->region;
2130   if (slp == NULL) return;
2131   left  = (Int4) MAX ((Int4) from, (Int4) SeqLocStart(slp));
2132   right = (Int4) MIN ((Int4) from+drw_width, (Int4) SeqLocStop(slp)+1);
2133   if (right < left) {
2134      ErrPostEx (SEV_ERROR, 0, 0, "fail in draw_trans: left %ld right %ld", (long) left, (long) right);
2135   }
2136   transtr = (CharPtr)MemNew ((size_t)(512 * (sizeof (Char))));
2137   emptystring (transtr, 512);
2138   transtr[0] = ' ';
2139   transtr[511] = '\0';
2140   strPtr = transtr;
2141   strPtr += (Int2) (left - from);
2142   transPtr = trans;
2143   transPtr += cds->offset;   /*!!!!!!!!!!!!! += cds->codonstart ?? */
2144   if (SeqLocStart(slp) < from)
2145      transPtr += (Int2)(from - SeqLocStart(slp));
2146   if (adp->prot_mode == MPROTAA) {
2147      for (k =0; k < (right - left); k++, strPtr++, transPtr++) {
2148         if ( *transPtr=='M' || *transPtr=='*') *strPtr = *transPtr;
2149      }
2150   }
2151   else {
2152      for (k =0; k < (right - left); k++, strPtr++, transPtr++) {
2153         *strPtr = *transPtr;
2154      }
2155   }
2156   strPtr++;
2157   *strPtr= '\0';
2158   draw_seq (adp, cds, from, drw_width, *pt, transtr, FALSE, NULL, TRUE, OBJ_SEQFEAT, FALSE);
2159   transtr = (CharPtr)MemFree (transtr);
2160   return;
2161 }
2162 
2163 /*********************************************************************
2164 ***  draw_pept
2165 *********************************************************************/
draw_pept(EditAlignDataPtr adp,SelEdStructPtr cds,PoinT * pt,Int4 from,Int4 drw_width,Int2 line,Uint2 offset)2166 static void draw_pept (EditAlignDataPtr adp, SelEdStructPtr cds, PoinT *pt, Int4 from, Int4 drw_width, Int2 line, Uint2 offset)
2167 {
2168   ValNodePtr  pept;
2169 
2170   if (cds!=NULL) {
2171      pept = cds->data;
2172      if (pept != NULL)  {
2173         if (pept->data.ptrvalue != NULL)  {
2174            draw_trans (adp, cds, (CharPtr) pept->data.ptrvalue, pt, from, drw_width, offset);
2175         }
2176      }
2177   }
2178 }
2179 
2180 /*********************************************************************
2181 ***  draw_feat
2182 *********************************************************************/
draw_feat(EditAlignDataPtr adp,Uint2 eid,Uint2 iid,Uint2 it,Uint2 choice,Int4 start,Int4 stop,Uint1 strand,CharPtr label,PoinT * pt,Int4 from,Int4 drw_width,Int2 line,Int4 alignline,Uint4 color,Boolean partialstart,Boolean partialstop,BoolPtr gapline)2183 static void draw_feat (EditAlignDataPtr adp, Uint2 eid, Uint2 iid, Uint2 it, Uint2 choice, Int4 start, Int4 stop, Uint1 strand, CharPtr label, PoinT *pt, Int4 from, Int4 drw_width, Int2 line, Int4 alignline, Uint4 color, Boolean partialstart, Boolean partialstop, BoolPtr gapline)
2184 {
2185   Char      str[128];
2186   Uint2     wideline;
2187   Boolean   featselect;
2188 
2189   if ( start > stop || start >= from + drw_width || stop < from )
2190      return;
2191   if (it == OBJ_VIRT)
2192   {
2193      wideline = 5;
2194      if (choice == SEQFEAT_CDREGION )
2195          sprintf (str, "CDS %d", (int) iid);
2196      else if (choice == SEQFEAT_GENE)
2197          sprintf (str, "gene %d", (int) iid);
2198      else if (choice == SEQFEAT_RNA)
2199          sprintf (str, "mRNA %d", (int) iid);
2200      str[15] = '\0';
2201      draw_id (adp, pt, -1, str, strand, 0, 3, FALSE, FALSE, -1);
2202   }
2203   else {
2204      wideline = 3;
2205      draw_id (adp, pt, -1, label, strand, 0, 3, FALSE, FALSE, -1);
2206   }
2207   featselect = (Boolean) (is_selectedbyID (eid, iid, it) != NULL);
2208   draw_line (adp, start, stop, strand, pt, from, drw_width, line, alignline, color, wideline, featselect, partialstart, partialstop, gapline);
2209 }
2210 
what_inline(EditAlignDataPtr adp,Int4 line,Uint2 ei,Uint4 ii,Uint2 it,Uint2 ist,Uint2 al)2211 static void what_inline (EditAlignDataPtr adp, Int4 line, Uint2 ei, Uint4 ii, Uint2 it, Uint2 ist, Uint2 al)
2212 {
2213   adp->seqEntity_id [line]  = ei;
2214   adp->item_id [line]  = ii;
2215   adp->itemtype[line] = it;
2216   adp->itemsubtype[line] = ist;
2217   adp->alignline [line]= al;
2218 }
2219 
id_is_invalid(EditAlignDataPtr adp,PoinT ptlh)2220 static Boolean id_is_invalid (EditAlignDataPtr adp, PoinT ptlh)
2221 {
2222   RecT  rect;
2223   LoadRect(&rect, ptlh.x, ptlh.y,
2224                   (Int2)(ptlh.x + adp->marginleft * adp->charw),
2225                   (Int2)(ptlh.y + adp->lineheight));
2226   return RectInRgn (&rect, updateRgn);
2227 }
2228 
row_is_invalid(EditAlignDataPtr adp,PoinT ptlh)2229 static Boolean row_is_invalid (EditAlignDataPtr adp, PoinT ptlh)
2230 {
2231   RecT  rect;
2232   LoadRect (&rect, (Int2)(ptlh.x + adp->margin.left - adp->charw), ptlh.y,
2233                    (Int2)(ptlh.x + adp->pnlWidth * adp->charw + 1),
2234                    (Int2)(ptlh.y + adp->lineheight));
2235   return RectInRgn (&rect, updateRgn);
2236 }
2237 
rang(Uint2 format,SelEdStructPtr ssp)2238 static Int2 rang (Uint2 format, SelEdStructPtr ssp)
2239 {
2240   if (format == OBJ_BIOSEQ)
2241      return ssp->entityID;
2242   if (format == OBJ_SEQALIGN)
2243      return ssp->itemID;
2244   return 0;
2245 }
2246 
getparam(ValNodePtr vnprm,Uint2 eID,Uint2 iID,Uint1 choice)2247 static Int2 getparam (ValNodePtr vnprm, Uint2 eID, Uint2 iID, Uint1 choice)
2248 {
2249   ValNodePtr   vnp;
2250   SeqParamPtr  prm;
2251 
2252   for (vnp = vnprm; vnp != NULL; vnp = vnp->next) {
2253      prm = (SeqParamPtr) vnp->data.ptrvalue;
2254      if (prm->entityID == eID && prm->itemID == iID)
2255      {
2256         if (choice == 1)
2257            return prm->group;
2258      }
2259   }
2260   return -1;
2261 }
2262 
seqid_tolabel(SeqIdPtr sip,Uint1 choice)2263 static CharPtr seqid_tolabel (SeqIdPtr sip, Uint1 choice)
2264 {
2265   BioseqPtr bsp;
2266   SeqIdPtr  tmp = NULL;
2267   Char      str[120];
2268   CharPtr   strp;
2269   Uint4     val;
2270 
2271   str[0] = '\0';
2272   if (choice && choice <= PRINTID_GIcc)
2273   {
2274      bsp = BioseqLockById(sip);
2275      if (bsp!=NULL)
2276      {
2277         if (choice==PRINTID_GIcc)
2278            tmp = SeqIdFindBest (bsp->id, 0);
2279         else
2280            tmp = bsp->id;
2281         if (tmp)
2282         {
2283            SeqIdWrite (tmp, str, PRINTID_TEXTID_ACCESSION, 120);
2284            val=WHICH_db_accession(str);
2285            if (val==0)
2286               choice = PRINTID_FASTA_SHORT;
2287 
2288            SeqIdWrite (tmp, str, choice, 120);
2289            BioseqUnlock(bsp);
2290            strp = StringSave (str);
2291            return strp;
2292         }
2293         BioseqUnlock(bsp);
2294      }
2295   }
2296   if (choice!=0 && sip) {
2297      SeqIdWrite (sip, str, choice, 120);
2298      strp = StringSave (str);
2299      return strp;
2300   }
2301   strp = StringSave (str);
2302   return strp;
2303 }
2304 
2305 /*****************************************************************
2306 ***
2307 ***     Draw Alignment in Panel p
2308 ***
2309 ******************************************************************/
2310 static Char strcmpl[] = "complement";
2311 
on_draw(PaneL p)2312 extern void on_draw (PaneL p)
2313 {
2314   PoinT            ptlh;        /* PoinT at the top of lineheight */
2315   RecT             rp;          /* Panel Rect */
2316   EditAlignDataPtr adp;
2317   TextAlignBufPtr  curtdp;
2318   SelStructPtr     curvnp;
2319   SelEdStructPtr   curssp = NULL;
2320   ValNodePtr       vnp = NULL;
2321   SeqLocPtr        curslp;
2322   SeqLocPtr        sip;
2323   SeqAlignPtr      salp;
2324 
2325   Int4          from_inbuf;  /* alignment coordinates in buffer */
2326   Int4          from_inseq;  /* alignment coordinates in buffer */
2327   Int4          stringlens;
2328   Int4          start,  stop;
2329   Int4          start2, stop2;
2330 
2331   Int4          line;        /* current line */
2332   Int4          curalgline;
2333   Int4          drw_width;   /* length of drw_str */
2334   Int4          group;
2335   Int4          chklocp,
2336                 chklocp2;
2337   Uint2         itemsubtype;
2338   Uint4         offset;
2339 
2340   CharPtr       stridp;
2341   CharPtr       curstr = NULL;
2342   CharPtr       masterbuf =NULL,
2343                 masterstr =NULL;
2344   Int2          oldstyle;
2345 
2346   Boolean       invalid_id;
2347   Boolean       invalid_row;
2348   Boolean       is_master, draw_diff;
2349   Boolean       first = TRUE;
2350   Boolean       line_drawn;
2351   Boolean       empty_line;
2352 
2353   Int1          gapinline;
2354   BoolPtr       gapline,
2355                 gaplinep;
2356 
2357   if ( (adp = GetAlignDataPanel (p)) == NULL )
2358      return;
2359   if ( adp->seqnumber == 0 )
2360      return;
2361 
2362   salp = (SeqAlignPtr) adp->sap_align->data;
2363 
2364   if ( adp->firstssp == NULL ) {
2365      adp->firstssp = get_firstline (NULL, adp->buffer);
2366   }
2367   if ( adp->firstssp == NULL )
2368      return;
2369   if ( adp->firstssp->region == NULL )
2370      return;
2371   from_inseq = adp->hoffset;
2372   from_inbuf = adp->hoffset - adp->bufferstart;
2373   drw_width = MIN ((Int4) adp->visibleWidth,
2374                    (Int4) (adp->bufferlength - from_inbuf));
2375   if ( drw_width <= 0 || adp->bufferstart < 0 ) {
2376          return;
2377   }
2378 
2379   oldstyle = GetMuskCurrentSt ();
2380   SetMuskCurrentSt (GetMuskStyleName (adp->styleNum));
2381 
2382   line = (drw_width +2) * sizeof(Boolean);
2383   gapline = (BoolPtr) MemNew ((size_t)(line));
2384   MemSet ((Pointer)gapline, (int)(FALSE), (size_t)(line));
2385   gaplinep = NULL;
2386   gapinline = LINE_NOGAP;
2387   empty_line = FALSE;
2388 
2389   curssp = (SelEdStructPtr) adp->firstssp->region;
2390   if (curssp->itemtype ==OBJ_SEQFEAT) {
2391      for (curvnp=adp->firstssp; curvnp!=NULL; curvnp=curvnp->prev) {
2392         curssp = (SelEdStructPtr) curvnp->region;
2393         if (curssp->itemtype==OBJ_BIOSEQ)   /*&&curvnp->itemtype==FEATDEF_BAD)*/
2394         {
2395            if (curssp->data !=NULL) {
2396               vnp = (ValNodePtr) curssp->data;
2397               curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
2398               curstr = get_substring(curtdp->buf, from_inbuf, drw_width);
2399               if ( curstr != NULL )
2400               {
2401                  gapinline=getgapsfromstring(curstr, 0, drw_width, &gapline);
2402                  empty_line =(Boolean)(gapinline == LINE_ONLYGAP);
2403                  if (gapinline == LINE_NOGAP)
2404                     gaplinep = NULL;
2405                  else
2406                     gaplinep = gapline;
2407               }
2408            }
2409            break;
2410         }
2411      }
2412   }
2413   get_client_rect (p, &rp);
2414   SelectFont ((FonT)(adp->font));
2415   ptlh.x = rp.left;
2416   ptlh.y = rp.top;
2417   line = 0;
2418   curalgline = 0;
2419   adp->visibleLength = drw_width;
2420   masterbuf = get_master (adp->linebuff, adp->master.entityID,
2421                           adp->master.itemID, adp->master.itemtype);
2422 
2423   curvnp = adp->firstssp;
2424   while ( line < adp->pnlLine )
2425   {
2426 
2427      curssp = (SelEdStructPtr) curvnp->region;
2428      if (curssp !=NULL) {
2429          adp->lastses = curssp;
2430          itemsubtype = curvnp->itemtype;
2431          invalid_row = row_is_invalid(adp, ptlh);
2432          invalid_id  = id_is_invalid (adp, ptlh);
2433          if (itemsubtype == EDITDEF_SCA)
2434          {
2435                 what_inline(adp, line, LINE0, LINE0, LINE0, LINE0, curalgline);
2436                 if ( invalid_row ) {
2437                    draw_scale (adp, from_inbuf, adp->visibleWidth, &ptlh);
2438                 }
2439                 line++;
2440                 ptlh.y += adp->lineheight;
2441          }
2442          else if (itemsubtype == EDITDEF_SCB)
2443          {
2444                 what_inline(adp, line, LINE0, LINE0, LINE0, LINE0, curalgline);
2445                 if ( invalid_row ) {
2446                    draw_bars (adp, from_inbuf, adp->visibleWidth, &ptlh);
2447                 }
2448                 line++;
2449                 ptlh.y += adp->lineheight;
2450          }
2451          else if (itemsubtype>=EDITDEF_RF1 && itemsubtype<=EDITDEF_RF6)
2452          {
2453             if (curssp->data !=NULL  && !empty_line) {
2454                curslp = (SeqLocPtr) curssp->region;
2455                vnp = (ValNodePtr) curssp->data;
2456                if ( SeqLocStop (curslp) > from_inseq && vnp != NULL)
2457                {
2458                   what_inline (adp, line, curssp->entityID, curssp->itemID,
2459                                 curssp->itemtype, itemsubtype, curalgline);
2460                   curstr = (CharPtr) vnp->data.ptrvalue;
2461                   offset = (Uint2)(itemsubtype - EDITDEF_RF1) % (Uint2)3;
2462                   if (itemsubtype>=EDITDEF_RF1 && itemsubtype<EDITDEF_RF4)
2463                      draw_id (adp, &ptlh, rang(adp->input_format, curssp), NULL,  Seq_strand_plus, 0, curssp->itemtype, FALSE, FALSE, -1);
2464                   else
2465                      draw_id (adp, &ptlh, rang(adp->input_format, curssp), NULL, Seq_strand_minus, 0, curssp->itemtype, FALSE, FALSE, -1);
2466 
2467                   if ( invalid_row )
2468                   {
2469                     draw_trans (adp, curssp, curstr, &ptlh, from_inseq, drw_width, offset);
2470                   }
2471                }
2472                line++;
2473                ptlh.y += adp->lineheight;
2474             }
2475          }
2476          else if ( itemsubtype == FEATDEF_TRSL )
2477          {
2478             if (!empty_line) {
2479                first = TRUE;
2480                line_drawn = FALSE;
2481                while ( curssp != NULL && curssp->data != NULL)
2482                {
2483                   curslp = (SeqLocPtr) curssp->region;
2484                   sip = SeqLocId (curslp);
2485                   start2 = SeqLocStart(curslp);
2486                   chklocp =chkloc(sip, start2, adp->sqloc_list, &start2);
2487                   start= SeqCoordToAlignCoord (start2, sip, salp, 0, chklocp);
2488                   stop2 = SeqLocStop(curslp);
2489                   chklocp =chkloc(sip, stop2, adp->sqloc_list, &stop2);
2490                   stop = SeqCoordToAlignCoord (stop2, sip, salp, 0, chklocp);
2491                   if (start < from_inseq + drw_width && stop >= from_inseq)
2492                   {
2493                      if ( invalid_row ) {
2494                         draw_pept (adp, curssp, &ptlh, from_inseq, drw_width, line, 0);
2495                      }
2496                      if (first) {
2497                         what_inline (adp, line, curssp->entityID, curssp->itemID, curssp->itemtype, itemsubtype, curalgline);
2498                         line_drawn = TRUE;
2499                         first = FALSE;
2500                      }
2501                   }
2502                   curssp = FindNextSegment (curssp);
2503                }
2504                if (line_drawn) {
2505                   line++;
2506                   ptlh.y += adp->lineheight;
2507                }
2508             }
2509          }
2510          else if ( itemsubtype == EDITDEF_CPL )
2511          {
2512             if (curssp->data !=NULL && !empty_line)
2513             {
2514                 vnp = (ValNodePtr) curssp->data;
2515                 curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
2516                 curstr = get_substring (curtdp->buf, from_inbuf, drw_width);
2517                 if ( curstr != NULL )                         /* !!!!!!! */
2518                 {
2519                    what_inline (adp, line, curssp->entityID, curssp->itemID,
2520                             curssp->itemtype, itemsubtype, curalgline);
2521                    if ( invalid_id && (( !adp->displaytype
2522                    && curssp->itemtype != OBJ_BIOSEQ) || adp->displaytype))
2523                       draw_id (adp, &ptlh, -1, strcmpl, 255, 0, curssp->itemtype, FALSE, FALSE, -1);
2524                    if ( invalid_row && (( !adp->displaytype
2525                    && curssp->itemtype != OBJ_BIOSEQ) || adp->displaytype) )
2526                    {
2527                       draw_seq (adp, curssp, from_inseq, drw_width, ptlh, curstr, draw_diff, masterstr, TRUE, itemsubtype, FALSE);
2528                    }
2529                    line++;
2530                    ptlh.y += adp->lineheight;
2531                 }
2532             }
2533          }
2534          else if (curssp->itemtype == OBJ_BIOSEQ)
2535          {
2536             if (curssp->data !=NULL) {
2537                vnp = (ValNodePtr) curssp->data;
2538                curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
2539                curstr = get_substring(curtdp->buf, from_inbuf, drw_width);
2540                if ( curstr != NULL )
2541                {
2542                  gapinline=getgapsfromstring(curstr, 0, drw_width, &gapline);
2543                  empty_line =(Boolean)(gapinline == LINE_ONLYGAP);
2544                  if (gapinline == LINE_NOGAP)
2545                     gaplinep = NULL;
2546                  else
2547                     gaplinep = gapline;
2548                  if (adp->draw_emptyline || (!adp->draw_emptyline && !empty_line)) {
2549                    what_inline (adp, line, curssp->entityID, curssp->itemID,
2550                                 curssp->itemtype, itemsubtype, curalgline);
2551                    is_master = is_samess_ses (&(adp->master), curssp);
2552                    draw_diff=!(!adp->charmode || (adp->charmode && is_master));
2553                    masterstr = NULL;
2554                    if ( draw_diff ) {
2555                       stringlens = StringLen (masterbuf);
2556                       if ( from_inbuf < stringlens )
2557                             masterstr = masterbuf + from_inbuf;
2558                    }
2559                    if ( invalid_id ) {
2560                      if (adp->displaytype)
2561                      {
2562                         if (adp->marginwithgroup)
2563                            group=getparam(adp->params,curssp->entityID, curssp->itemID, 1);
2564                         else group = -1;
2565                         sip = SeqLocId((SeqLocPtr) curssp->region);
2566                         start=AlignCoordToSeqCoord(from_inseq, sip,salp, adp->sqloc_list, 0) +1;
2567                         stridp = seqid_tolabel (sip, adp->printid);
2568                         /* seqid_to_label calls BioseqLockById, which will
2569                          * refresh the Desktop if it is open and will change
2570                          * the font setting - need to put the font back.
2571                          */
2572                         SelectFont ((FonT)(adp->font));
2573                         draw_id (adp, &ptlh, rang(adp->input_format, curssp), stridp, curtdp->strand, start, curssp->itemtype, FALSE, is_master, group);
2574                      }
2575                    }
2576                    if ( invalid_row && adp->displaytype )
2577                    {
2578                       draw_seq (adp, curssp, from_inseq, drw_width, ptlh, curstr, draw_diff, masterstr, FALSE, curssp->itemtype, TRUE);
2579                       draw_caret (adp, curssp, ptlh, line);
2580                    }
2581                    line++;
2582                    ptlh.y += adp->lineheight;
2583                  }
2584                }
2585             }
2586          }
2587          else if (curssp->itemtype==OBJ_SEQFEAT && itemsubtype==FEATDEF_PROT)
2588          {
2589             if (curssp->data !=NULL && !empty_line)
2590             {
2591                vnp = (ValNodePtr) curssp->data;
2592                curtdp = (TextAlignBufPtr) vnp->data.ptrvalue;
2593                curstr = get_substring(curtdp->buf, from_inbuf, drw_width);
2594                if ( curstr != NULL )
2595                {
2596                   what_inline (adp, line, curssp->entityID, curssp->itemID,  curssp->itemtype, itemsubtype, curalgline);
2597                   draw_id (adp, &ptlh, -1, curtdp->label, curtdp->strand, 0, curssp->itemtype, FALSE, FALSE, -1);
2598                   if ( invalid_row ) {
2599                      draw_seq (adp, curssp, from_inseq, drw_width, ptlh, curstr, draw_diff, masterstr, FALSE, curssp->itemtype, FALSE);
2600                   }
2601                   line++;
2602                   ptlh.y += adp->lineheight;
2603                }
2604             }
2605          }
2606          else if ( curssp->itemtype ==OBJ_SEQFEAT )
2607          {
2608             if (!empty_line) {
2609                first = TRUE;
2610                line_drawn = FALSE;
2611                while (curssp!=NULL)
2612                {
2613                   curslp = (SeqLocPtr) curssp->region;
2614                   sip = SeqLocId (curslp);
2615                   start2 = SeqLocStart(curslp);
2616                   chklocp = chkloc(sip, start2, adp->sqloc_list, &start2);
2617                   start= SeqCoordToAlignCoord (start2, sip, salp, 0, chklocp);
2618                   stop2 = SeqLocStop(curslp);
2619                   chklocp2 = chkloc(sip, stop2, adp->sqloc_list, &stop2);
2620                   stop = SeqCoordToAlignCoord (stop2, sip, salp, 0, chklocp2);
2621                   if (start <= stop && start < from_inseq + drw_width && stop >= from_inseq)
2622                   {
2623                      if ( invalid_row )
2624                      {
2625                         draw_feat (adp, curssp->entityID, curssp->itemID, curssp->itemtype, itemsubtype, start, stop, SeqLocStrand(curslp), curssp->label, &ptlh, from_inseq, drw_width, line, curalgline, (Uint4) getcolor_fromstyles(itemsubtype), (Boolean)(chklocp==-1), (Boolean)(chklocp2==APPEND_RESIDUE), gaplinep);
2626                      }
2627                      if (first) {
2628                         what_inline(adp, line, curssp->entityID, curssp->itemID,
2629                                      curssp->itemtype, itemsubtype, curalgline);
2630                         line_drawn = TRUE;
2631                         first = FALSE;
2632                      }
2633                   }
2634                   curssp = FindNextSegment (curssp);
2635                }
2636                if (line_drawn) {
2637                   line++;
2638                   ptlh.y += adp->lineheight;
2639                }
2640             }
2641          }
2642          else if( itemsubtype==SEQFEAT_GENE || itemsubtype==SEQFEAT_RNA
2643               ||  itemsubtype==SEQFEAT_CDREGION)
2644          {
2645             if (!empty_line) {
2646                first = TRUE;
2647                line_drawn = FALSE;
2648                while (curssp!=NULL)
2649                {
2650                   curslp = (SeqLocPtr) curssp->region;
2651                   sip = SeqLocId (curslp);
2652                   start2 = SeqLocStart(curslp);
2653                   chklocp =chkloc(sip, start2, adp->sqloc_list, &start2);
2654                   start= SeqCoordToAlignCoord (start2, sip, salp, 0, chklocp);
2655                   stop2 = SeqLocStop(curslp);
2656                   chklocp2 =chkloc(sip, stop2, adp->sqloc_list, &stop2);
2657                   stop = SeqCoordToAlignCoord (stop2, sip, salp, 0, chklocp);
2658                   if (start <= from_inseq + drw_width && stop >= from_inseq)
2659                   {
2660                      if ( invalid_row )
2661                      {
2662                         draw_feat (adp, curssp->entityID, curssp->itemID, curssp->itemtype, itemsubtype, start, stop, SeqLocStrand(curslp), curssp->label, &ptlh, from_inseq, drw_width, line, curalgline, (Uint4) getcolorforvirtfeat(curssp->itemID), (Boolean)(chklocp==-1), (Boolean)(chklocp2==APPEND_RESIDUE), gaplinep);
2663                      }
2664                      if (first) {
2665                         what_inline (adp, line, curssp->entityID, curssp->itemID,
2666                                      curssp->itemtype, itemsubtype, curalgline);
2667                         line_drawn = TRUE;
2668                         first = FALSE;
2669                      }
2670                   }
2671                   curssp = FindNextSegment (curssp);
2672                }
2673                if (line_drawn) {
2674                   line++;
2675                   ptlh.y += adp->lineheight;
2676                }
2677             }
2678          }
2679          else {
2680 /**
2681             ErrPostEx (SEV_ERROR, 0, 0, "fail in on_draw [46] subtype %ld type %ld", (long) itemsubtype, (long) curssp->itemtype);
2682 **/
2683             return;
2684          }
2685          if (line == adp->pnlLine)
2686             break;
2687          curvnp = curvnp->next;
2688          if (curvnp == NULL)
2689          {
2690             if (adp->rowpcell > 0
2691             && ((Int4)(curalgline+1) % (Int4)adp->rowpcell) == 0)
2692             {
2693                 what_inline(adp,line,LINE0,LINE0, LINE0, LINE0, curalgline);
2694                 ptlh.y += adp->lineheight;
2695                 line++;
2696             }
2697             curvnp = adp->buffer;
2698             curalgline++;
2699 /*****************
2700 *******************/
2701 if (curalgline>500)
2702 break;
2703 /*****************
2704 *******************/
2705 
2706             from_inbuf += drw_width;
2707             from_inseq += drw_width;
2708             if (from_inseq >= adp->length)
2709                 break;
2710             drw_width = MIN ((Int4) adp->visibleWidth, (Int4)(adp->bufferlength
2711                       - (adp->hoffset -adp->bufferstart) - adp->visibleLength));
2712             adp->visibleLength += drw_width;
2713          }
2714      }
2715   }
2716   MemFree (gapline);
2717   SetMuskCurrentSt (GetMuskStyleName (oldstyle));
2718   return;
2719 }
2720 
2721 /* This section of code is used for feature propagation */
2722 typedef struct fprdata {
2723   FORM_MESSAGE_BLOCK
2724   BioseqPtr           bsp;
2725   SeqAlignPtr         salp;
2726   Int4                aln_length;
2727   Int4                log10_aln_length;
2728   VieweR              details;
2729   SegmenT             dtpict;
2730   Int4                scaleX;
2731   GrouP               allOrSel;
2732   GrouP               gapSplit;
2733   DialoG              sequence_list_dlg;
2734   ButtoN              stopCDS;
2735   ButtoN              transPast;
2736   ButtoN              fixCDS;
2737   ButtoN              fuseJoints;
2738   ButtoN              accept;
2739   ButtoN              leave_dlg_up;
2740 } FprData, PNTR FprDataPtr;
2741 
2742 typedef struct ivalinfo {
2743   Int4  start1;
2744   Int4  stop1;
2745   Int4  start2;
2746   Int4  stop2;
2747   struct ivalinfo PNTR next;
2748 } IvalInfo, PNTR IvalInfoPtr;
2749 
IvalInfoFree(IvalInfoPtr ival)2750 static IvalInfoPtr IvalInfoFree (
2751   IvalInfoPtr ival
2752 )
2753 
2754 {
2755   IvalInfoPtr  next;
2756 
2757   while (ival != NULL) {
2758     next = ival->next;
2759     MemFree (ival);
2760     ival = next;
2761   }
2762   return NULL;
2763 }
2764 
GetAlignmentIntervals(SeqAlignPtr sap,Int4 row1,Int4 row2,Int4 from,Int4 to)2765 static IvalInfoPtr GetAlignmentIntervals (SeqAlignPtr sap, Int4 row1, Int4 row2, Int4 from, Int4 to)
2766 {
2767    AlnMsg2Ptr    amp1;
2768    AlnMsg2Ptr    amp2;
2769    IvalInfoPtr  ival;
2770    IvalInfoPtr  ival_head = NULL;
2771    IvalInfoPtr  ival_prev = NULL;
2772    Int4         from_aln;
2773    Int4         start;
2774    Int4         stop;
2775    Int4         tmp;
2776    Int4         to_aln;
2777    Int4         seg_i, seg_n, seg_start, seg_stop;
2778 
2779    if (sap == NULL || sap->saip == NULL)
2780       return NULL;
2781    AlnMgr2GetNthSeqRangeInSA(sap, row1, &start, &stop);
2782    if (from < start)
2783       from = start;
2784    if (to > stop)
2785       to = stop;
2786    from_aln = AlnMgr2MapBioseqToSeqAlign(sap, from, row1);
2787    to_aln = AlnMgr2MapBioseqToSeqAlign(sap, to, row1);
2788    if (from_aln > to_aln)
2789    {
2790       tmp = from_aln;
2791       from_aln = to_aln;
2792       to_aln = tmp;
2793    }
2794    seg_n = AlnMgr2GetNumSegs(sap);
2795    for (seg_i=1; seg_i<=seg_n; seg_i++) {
2796      AlnMgr2GetNthSegmentRange(sap, seg_i, &seg_start, &seg_stop);
2797      if (seg_start > to_aln) continue;
2798      if (seg_stop < from_aln) continue;
2799      if (seg_start < from_aln) seg_start = from_aln;
2800      if (seg_stop > to_aln) seg_stop = to_aln;
2801 
2802      amp1 = AlnMsgNew2();
2803      amp1->from_aln = seg_start;
2804      amp1->to_aln = seg_stop;
2805      amp1->row_num = row1;
2806      amp2 = AlnMsgNew2();
2807      amp2->from_aln = seg_start;
2808      amp2->to_aln = seg_stop;
2809      amp2->row_num = row2;
2810      AlnMgr2GetNextAlnBit(sap, amp1);
2811      AlnMgr2GetNextAlnBit(sap, amp2);
2812      if (amp1->type == AM_SEQ && amp2->type == AM_SEQ) {
2813        ival = (IvalInfoPtr)MemNew(sizeof(IvalInfo));
2814        ival->start1 = amp1->from_row;
2815        ival->stop1 = amp1->to_row;
2816        ival->start2 = amp2->from_row;
2817        ival->stop2 = amp2->to_row;
2818        if (ival_head == NULL)
2819          ival_head = ival_prev = ival;
2820        else {
2821          ival_prev->next = ival;
2822          ival_prev = ival;
2823        }
2824      }
2825      AlnMsgFree2(amp1);
2826      AlnMsgFree2(amp2);
2827    }
2828    return ival_head;
2829 }
2830 
MergeAdjacentIntervals(IvalInfoPtr list)2831 static IvalInfoPtr MergeAdjacentIntervals (
2832   IvalInfoPtr list
2833 )
2834 
2835 {
2836   IvalInfoPtr  curr, last, next;
2837 
2838   if (list != NULL) {
2839     curr = list->next;
2840     last = list;
2841     while (curr != NULL) {
2842       next = curr->next;
2843       if (curr->start2 == last->stop2 + 1) {
2844         last->stop2 = MAX (curr->stop2, last->stop2);
2845         MemFree (curr);
2846         last->next = next;
2847       } else {
2848         last = curr;
2849       }
2850       curr = next;
2851     }
2852   }
2853   return list;
2854 }
2855 
MergeAdjacentSeqLocIntervals(SeqLocPtr location)2856 static SeqLocPtr MergeAdjacentSeqLocIntervals (SeqLocPtr location)
2857 
2858 {
2859   SeqLocPtr    head = NULL;
2860   SeqIntPtr    sinp, last_sinp;
2861   SeqLocPtr    slp;
2862   SeqPntPtr    spp, last_spp;
2863   SeqLocPtr    last_slp = NULL;
2864   Int4         last_from = -1, last_to = -1;
2865   Uint1        last_strand = 0;
2866   SeqIdPtr     last_id = NULL;
2867 
2868   head = NULL;
2869   slp = SeqLocFindNext (location, NULL);
2870   while (slp != NULL) {
2871     switch (slp->choice) {
2872     case SEQLOC_INT :
2873       sinp = (SeqIntPtr) slp->data.ptrvalue;
2874       if (sinp != NULL) {
2875 	    if (last_slp != NULL && last_strand == sinp->strand && last_id != NULL
2876 			&& SeqIdComp (sinp->id, last_id) == SIC_YES
2877 			&& ((last_from <= sinp->from + 1 && last_to >= sinp->from - 1)
2878 			  || (last_from <= sinp->to + 1 && last_to >= sinp->to - 1)
2879 			  || (last_from >= sinp->from - 1 && last_to <= sinp->to + 1)
2880 			  || (last_from <= sinp->from + 1 && last_to >= sinp->to - 1)))
2881 		{
2882 		  /* intervals are adjacent, so expand previous interval */
2883   	      if (last_slp->choice == SEQLOC_INT) {
2884 		    last_sinp = last_slp->data.ptrvalue;
2885 		    if (last_sinp != NULL) {
2886 		      last_from = MIN (sinp->from, last_sinp->from);
2887 			  last_sinp->from = last_from;
2888 			  last_to = MAX (sinp->to, last_sinp->to);
2889 			  last_sinp->to = last_to;
2890 			}
2891 		  } else if (last_slp->choice == SEQLOC_PNT) {
2892 		    /* change previous entry from point to interval that includes point */
2893 		    spp = (SeqPntPtr)last_slp->data.ptrvalue;
2894 		    if (spp != NULL) {
2895               last_sinp = SeqIntNew ();
2896 			  last_from = MIN (spp->point, sinp->from);
2897 			  last_sinp->from = last_from;
2898 			  last_to = MAX (sinp->to, spp->point);
2899 			  last_sinp->to = last_to;
2900 			  last_sinp->strand = sinp->strand;
2901 			  last_sinp->id = SeqIdDup (sinp->id);
2902 			  last_slp->choice = SEQLOC_INT;
2903 			  last_slp->data.ptrvalue = last_sinp;
2904 			  SeqPntFree (spp);
2905 			}
2906 		  }
2907 		} else {
2908 		  /* add new interval */
2909 		  last_sinp = SeqIntNew ();
2910           last_sinp->from = sinp->from;
2911 		  last_from = sinp->from;
2912           last_sinp->to = sinp->to;
2913 		  last_to = sinp->to;
2914           last_sinp->strand = sinp->strand;
2915 		  last_strand = sinp->strand;
2916 		  last_sinp->id = SeqIdDup (sinp->id);
2917           last_id = last_sinp->id;
2918           last_slp = ValNodeAddPointer (&head, SEQLOC_INT, (Pointer) last_sinp);
2919         }
2920 	  }
2921 	  break;
2922 	case SEQLOC_PNT:
2923 	  spp = (SeqPntPtr)slp->data.ptrvalue;
2924 	  if (spp != NULL) {
2925 	    if (last_slp != NULL && last_strand == spp->strand && last_id != NULL
2926 			&& SeqIdComp (spp->id, last_id) == SIC_YES
2927 			&& last_to >= spp->point - 1)
2928 		{
2929 		  /* intervals are adjacent, so expand previous interval */
2930 		  if (last_slp->choice == SEQLOC_INT) {
2931 		    last_sinp = last_slp->data.ptrvalue;
2932 			if (last_sinp != NULL) {
2933 			  last_to = MAX (spp->point, last_sinp->to);
2934 			  last_sinp->to = last_to;
2935 			  last_from = MIN (spp->point, last_sinp->from);
2936 			  last_sinp->from = last_from;
2937 			}
2938 		  } else if (last_slp->choice == SEQLOC_PNT) {
2939 		    /* change previous entry from point to interval that includes point */
2940 		    last_spp = (SeqPntPtr)last_slp->data.ptrvalue;
2941 			if (last_spp != NULL) {
2942               last_sinp = SeqIntNew ();
2943 			  last_from = MIN (spp->point, last_spp->point);
2944 			  last_sinp->from = last_from;
2945 			  last_to = MAX (last_spp->point, spp->point);
2946 			  last_sinp->to = last_to;
2947 			  last_sinp->strand = spp->strand;
2948 			  last_sinp->id = SeqIdDup (spp->id);
2949 			  last_slp->choice = SEQLOC_INT;
2950 			  last_slp->data.ptrvalue = last_sinp;
2951 			  SeqPntFree (spp);
2952 			}
2953 		  }
2954 		} else {
2955 		  /* add new point */
2956           last_spp = SeqPntNew ();
2957           last_spp->point = spp->point;
2958 		  last_to = spp->point;
2959 		  last_from = spp->point;
2960           last_spp->strand = spp->strand;
2961 		  last_strand = spp->strand;
2962           last_spp->id = SeqIdDup (spp->id);
2963           last_slp = ValNodeAddPointer (&head, SEQLOC_PNT, (Pointer) last_spp);
2964 		}
2965 	  }
2966 	  break;
2967 	default:
2968 	  break;
2969 	}
2970     slp = SeqLocFindNext (location, slp);
2971   }
2972 
2973   if (head == NULL) return NULL;
2974   if (head->next == NULL) return head;
2975 
2976   slp = ValNodeNew (NULL);
2977   slp->choice = SEQLOC_MIX;
2978   slp->data.ptrvalue = (Pointer) head;
2979   slp->next = NULL;
2980 
2981   return slp;
2982 }
2983 
2984 /* We need to be able to propagate features with locations on multiple segments
2985  * whose IDs may be found in separate alignments.
2986  * To do this, we will take the location of the master feature and for each sublocation,
2987  * we will find the sequence ID of the sublocation.  We will find the alignment that
2988  * contains the master feature sublocation sequence ID and construct a propagated
2989  * sublocation for each sequence in the same alignment as the master feature sublocation
2990  * sequence ID and add this to a list.
2991  * Once we have created all of the propagated sublocations, we will reconstitute the
2992  * total locations for the propagated features by associating each propagated sublocation
2993  * with other propagated sublocations with the same sequence ID or having a sequence ID
2994  * that belongs to the same segmented set.
2995  * We can then use the list of total locations to construct the propagated features.
2996  */
2997 
MapSubLoc(SeqLocPtr master_subloc,SeqAlignPtr salp,Int4 master_row,Int4 prop_row,Boolean gapSplit)2998 static SeqLocPtr MapSubLoc
2999 (SeqLocPtr   master_subloc,
3000  SeqAlignPtr salp,
3001  Int4        master_row,
3002  Int4        prop_row,
3003  Boolean     gapSplit)
3004 {
3005   SeqLocPtr   prop_loc = NULL;
3006   SeqIdPtr    prop_sip;
3007   SeqIntPtr   sinp;
3008   IvalInfoPtr ival_head, ival;
3009   SeqPntPtr   spp;
3010   Uint1       strand;
3011   BioseqPtr   prop_bsp;
3012 
3013   if (master_subloc == NULL || salp == NULL || master_row < 1 || prop_row < 1)
3014   {
3015     return NULL;
3016   }
3017 
3018   prop_sip = AlnMgr2GetNthSeqIdPtr (salp, prop_row);
3019   if (prop_sip == NULL) return NULL;
3020   prop_bsp = BioseqFind (prop_sip);
3021   if (prop_bsp != NULL)
3022   {
3023     prop_sip = SeqIdFindBest (prop_bsp->id, SEQID_GENBANK);
3024     prop_sip = SeqIdDup (prop_sip);
3025   }
3026 
3027   switch (master_subloc->choice) {
3028     case SEQLOC_INT :
3029       sinp = (SeqIntPtr) master_subloc->data.ptrvalue;
3030       if (sinp != NULL) {
3031         strand = sinp->strand;
3032         ival_head = GetAlignmentIntervals (salp, master_row, prop_row, sinp->from, sinp->to);
3033         ival_head = MergeAdjacentIntervals (ival_head);
3034         if (ival_head != NULL) {
3035 
3036           /* what if one or the other interval maps into a gap? */
3037 
3038           if (gapSplit) {
3039             for (ival = ival_head; ival != NULL; ival = ival->next) {
3040               sinp = SeqIntNew ();
3041               sinp->from = ival->start2;
3042               sinp->to = ival->stop2;
3043               sinp->strand = strand;
3044               sinp->id = SeqIdDup (prop_sip);
3045               ValNodeAddPointer (&prop_loc, SEQLOC_INT, (Pointer) sinp);
3046             }
3047             prop_sip = SeqIdFree (prop_sip);
3048           } else {
3049             sinp = SeqIntNew ();
3050             sinp->from = ival_head->start2;
3051             for (ival = ival_head; ival->next != NULL; ival = ival->next) continue;
3052             sinp->to = ival->stop2;
3053             sinp->strand = strand;
3054             sinp->id = prop_sip;
3055             prop_sip = NULL;
3056             ValNodeAddPointer (&prop_loc, SEQLOC_INT, (Pointer) sinp);
3057           }
3058 
3059         }
3060         IvalInfoFree (ival_head);
3061       }
3062       break;
3063     case SEQLOC_PNT :
3064       spp = (SeqPntPtr) master_subloc->data.ptrvalue;
3065       if (spp != NULL) {
3066         strand = spp->strand;
3067         ival_head = GetAlignmentIntervals (salp, master_row, prop_row, spp->point, spp->point);
3068         if (ival_head != NULL) {
3069 
3070           spp = SeqPntNew ();
3071           spp->point = ival_head->start2;
3072           spp->strand = strand;
3073           spp->id = prop_sip;
3074           prop_sip = NULL;
3075           ValNodeAddPointer (&prop_loc, SEQLOC_PNT, (Pointer) spp);
3076 
3077         }
3078         IvalInfoFree (ival_head);
3079       }
3080       break;
3081     case SEQLOC_PACKED_PNT :
3082       /* not yet implemented */
3083       break;
3084     default :
3085       break;
3086   }
3087   prop_sip = SeqIdFree (prop_sip);
3088 
3089   return prop_loc;
3090 }
3091 
3092 typedef struct loclist
3093 {
3094   SeqIdPtr sip_list;
3095   SeqLocPtr slp;
3096 } LocListData, PNTR LocListPtr;
3097 
FindLocListForSeqId(ValNodePtr loc_list,SeqIdPtr sip)3098 static LocListPtr FindLocListForSeqId (ValNodePtr loc_list, SeqIdPtr sip)
3099 {
3100   SeqIdPtr   search_sip, find_sip;
3101   LocListPtr llp;
3102   ValNodePtr vnp;
3103 
3104   for (vnp = loc_list; vnp != NULL; vnp = vnp->next)
3105   {
3106     llp = (LocListPtr) vnp->data.ptrvalue;
3107     if (llp != NULL && llp->slp != NULL)
3108     {
3109       for (search_sip = llp->sip_list; search_sip != NULL; search_sip = search_sip->next)
3110       {
3111         for (find_sip = sip; find_sip != NULL; find_sip = find_sip->next)
3112         {
3113           if (SeqIdComp (find_sip, search_sip) == SIC_YES)
3114           {
3115             return llp;
3116           }
3117         }
3118       }
3119     }
3120   }
3121   return NULL;
3122 }
3123 
3124 /* Compare the Sequence ID of this location with the sequence IDs of other locations in the
3125  * list.  If the sequence ID matches that of another loclist, add to that loclist,
3126  * otherwise add a new loclist entry with the sequence ID of this sequence and the sequence IDs
3127  * of other sequences in the same segset if the segset flag is set.
3128  */
AssociatePropagatedSubloc(ValNodePtr subloc_list,SeqLocPtr prop_loc,Boolean segset)3129 static ValNodePtr AssociatePropagatedSubloc (ValNodePtr subloc_list, SeqLocPtr prop_loc, Boolean segset)
3130 {
3131   ValNodePtr   vnp;
3132   LocListPtr   llp = NULL;
3133   SeqIdPtr     prop_sip;
3134   BioseqPtr    prop_bsp;
3135   BioseqSetPtr parent_set;
3136   SeqEntryPtr  sep;
3137 
3138   if (prop_loc == NULL) return subloc_list;
3139   prop_sip = SeqLocId (prop_loc);
3140   if (prop_sip == NULL)
3141   {
3142     SeqLocFree (prop_loc);
3143     return subloc_list;
3144   }
3145 
3146   llp = FindLocListForSeqId (subloc_list, prop_sip);
3147   if (llp != NULL)
3148   {
3149     ValNodeAddPointer (&(llp->slp), prop_loc->choice, prop_loc->data.ptrvalue);
3150     prop_loc = ValNodeFree (prop_loc);
3151   }
3152   else
3153   {
3154     llp = (LocListPtr) MemNew (sizeof (LocListData));
3155     if (llp != NULL)
3156     {
3157       llp->sip_list = SeqIdDup (prop_sip);
3158       llp->slp = prop_loc;
3159       if (segset)
3160       {
3161         prop_bsp = BioseqFind (prop_sip);
3162         if (prop_bsp != NULL && prop_bsp->idx.parenttype == OBJ_BIOSEQSET)
3163         {
3164           parent_set = prop_bsp->idx.parentptr;
3165           if (parent_set != NULL && parent_set->_class == BioseqseqSet_class_parts)
3166           {
3167             /* add other IDs from set to list */
3168             for (sep = parent_set->seq_set; sep != NULL; sep = sep->next)
3169             {
3170               if (IS_Bioseq (sep))
3171               {
3172                 prop_bsp = (BioseqPtr) sep->data.ptrvalue;
3173                 prop_sip = SeqIdDup (prop_bsp->id);
3174                 ValNodeAddPointer (&(llp->sip_list), prop_sip->choice, prop_sip->data.ptrvalue);
3175                 prop_sip = ValNodeFree (prop_sip);
3176               }
3177             }
3178           }
3179         }
3180       }
3181       vnp = ValNodeAddPointer (&subloc_list, 0, llp);
3182     }
3183   }
3184   return subloc_list;
3185 }
3186 
FreeLocList(ValNodePtr loc_list)3187 static ValNodePtr FreeLocList (ValNodePtr loc_list)
3188 {
3189   LocListPtr llp;
3190 
3191   if (loc_list == NULL) return NULL;
3192   loc_list->next = FreeLocList (loc_list->next);
3193   llp = loc_list->data.ptrvalue;
3194   if (llp != NULL)
3195   {
3196     SeqIdFree (llp->sip_list);
3197     SeqLocFree (llp->slp);
3198     MemFree (llp);
3199   }
3200   ValNodeFree (loc_list);
3201   return NULL;
3202 }
3203 
GetMasterRow(SeqAlignPtr salp,SeqIdPtr sip)3204 static Int4 GetMasterRow (SeqAlignPtr salp, SeqIdPtr sip)
3205 {
3206   Int4     master_row = -1;
3207   SeqIdPtr sip_next;
3208 
3209   if (salp == NULL || sip == NULL)
3210   {
3211     return -1;
3212   }
3213 
3214   while (sip != NULL && master_row == -1)
3215   {
3216     sip_next = sip->next;
3217     sip->next = NULL;
3218     master_row = AlnMgr2GetFirstNForSip (salp, sip);
3219     sip->next = sip_next;
3220     sip = sip_next;
3221   }
3222   return master_row;
3223 }
3224 
3225 static Boolean
NthAlignmentSequenceInSeqPropList(SeqAlignPtr salp,Int4 n,ValNodePtr seq_for_prop)3226 NthAlignmentSequenceInSeqPropList
3227 (SeqAlignPtr salp,
3228  Int4        n,
3229  ValNodePtr  seq_for_prop)
3230 {
3231   SeqIdPtr    sip;
3232   ValNodePtr  seq_vnp;
3233   BioseqPtr   bsp;
3234   SeqEntryPtr sep;
3235   BioseqSetPtr bssp;
3236 
3237   if (salp == NULL || seq_for_prop == NULL)
3238   {
3239     return FALSE;
3240   }
3241 
3242   sip = AlnMgr2GetNthSeqIdPtr(salp, n);
3243   for (seq_vnp = seq_for_prop; seq_vnp != NULL; seq_vnp = seq_vnp->next)
3244   {
3245     if (SeqIdIn (sip, (SeqIdPtr) seq_vnp->data.ptrvalue))
3246     {
3247       return TRUE;
3248     }
3249     /* check for segments */
3250     bsp = BioseqFind (seq_vnp->data.ptrvalue);
3251     if (bsp != NULL && bsp->repr == Seq_repr_seg)
3252     {
3253       sep = SeqMgrGetSeqEntryForData (bsp);
3254       sep = sep->next; /* parts should be next */
3255       if (sep != NULL && IS_Bioseq_set (sep))
3256       {
3257         bssp = (BioseqSetPtr) sep->data.ptrvalue;
3258         if (bssp != NULL && bssp->_class == BioseqseqSet_class_parts)
3259         {
3260           for (sep = bssp->seq_set; sep != NULL; sep = sep->next)
3261           {
3262             if (IS_Bioseq (sep))
3263             {
3264               bsp = (BioseqPtr) sep->data.ptrvalue;
3265               if (bsp != NULL && SeqIdIn (sip, bsp->id))
3266               {
3267                 return TRUE;
3268               }
3269             }
3270           }
3271         }
3272       }
3273     }
3274   }
3275 
3276 
3277   return FALSE;
3278 }
3279 
AddNullLocToLists(ValNodePtr loc_list)3280 static void AddNullLocToLists (ValNodePtr loc_list)
3281 {
3282   ValNodePtr vnp;
3283   LocListPtr llp;
3284 
3285   for (vnp = loc_list; vnp != NULL; vnp = vnp->next)
3286   {
3287     llp = (LocListPtr) vnp->data.ptrvalue;
3288     if (llp != NULL)
3289     {
3290       ValNodeAddPointer (&(llp->slp), SEQLOC_NULL, NULL);
3291     }
3292   }
3293 }
3294 
3295 
GetPropagatedSublocations(SeqLocPtr master_location,Boolean gap_split,ValNodePtr prop_loc_list,ValNodePtr seq_for_prop,BoolPtr warned_about_master)3296 static ValNodePtr GetPropagatedSublocations
3297 (SeqLocPtr master_location,
3298  Boolean gap_split,
3299  ValNodePtr prop_loc_list,
3300  ValNodePtr seq_for_prop,
3301  BoolPtr warned_about_master)
3302 {
3303   SeqLocPtr   master_subloc;
3304   SeqIdPtr    master_subloc_id;
3305   BioseqPtr   master_subloc_bsp;
3306   SeqLocPtr   tmp_loc;
3307   SeqAlignPtr salp;
3308   Int4        master_row, num_rows, prop_row;
3309   SeqLocPtr   prop_loc;
3310 
3311   if (master_location == NULL) return prop_loc_list;
3312 
3313   master_subloc = SeqLocFindNext (master_location, NULL);
3314   while (master_subloc != NULL)
3315   {
3316     if (master_subloc->choice == SEQLOC_NULL) {
3317       /* don't need to propagate, just add nulls to each item in list */
3318       AddNullLocToLists (prop_loc_list);
3319     } else {
3320       master_subloc_id = SeqLocId (master_subloc);
3321       master_subloc_bsp = BioseqFind (master_subloc_id);
3322       master_subloc_id = master_subloc_bsp->id;
3323       if (master_subloc_bsp != NULL)
3324       {
3325         if (master_subloc_bsp->repr == Seq_repr_seg)
3326         {
3327           if (warned_about_master != NULL && ! *warned_about_master)
3328           {
3329             Message (MSG_OK, "Warning - you are propagating a feature that "
3330                     "contains locations on the master sequence.  These locations"
3331                     " will be mapped to the segments in the propagated features.");
3332             *warned_about_master = TRUE;
3333           }
3334           /* this is a location on the master segment */
3335           tmp_loc = SegLocToParts (master_subloc_bsp, master_subloc);
3336           prop_loc_list = GetPropagatedSublocations (tmp_loc, gap_split, prop_loc_list,
3337                                                      seq_for_prop, warned_about_master);
3338           tmp_loc = SeqLocFree (tmp_loc);
3339         }
3340         else
3341         {
3342           salp = FindAlignmentsForBioseq (master_subloc_bsp);
3343           while (salp != NULL)
3344           {
3345             master_row = GetMasterRow (salp, master_subloc_id);
3346             num_rows = AlnMgr2GetNumRows (salp);
3347             for (prop_row = 1; prop_row <= num_rows; prop_row++)
3348             {
3349               if (prop_row == master_row) continue;
3350               if (! NthAlignmentSequenceInSeqPropList (salp, prop_row, seq_for_prop))
3351               {
3352                 continue;
3353               }
3354 
3355               prop_loc = MapSubLoc (master_subloc, salp, master_row, prop_row, gap_split);
3356               prop_loc_list = AssociatePropagatedSubloc (prop_loc_list, prop_loc, TRUE);
3357             }
3358             salp = salp->next;
3359           }
3360         }
3361       }
3362     }
3363     master_subloc = SeqLocFindNext (master_location, master_subloc);
3364   }
3365   return prop_loc_list;
3366 }
3367 
MapLocForProp(SeqLocPtr master_location,Boolean gapSplit,ValNodePtr seq_for_prop,BoolPtr warned_about_master)3368 static ValNodePtr MapLocForProp
3369 (SeqLocPtr   master_location,
3370  Boolean     gapSplit,
3371  ValNodePtr  seq_for_prop,
3372  BoolPtr     warned_about_master)
3373 {
3374   ValNodePtr  prop_loc_list = NULL, vnp;
3375   LocListPtr  llp;
3376   SeqLocPtr   slp;
3377 
3378   if (master_location == NULL)
3379   {
3380     return NULL;
3381   }
3382 
3383   prop_loc_list = GetPropagatedSublocations (master_location, gapSplit, prop_loc_list,
3384                                              seq_for_prop, warned_about_master);
3385 
3386   /* now fix locations in prop_loc_list (add SEQLOC_MIX header to the locations that
3387    * are mixed)
3388    */
3389   for (vnp = prop_loc_list; vnp != NULL; vnp = vnp->next)
3390   {
3391     llp = (LocListPtr) vnp->data.ptrvalue;
3392     if (llp != NULL)
3393     {
3394       if (llp->slp != NULL)
3395       {
3396         if (llp->slp->next != NULL)
3397         {
3398           slp = ValNodeNew (NULL);
3399           slp->choice = SEQLOC_MIX;
3400           slp->data.ptrvalue = llp->slp;
3401           llp->slp = slp;
3402         }
3403       }
3404     }
3405   }
3406   return prop_loc_list;
3407 }
3408 
3409 
GetSegIdList(BioseqPtr master_seg)3410 static SeqIdPtr GetSegIdList (BioseqPtr master_seg)
3411 {
3412   SeqIdPtr  sip_list = NULL, sip_last = NULL, sip;
3413   SeqLocPtr slp;
3414   if (master_seg == NULL)
3415   {
3416     return NULL;
3417   }
3418   if (master_seg->repr != Seq_repr_seg)
3419   {
3420     sip_list = SeqIdDupList (master_seg->id);
3421   }
3422   else
3423   {
3424     for (slp = master_seg->seq_ext; slp != NULL; slp = slp->next)
3425     {
3426       sip = SeqIdDup (SeqLocId (slp));
3427       if (sip_last == NULL)
3428       {
3429         sip_list = sip;
3430       }
3431       else
3432       {
3433         sip_last->next = sip;
3434       }
3435       sip_last = sip;
3436     }
3437   }
3438   return sip_list;
3439 }
3440 
PropagateCodeBreaks(CdRegionPtr crp,SeqIdPtr sip,ValNodePtr codebreak_location_list,ValNodePtr codebreak_choice_list)3441 static void PropagateCodeBreaks
3442 (CdRegionPtr crp,
3443  SeqIdPtr sip,
3444  ValNodePtr codebreak_location_list,
3445  ValNodePtr codebreak_choice_list)
3446 {
3447   CodeBreakPtr cbp, last_cbp = NULL;
3448   ValNodePtr   choice_vnp, cbp_vnp;
3449   LocListPtr   llp;
3450   BioseqPtr    cds_bsp;
3451   SeqIdPtr     sip_list;
3452 
3453   if (crp == NULL || codebreak_location_list == NULL || crp->code_break == NULL)
3454   {
3455     return;
3456   }
3457 
3458   crp->code_break = CodeBreakFree (crp->code_break);
3459 
3460   cds_bsp = BioseqFind (sip);
3461   if (cds_bsp == NULL)
3462   {
3463     return;
3464   }
3465 
3466   sip_list = GetSegIdList (cds_bsp);
3467 
3468   for (cbp_vnp = codebreak_location_list, choice_vnp = codebreak_choice_list;
3469        cbp_vnp != NULL && choice_vnp != NULL;
3470        cbp_vnp = cbp_vnp->next, choice_vnp = choice_vnp->next)
3471   {
3472     llp = FindLocListForSeqId (cbp_vnp->data.ptrvalue, sip_list);
3473     if (llp != NULL)
3474     {
3475       cbp = CodeBreakNew ();
3476       if (cbp != NULL)
3477       {
3478         cbp->loc = llp->slp;
3479         llp->slp = NULL;
3480         MemCpy (&(cbp->aa), choice_vnp->data.ptrvalue, sizeof (cbp->aa));
3481         if (last_cbp == NULL)
3482         {
3483           crp->code_break = cbp;
3484         }
3485         else
3486         {
3487           last_cbp->next = cbp;
3488         }
3489       }
3490     }
3491   }
3492   SeqIdFree (sip_list);
3493 }
3494 
PropagateAnticodons(tRNAPtr trp,SeqIdPtr sip,ValNodePtr anticodon_location_list)3495 static void PropagateAnticodons
3496 (tRNAPtr trp,
3497  SeqIdPtr sip,
3498  ValNodePtr anticodon_location_list)
3499 {
3500   LocListPtr llp;
3501   BioseqPtr  trna_bsp;
3502   SeqIdPtr   sip_list;
3503 
3504   if (trp == NULL || anticodon_location_list == NULL || trp->anticodon == NULL)
3505   {
3506     return;
3507   }
3508 
3509   trp->anticodon = SeqLocFree (trp->anticodon);
3510 
3511   trna_bsp = BioseqFind (sip);
3512   if (trna_bsp == NULL)
3513   {
3514     return;
3515   }
3516   sip_list = GetSegIdList (trna_bsp);
3517 
3518   llp = FindLocListForSeqId (anticodon_location_list, sip_list);
3519   if (llp != NULL)
3520   {
3521     trp->anticodon = llp->slp;
3522     llp->slp = NULL;
3523   }
3524 
3525   SeqIdFree (sip_list);
3526 }
3527 
3528 
ExtendLocToEnd(SeqLocPtr location,BioseqPtr bsp,Uint1 strand)3529 static void ExtendLocToEnd (
3530   SeqLocPtr location,
3531   BioseqPtr bsp,
3532   Uint1 strand
3533 )
3534 
3535 {
3536   SeqIntPtr  sinp;
3537   SeqLocPtr  slp, last = NULL;
3538 
3539   slp = SeqLocFindNext (location, NULL);
3540   while (slp != NULL) {
3541     last = slp;
3542     slp = SeqLocFindNext (location, slp);
3543   }
3544   if (last == NULL) return;
3545 
3546   switch (last->choice) {
3547     case SEQLOC_INT :
3548       sinp = (SeqIntPtr) last->data.ptrvalue;
3549       if (sinp != NULL) {
3550         if (strand == Seq_strand_minus) {
3551           sinp->from = 0;
3552         } else {
3553           sinp->to = bsp->length - 1;
3554         }
3555       }
3556     case SEQLOC_PNT :
3557       /* not yet implemented */
3558       break;
3559     case SEQLOC_PACKED_PNT :
3560       /* not yet implemented */
3561       break;
3562     default :
3563       break;
3564   }
3565 }
3566 
TruncateCDS(SeqFeatPtr sfp,Uint1 frame,BioseqPtr pbsp)3567 static void TruncateCDS (
3568   SeqFeatPtr sfp,
3569   Uint1 frame,
3570   BioseqPtr pbsp
3571 )
3572 
3573 {
3574   Int4       len;
3575   SeqIntPtr  sinp;
3576   SeqLocPtr  slp;
3577   Int4       total = 0;
3578 
3579   if (frame > 0) {
3580     frame--;
3581   }
3582   slp = SeqLocFindNext (sfp->location, NULL);
3583   while (slp != NULL) {
3584     len = SeqLocLen (slp);
3585 
3586     if (len + total - frame <= (pbsp->length + 1) * 3) {
3587       total += len;
3588     } else {
3589       if (slp->choice == SEQLOC_INT) {
3590         sinp = (SeqIntPtr) slp->data.ptrvalue;
3591         if (sinp != NULL) {
3592           len = (pbsp->length + 1) * 3 - total;
3593           if (sinp->strand == Seq_strand_minus) {
3594             sinp->from = sinp->to - len + 1;
3595           } else {
3596             sinp->to = sinp->from + len - 1;
3597           }
3598         }
3599       }
3600       return;
3601     }
3602 
3603     slp = SeqLocFindNext (sfp->location, slp);
3604   }
3605 }
3606 
3607 /*------------------------------------------------------------------*/
3608 /*                                                                  */
3609 /* PropagateCDS () - Called from DoFeatProp() for CDS-specific      */
3610 /*                   feature propagation.                           */
3611 /*                                                                  */
3612 /*------------------------------------------------------------------*/
3613 
PropagateCDS(SeqFeatPtr dup,ProtRefPtr prp,BioseqPtr newbsp,Boolean stopCDS,Boolean transPast,Boolean cds3end,Uint1 frame,Uint1 strand)3614 static void PropagateCDS (SeqFeatPtr dup,
3615 			  ProtRefPtr prp,
3616 			  BioseqPtr  newbsp,
3617 			  Boolean    stopCDS,
3618 			  Boolean    transPast,
3619 			  Boolean    cds3end,
3620 			  Uint1      frame,
3621 			  Uint1      strand)
3622 {
3623   Uint2           entityID;
3624   MolInfoPtr      mip;
3625   Boolean         partial3;
3626   Boolean         partial5;
3627   BioseqPtr       pbsp;
3628   SeqDescrPtr     sdp;
3629   SeqIdPtr        sip;
3630   SeqFeatXrefPtr  xref;
3631   Boolean         xtend;
3632 
3633   /* Check parameters */
3634 
3635   if (dup == NULL || dup->data.choice != SEQFEAT_CDREGION || prp == NULL)
3636     return;
3637 
3638   /* Extend the location to the end if that was checked */
3639 
3640   if (transPast && (cds3end || !DoesCDSEndWithStopCodon (dup)))
3641     ExtendLocToEnd (dup->location, newbsp, strand);
3642 
3643   /**/
3644 
3645   prp = AsnIoMemCopy ((Pointer) prp,
3646                        (AsnReadFunc) ProtRefAsnRead,
3647                        (AsnWriteFunc) ProtRefAsnWrite);
3648 
3649   xref = SeqFeatXrefNew ();
3650   if (xref == NULL)
3651     return;
3652   xref->data.choice = SEQFEAT_PROT;
3653   xref->data.value.ptrvalue = (Pointer) prp;
3654   xref->next = dup->xref;
3655   dup->xref = xref;
3656 
3657   entityID = ObjMgrGetEntityIDForPointer (newbsp);
3658   PromoteXrefsEx (dup, newbsp, entityID, (Boolean) (! stopCDS), FALSE, FALSE);
3659 
3660   /* Truncate new CDS based on new protein length */
3661 
3662   sip = SeqLocId (dup->product);
3663   if (sip == NULL)
3664     return;
3665 
3666   pbsp = BioseqFindCore (sip);
3667   if (pbsp == NULL)
3668     return;
3669 
3670   TruncateCDS (dup, frame, pbsp);
3671 
3672   /**/
3673 
3674   CheckSeqLocForPartial (dup->location, &partial5, &partial3);
3675   if (cds3end) {
3676     xtend = FALSE;
3677     if (strand == Seq_strand_minus) {
3678       if (SeqLocStop (dup->location) == 0) {
3679         xtend = TRUE;
3680       }
3681     } else {
3682       if (SeqLocStop (dup->location) == newbsp->length - 1) {
3683         xtend = TRUE;
3684       }
3685     }
3686     if (xtend) {
3687       partial3 = TRUE;
3688       SetSeqLocPartial (dup->location, partial5, partial3);
3689       for (sdp = pbsp->descr; sdp != NULL; sdp = sdp->next) {
3690         if (sdp->choice != Seq_descr_molinfo) continue;
3691         mip = (MolInfoPtr) sdp->data.ptrvalue;
3692         if (mip == NULL) continue;
3693         if (partial5 && partial3) {
3694           mip->completeness = 5;
3695         } else if (partial5) {
3696           mip->completeness = 3;
3697         } else if (partial3) {
3698           mip->completeness = 4;
3699         }
3700       }
3701     }
3702   }
3703 
3704   /* Set partial flag */
3705 
3706   dup->partial = (Boolean) (partial5 || partial3);
3707 }
3708 
3709 
CheckForProteinAlignment(ByteStorePtr bs,BioseqPtr match_prot)3710 static SeqAlignPtr CheckForProteinAlignment (ByteStorePtr bs, BioseqPtr match_prot)
3711 {
3712   BioseqPtr   newBsp;
3713   SeqAlignPtr salp;
3714   SeqEntryPtr nwsep;
3715   Boolean     revcomp;
3716   ErrSev      oldsev;
3717 
3718   if (bs == NULL || match_prot == NULL)
3719   {
3720     return NULL;
3721   }
3722   newBsp = BioseqNew ();
3723   if (newBsp == NULL) {
3724     return NULL;
3725   }
3726 
3727   newBsp->id = SeqIdParse ("lcl|ProtAlign");
3728   newBsp->repr = Seq_repr_raw;
3729   newBsp->mol = Seq_mol_aa;
3730   newBsp->seq_data_type = Seq_code_ncbieaa;
3731   newBsp->seq_data = (SeqDataPtr) bs;
3732   newBsp->length = BSLen (bs);
3733 
3734   /* create SeqEntry for temporary protein bioseq to live in */
3735   nwsep = SeqEntryNew ();
3736   nwsep->choice = 1;
3737   nwsep->data.ptrvalue = newBsp;
3738   SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) newBsp, nwsep);
3739 
3740   oldsev = ErrSetMessageLevel (SEV_MAX);
3741   salp = Sequin_GlobalAlign2Seq (match_prot, newBsp, &revcomp);
3742   ErrSetMessageLevel (oldsev);
3743 
3744   SeqMgrDeleteFromBioseqIndex (newBsp);
3745   /* the calling function will free bs */
3746   newBsp->seq_data = NULL;
3747   nwsep = SeqEntryFree (nwsep);
3748   return salp;
3749 }
3750 
3751 /*------------------------------------------------------------------*/
3752 /*                                                                  */
3753 /* CalculateReadingFrame () -- Calculates a sequence's reading      */
3754 /*                             frame by seeing which frame          */
3755 /*                             generates the most amino acids       */
3756 /*                             when converted to a protein.         */
3757 /*                                                                  */
3758 /*------------------------------------------------------------------*/
3759 
CalculateReadingFrame(SeqFeatPtr sfp,Boolean partial3,BioseqPtr match_prot)3760 static Uint1 CalculateReadingFrame (SeqFeatPtr sfp, Boolean partial3, BioseqPtr match_prot)
3761 {
3762   ByteStorePtr  bs;
3763   CdRegionPtr   crp;
3764   Int4          len;
3765   Int4          max;
3766   Uint1         frame, orig_frame;
3767   Int2          i;
3768   CharPtr       protstr;
3769   SeqAlignPtr   salp = NULL;
3770   Boolean       best_is_aligned = FALSE;
3771 
3772   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
3773 
3774   max = 0;
3775   frame = 0;
3776 
3777   if (! partial3 && crp->frame != 0)
3778   {
3779   	bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
3780   	if (bs != NULL)
3781   	{
3782       protstr = BSMerge (bs, NULL);
3783       BSFree (bs);
3784       if (protstr != NULL) {
3785         len = StringLen (protstr);
3786         if (len > 0 && protstr [len - 1] == '*') {
3787           MemFree (protstr);
3788           return crp->frame;
3789         }
3790         MemFree (protstr);
3791       }
3792   	}
3793   }
3794   orig_frame = crp->frame;
3795   if (orig_frame == 0) {
3796     orig_frame = 1;
3797   }
3798   for (i = 1; i <= 3; i++) {
3799     crp->frame = (Uint1) i;
3800     bs = ProteinFromCdRegionEx (sfp, FALSE, FALSE);
3801     salp = CheckForProteinAlignment (bs, match_prot);
3802     len = BSLen (bs);
3803     BSFree (bs);
3804     if (salp == NULL)
3805     {
3806       /* if no alignment, take longest protein */
3807       if (! best_is_aligned && (len > max || (len == max && i == orig_frame))) {
3808         max = len;
3809         frame = (Uint1) i;
3810       }
3811     } else if (!best_is_aligned) {
3812       /* if this is the first alignment encountered, use this */
3813       max = len;
3814       frame = (Uint1) i;
3815       best_is_aligned = TRUE;
3816     } else if (len > max) {
3817       /* if this is not the first alignment, but the sequence is longer, use this */
3818       max = len;
3819       frame = (Uint1) i;
3820     }
3821     salp = SeqAlignFree (salp);
3822   }
3823 
3824   return frame;
3825 }
3826 
3827 /* we don't want to propagate Prot features if the target
3828  * sequence already has one.
3829  */
OkToPropagate(SeqFeatPtr sfp,BioseqPtr bsp)3830 static Boolean OkToPropagate(SeqFeatPtr sfp, BioseqPtr bsp)
3831 {
3832   SeqMgrFeatContext fcontext;
3833 
3834   if (sfp == NULL || bsp == NULL) return FALSE;
3835   /* never ok if a gap */
3836   if (sfp->idx.subtype == FEATDEF_gap) return FALSE;
3837   /* always ok if not a Prot feature */
3838   if (sfp->idx.subtype != FEATDEF_PROT) return TRUE;
3839   /* always ok if not a protein sequence */
3840   if (ISA_na (bsp->mol)) return TRUE;
3841   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_PROT, &fcontext);
3842   if (sfp == NULL)
3843     return TRUE;
3844   else
3845     return FALSE;
3846 }
3847 
3848 
GetSegSetId(SeqLocPtr slp)3849 static SeqIdPtr GetSegSetId (SeqLocPtr slp)
3850 {
3851   SeqLocPtr    sub_slp;
3852   SeqIdPtr     master_sip, part_sip;
3853   BioseqPtr    seg_bsp;
3854   BioseqSetPtr parent_set;
3855   BioseqSetPtr last_parent_set = NULL;
3856   SeqEntryPtr  sep;
3857   BioseqPtr    parent_bsp;
3858 
3859   if (slp == NULL) return NULL;
3860   master_sip = SeqLocId (slp);
3861   if (master_sip != NULL || slp->choice != SEQLOC_MIX)
3862   {
3863     return master_sip;
3864   }
3865   /* make sure all parts are from the same segmented set */
3866   for (sub_slp = slp->data.ptrvalue; sub_slp != NULL; sub_slp = sub_slp->next)
3867   {
3868     part_sip = SeqLocId (sub_slp);
3869     seg_bsp = BioseqFind (part_sip);
3870     if (seg_bsp == NULL || seg_bsp->idx.parenttype != OBJ_BIOSEQSET
3871         || seg_bsp->idx.parentptr == NULL)
3872     {
3873       return NULL;
3874     }
3875     parent_set = (BioseqSetPtr) seg_bsp->idx.parentptr;
3876     if (parent_set->_class != BioseqseqSet_class_parts
3877         || parent_set->idx.parenttype != OBJ_BIOSEQSET
3878         || parent_set->idx.parentptr == NULL)
3879     {
3880       return NULL;
3881     }
3882     if (last_parent_set == NULL)
3883     {
3884       last_parent_set = parent_set;
3885     }
3886     else if (last_parent_set != parent_set)
3887     {
3888       return NULL;
3889     }
3890   }
3891   if (last_parent_set == NULL)
3892   {
3893     return NULL;
3894   }
3895   parent_set = (BioseqSetPtr) last_parent_set->idx.parentptr;
3896   if (parent_set->_class != BioseqseqSet_class_segset)
3897   {
3898     return NULL;
3899   }
3900   for (sep = parent_set->seq_set; sep != NULL && ! IS_Bioseq (sep); sep = sep->next)
3901   {
3902   }
3903   if (sep == NULL) return NULL;
3904   parent_bsp = sep->data.ptrvalue;
3905   if (parent_bsp == NULL) return NULL;
3906   master_sip = parent_bsp->id;
3907   return master_sip;
3908 }
3909 
3910 /* for each feature, find all propagated locations and create features using
3911  * those locations.
3912  */
3913 extern void
PropagateOneFeat(SeqFeatPtr sfp,Boolean gapSplit,Boolean fuse_joints,Boolean stopCDS,Boolean transPast,Boolean cds3end,ValNodePtr seq_for_prop,BoolPtr warned_about_master)3914 PropagateOneFeat
3915 (SeqFeatPtr sfp,
3916  Boolean    gapSplit,
3917  Boolean    fuse_joints,
3918  Boolean    stopCDS,
3919  Boolean    transPast,
3920  Boolean    cds3end,
3921  ValNodePtr seq_for_prop, /* ValNode data.ptrvalue points to SeqId */
3922  BoolPtr    warned_about_master)
3923 {
3924   ValNodePtr      feature_location_list, vnp;
3925   ValNodePtr      codebreak_location_list = NULL;
3926   ValNodePtr      codebreak_choice_list = NULL;
3927   ValNodePtr      anticodon_location_list = NULL;
3928   CodeBreakPtr    cbp;
3929   CdRegionPtr     crp;
3930   SeqFeatPtr      dup;
3931   Uint1           frame = 0;
3932   BioseqPtr       newbsp;
3933   SeqLocPtr       newloc, mergedloc;
3934   Boolean         partial5;
3935   Boolean         partial3;
3936   RnaRefPtr       rrp;
3937   SeqEntryPtr     sep;
3938   SeqIdPtr        sip;
3939   tRNAPtr         trp;
3940   LocListPtr      llp;
3941   Uint1           strand;
3942   ProtRefPtr      prp = NULL;
3943   BioseqPtr       pbsp = NULL;
3944   SeqFeatPtr      prot;
3945 
3946   if (sfp == NULL || sfp->location == NULL) return;
3947 
3948   feature_location_list = MapLocForProp (sfp->location, gapSplit,
3949                                          seq_for_prop, warned_about_master);
3950   if (feature_location_list == NULL) return;
3951 
3952   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
3953 
3954   /* also need to propagate locations for CDS code breaks and tRNA anticodons */
3955   if (sfp->data.choice == SEQFEAT_CDREGION)
3956   {
3957     crp = (CdRegionPtr) sfp->data.value.ptrvalue;
3958     if (crp != NULL)
3959     {
3960       for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next)
3961       {
3962         vnp = MapLocForProp (cbp->loc, gapSplit, seq_for_prop, warned_about_master);
3963         ValNodeAddPointer (&codebreak_location_list, 0, vnp);
3964         ValNodeAddPointer (&codebreak_choice_list, 0, &(cbp->aa));
3965       }
3966     }
3967     sip = SeqLocId (sfp->product);
3968     if (sip != NULL)
3969     {
3970       pbsp = BioseqFindCore (sip);
3971       if (pbsp != NULL)
3972       {
3973         prot = SeqMgrGetBestProteinFeature (pbsp, NULL);
3974         if (prot != NULL && prot->data.choice == SEQFEAT_PROT)
3975         {
3976           prp = (ProtRefPtr) prot->data.value.ptrvalue;
3977         }
3978       }
3979     }
3980   }
3981   else if (sfp->data.choice == SEQFEAT_RNA)
3982   {
3983     rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
3984     if (rrp != NULL && rrp->ext.choice == 2)
3985     {
3986       trp = (tRNAPtr) rrp->ext.value.ptrvalue;
3987       if (trp != NULL && trp->anticodon != NULL)
3988       {
3989         anticodon_location_list = MapLocForProp (trp->anticodon, gapSplit,
3990                                                  seq_for_prop, warned_about_master);
3991       }
3992     }
3993   }
3994 
3995   for (vnp = feature_location_list; vnp != NULL; vnp = vnp->next)
3996   {
3997     llp = (LocListPtr) vnp->data.ptrvalue;
3998     if (llp == NULL)
3999     {
4000       continue;
4001     }
4002     newloc = llp->slp;
4003     llp->slp = NULL;
4004     if (newloc == NULL)
4005     {
4006       continue;
4007     }
4008 
4009     mergedloc = NULL;
4010     if (fuse_joints)
4011     {
4012       mergedloc = MergeAdjacentSeqLocIntervals (newloc);
4013 	    if (mergedloc != NULL)
4014 	    {
4015         SeqLocFree (newloc);
4016         newloc = mergedloc;
4017 	    }
4018     }
4019 
4020     /* if we have a mixed location with multiple sequences, SeqLocId will
4021      * return NULL.
4022      * We should check to see if we are trying to create a feature for
4023      * a segset, in which case we'll want the Bioseq for the master segment.
4024      */
4025     sip = GetSegSetId (newloc);
4026 
4027     dup = AsnIoMemCopy ((Pointer) sfp,
4028                         (AsnReadFunc) SeqFeatAsnRead,
4029                         (AsnWriteFunc) SeqFeatAsnWrite);
4030     SeqLocFree (dup->location);
4031     dup->location = newloc;
4032     SetSeqLocPartial (dup->location, partial5, partial3);
4033 
4034     /* do not propagate feature IDs or links */
4035     ClearFeatIDs (dup);
4036     ClearFeatIDXrefs (dup);
4037 
4038     /* clean up product before we look for (and maybe don't find) the newbsp */
4039     if (dup->product != NULL)
4040       dup->product = SeqLocFree (dup->product);
4041 
4042     switch (dup->data.choice) {
4043       case SEQFEAT_CDREGION :
4044         crp = (CdRegionPtr) dup->data.value.ptrvalue;
4045         if (crp != NULL) {
4046           crp->frame = CalculateReadingFrame (dup, partial3, pbsp);
4047           frame = crp->frame;
4048 
4049           PropagateCodeBreaks (crp, sip,
4050                                codebreak_location_list,
4051                                codebreak_choice_list);
4052         }
4053         break;
4054       case SEQFEAT_RNA :
4055         rrp = (RnaRefPtr) dup->data.value.ptrvalue;
4056         if (rrp != NULL && rrp->ext.choice == 2) {
4057           trp = (tRNAPtr) rrp->ext.value.ptrvalue;
4058           if (trp != NULL && trp->anticodon != NULL)
4059           {
4060             PropagateAnticodons (trp, sip, anticodon_location_list);
4061           }
4062         }
4063         break;
4064       default :
4065         break;
4066     }
4067 
4068     newbsp = BioseqFindCore (sip);
4069     if (newbsp == NULL)
4070       return;
4071 
4072     /* need to call OkToPropagate with sfp instead of dup
4073      * because dup has not been indexed yet, so subtype isn't set.
4074      */
4075     if (OkToPropagate(sfp, newbsp))
4076     {
4077       sep = SeqMgrGetSeqEntryForData (newbsp);
4078       if (sep == NULL)
4079         return;
4080       CreateNewFeature (sep, NULL, dup->data.choice, dup);
4081 
4082       /* If we're doing a CDS propagation, then */
4083       /* do the extra stuff related to that.    */
4084 
4085       if (SEQFEAT_CDREGION == dup->data.choice)
4086       {
4087         strand = SeqLocStrand (dup->location);
4088 
4089         PropagateCDS (dup, prp, newbsp, stopCDS, transPast, cds3end, frame, strand);
4090       }
4091     }
4092     else
4093     {
4094       SeqFeatFree (dup);
4095     }
4096   }
4097 
4098   feature_location_list = FreeLocList (feature_location_list);
4099   anticodon_location_list = FreeLocList (anticodon_location_list);
4100   for (vnp = codebreak_location_list; vnp != NULL; vnp = vnp->next)
4101   {
4102     vnp->data.ptrvalue = FreeLocList (vnp->data.ptrvalue);
4103   }
4104   codebreak_location_list = ValNodeFree (codebreak_location_list);
4105   codebreak_choice_list = ValNodeFree (codebreak_choice_list);
4106 
4107 }
4108 
CDSgoesToEnd(BioseqPtr bsp,SeqMgrFeatContext PNTR fcontext)4109 static Boolean CDSgoesToEnd (
4110   BioseqPtr bsp,
4111   SeqMgrFeatContext PNTR fcontext
4112 )
4113 
4114 {
4115   if (fcontext->strand == Seq_strand_minus) {
4116     if (fcontext->left == 0 && fcontext->partialR) return TRUE;
4117   } else {
4118     if (fcontext->right == bsp->length - 1 && fcontext->partialR) return TRUE;
4119   }
4120   return FALSE;
4121 }
4122 
DoFixCDS(SeqFeatPtr sfp,Pointer userdata)4123 extern void DoFixCDS (
4124   SeqFeatPtr sfp,
4125   Pointer userdata
4126 )
4127 
4128 {
4129   BaseFormPtr        bfp;
4130   ByteStorePtr       bs;
4131   BioseqPtr          bsp;
4132   Boolean            change_partials = FALSE;
4133   SeqMgrFeatContext  context;
4134   CdRegionPtr        crp;
4135   size_t             len;
4136   Boolean            partial5;
4137   Boolean            partial3;
4138   SeqIntPtr          sintp;
4139   SeqLocPtr          slp;
4140   CharPtr            str;
4141 
4142   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return;
4143   bfp = (BaseFormPtr) userdata;
4144   if (SeqMgrGetDesiredFeature (bfp->input_entityID, NULL,
4145                                0, 0, sfp, &context) != sfp) return;
4146   bsp = context.bsp;
4147   if (bsp == NULL) return;
4148 
4149   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
4150   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
4151   if (crp->frame > 1) {
4152     if (context.strand == Seq_strand_minus) {
4153       if (context.right == bsp->length - 1) {
4154         partial5 = TRUE;
4155         change_partials = TRUE;
4156       }
4157     } else {
4158       if (context.left == 0) {
4159         partial5 = TRUE;
4160         change_partials = TRUE;
4161       }
4162     }
4163   }
4164     bs = ProteinFromCdRegion (sfp, TRUE);
4165     if (bs != NULL) {
4166       str = BSMerge (bs, NULL);
4167       BSFree (bs);
4168       if (str != NULL) {
4169         if (*str == '-') {
4170           if (! partial5) {
4171             partial5 = TRUE;
4172             change_partials = TRUE;
4173           }
4174         }
4175         len = StringLen (str);
4176         if (len > 0 && str [len - 1] != '*') {
4177           if (context.strand == Seq_strand_minus) {
4178           } else {
4179             if (bsp->length - context.right < 3) {
4180               slp = SeqLocFindNext (sfp->location, NULL);
4181               while (slp != NULL) {
4182                 if (slp->choice == SEQLOC_INT) {
4183                   sintp = (SeqIntPtr) slp->data.ptrvalue;
4184                   if (sintp != NULL) {
4185                     if (sintp->to == context.right) {
4186                       sintp->to = bsp->length - 1;
4187                     }
4188                   }
4189                 }
4190                 slp = SeqLocFindNext (sfp->location, slp);
4191               }
4192             }
4193             partial3 = TRUE;
4194             change_partials = TRUE;
4195           }
4196         }
4197         MemFree (str);
4198       }
4199     }
4200   if (change_partials) {
4201     SetSeqLocPartial (sfp->location, partial5, partial3);
4202     ResynchCDSPartials (sfp, NULL);
4203   }
4204 }
4205 
4206 extern SeqFeatPtr
GetNextFeatureOnSegOrMaster(BioseqPtr bsp,SeqFeatPtr sfp,Uint4 itemID,Uint4 index,SeqMgrFeatContextPtr fcontext)4207 GetNextFeatureOnSegOrMaster
4208 (BioseqPtr bsp, SeqFeatPtr sfp, Uint4 itemID, Uint4 index, SeqMgrFeatContextPtr fcontext)
4209 {
4210   BioseqSetPtr       bssp;
4211   SeqEntryPtr        sep;
4212   BioseqPtr          master_bsp = NULL;
4213   SeqFeatPtr         next_sfp;
4214   SeqLocPtr          slp;
4215   SeqIdPtr           loc_id;
4216   Boolean            on_this_segment = FALSE;
4217 
4218   if (bsp == NULL)
4219   {
4220     return NULL;
4221   }
4222   if (bsp->idx.parenttype != OBJ_BIOSEQSET || bsp->idx.parentptr == NULL)
4223   {
4224     return SeqMgrGetNextFeature (bsp, sfp, itemID, index, fcontext);
4225   }
4226 
4227   bssp = (BioseqSetPtr) bsp->idx.parentptr;
4228   if (bssp == NULL || bssp->_class != BioseqseqSet_class_parts
4229       || bssp->idx.parenttype != OBJ_BIOSEQSET || bsp->idx.parentptr == NULL)
4230   {
4231     return SeqMgrGetNextFeature (bsp, sfp, itemID, index, fcontext);
4232   }
4233 
4234   bssp = bssp->idx.parentptr;
4235   if (bssp->_class != BioseqseqSet_class_segset)
4236   {
4237     return SeqMgrGetNextFeature (bsp, sfp, itemID, index, fcontext);
4238   }
4239 
4240   for (sep = bssp->seq_set; sep != NULL && master_bsp == NULL; sep = sep->next)
4241   {
4242     if (IS_Bioseq (sep))
4243     {
4244       master_bsp = sep->data.ptrvalue;
4245       if (master_bsp != NULL && master_bsp->repr != Seq_repr_seg)
4246       {
4247         master_bsp = NULL;
4248       }
4249     }
4250   }
4251 
4252   if (master_bsp == NULL)
4253   {
4254     return SeqMgrGetNextFeature (bsp, sfp, itemID, index, fcontext);
4255   }
4256 
4257   next_sfp = SeqMgrGetNextFeature (master_bsp, sfp, itemID, index, fcontext);
4258   if (next_sfp == NULL) return NULL;
4259 
4260   while (next_sfp != NULL && !on_this_segment)
4261   {
4262     for (slp = SeqLocFindNext (next_sfp->location, NULL);
4263          slp != NULL && ! on_this_segment; slp = SeqLocFindNext (next_sfp->location, slp))
4264     {
4265       loc_id = SeqLocId (slp);
4266       if (SeqIdIn (loc_id, bsp->id))
4267       {
4268         on_this_segment = TRUE;
4269       }
4270     }
4271     if (!on_this_segment)
4272     {
4273       next_sfp = SeqMgrGetNextFeature (master_bsp, next_sfp, itemID, index, fcontext);
4274     }
4275   }
4276 
4277   return next_sfp;
4278 }
4279 
4280 
FeatureInAlignmentInterval(SeqFeatPtr sfp,BioseqPtr master_bsp,SeqAlignPtr salp_list)4281 static Boolean FeatureInAlignmentInterval (SeqFeatPtr sfp, BioseqPtr master_bsp, SeqAlignPtr salp_list)
4282 {
4283   SeqAlignPtr s;
4284   Boolean     rval = FALSE;
4285   Int4        start, stop, tmp, i, aln_start, aln_stop;
4286   SeqIdPtr    sip;
4287 
4288   if (sfp == NULL) {
4289     return FALSE;
4290   }
4291 
4292   start = SeqLocStart (sfp->location);
4293   stop = SeqLocStop (sfp->location);
4294   if (start > stop ) {
4295     tmp = start;
4296     start = stop;
4297     stop = tmp;
4298   }
4299 
4300   for (s = salp_list; s != NULL && !rval; s = s->next) {
4301     /* find position of master in alignment */
4302     for (i = 0; i < s->dim; i++) {
4303       sip = AlnMgrGetNthSeqIdPtr(s, i + 1);
4304       if (SeqIdIn (sip, master_bsp->id)) {
4305         AlnMgr2GetNthSeqRangeInSA(s, i + 1, &aln_start, &aln_stop);
4306         if (aln_start > aln_stop) {
4307           tmp = aln_start;
4308           aln_start = aln_stop;
4309           aln_stop = tmp;
4310         }
4311         if (stop < aln_start || start > aln_stop) {
4312           /* outside */
4313         } else {
4314           rval = TRUE;
4315         }
4316         break;
4317       }
4318     }
4319   }
4320   return rval;
4321 }
4322 
4323 
AreAllFeaturesCoveredByAlignmentIntervals(SelStructPtr sel,BioseqPtr bsp)4324 static Boolean AreAllFeaturesCoveredByAlignmentIntervals (SelStructPtr sel, BioseqPtr bsp)
4325 {
4326   SelStructPtr ssp;
4327   SeqAlignPtr  salp, salp_next;
4328   Boolean      rval = TRUE;
4329   SeqFeatPtr   sfp;
4330   SeqMgrFeatContext  fcontext;
4331 
4332   salp = FindAlignmentsForBioseq (bsp);
4333   if (salp == NULL) {
4334     return FALSE;
4335   }
4336 
4337   if (sel != NULL) {
4338     for (ssp = sel; ssp != NULL && rval; ssp = ssp->next) {
4339       sfp = SeqMgrGetDesiredFeature (ssp->entityID, NULL, ssp->itemID, 0, NULL, &fcontext);
4340       if (sfp != NULL) {
4341         rval = FeatureInAlignmentInterval (sfp, bsp, salp);
4342       }
4343     }
4344   } else {
4345     sfp = GetNextFeatureOnSegOrMaster (bsp, NULL, 0, 0, &fcontext);
4346     while (sfp != NULL && rval) {
4347       rval = FeatureInAlignmentInterval (sfp, bsp, salp);
4348       sfp = GetNextFeatureOnSegOrMaster (bsp, sfp, 0, 0, &fcontext);
4349     }
4350   }
4351 
4352   while (salp != NULL) {
4353     salp_next = salp->next;
4354     salp->next = NULL;
4355     salp = SeqAlignFree (salp);
4356     salp = salp_next;
4357   }
4358   return rval;
4359 }
4360 
4361 
AcceptFeatProp(ButtoN b)4362 static void AcceptFeatProp (
4363   ButtoN b
4364 )
4365 
4366 {
4367   BioseqPtr          bsp;
4368   Boolean            cds3end;
4369   DenseSegPtr        dsp;
4370   Uint2              entityID;
4371   SeqMgrFeatContext  fcontext;
4372   FprDataPtr         fdp;
4373   Boolean            fixCDS;
4374   Boolean            gapSplit;
4375   SeqAlignPtr        salp;
4376   SeqEntryPtr        sep;
4377   SeqFeatPtr         sfp;
4378   SeqIdPtr           sip;
4379   SeqIdPtr           sip_head;
4380   SeqIdPtr           sip_new;
4381   SeqIdPtr           sip_prev;
4382   SeqIdPtr           sip_tmp;
4383   Boolean            stopCDS;
4384   Boolean            transPast;
4385   Boolean            fuse_joints = FALSE;
4386   Boolean            warned_about_master = FALSE;
4387   ValNodePtr         seq_for_prop = NULL;
4388   SelStructPtr       sel = NULL, ssp;
4389 
4390   fdp = (FprDataPtr) GetObjectExtra (b);
4391   if (fdp == NULL) return;
4392   SafeHide (fdp->form);
4393 
4394   bsp = fdp->bsp;
4395   salp = fdp->salp;
4396   if (bsp == NULL || salp == NULL) {
4397     Remove (fdp->form);
4398     return;
4399   }
4400 
4401 
4402   if (GetValue (fdp->allOrSel) == 2) {
4403     sel = ObjMgrGetSelected ();
4404     if (sel == NULL) {
4405       Message (MSG_ERROR, "You have not selected features to propagate!");
4406       SafeShow (fdp->form);
4407       return;
4408     }
4409   }
4410 
4411   if (!AreAllFeaturesCoveredByAlignmentIntervals(sel, bsp)) {
4412     if (sel == NULL) {
4413       Message (MSG_ERROR, "Your alignment does not cover all features on the sequence.  Unable to propagate.");
4414     } else {
4415       Message (MSG_ERROR, "Your alignment does not cover all selected features.  Unable to propagate");
4416     }
4417     SafeShow (fdp->form);
4418     return;
4419   }
4420 
4421   if (GetValue (fdp->gapSplit) == 1) {
4422     gapSplit = FALSE;
4423   } else {
4424     gapSplit= TRUE;
4425   }
4426   if (GetStatus (fdp->stopCDS)) {
4427     stopCDS = TRUE;
4428   } else {
4429     stopCDS = FALSE;
4430   }
4431   if (GetStatus (fdp->transPast)) {
4432     transPast = TRUE;
4433   } else {
4434     transPast = FALSE;
4435   }
4436   if (GetStatus (fdp->fixCDS)) {
4437     fixCDS = TRUE;
4438   } else {
4439     fixCDS = FALSE;
4440   }
4441   if (GetStatus (fdp->fuseJoints)) {
4442     fuse_joints = TRUE;
4443   } else {
4444 	  fuse_joints = FALSE;
4445   }
4446 
4447   seq_for_prop = DialogToPointer (fdp->sequence_list_dlg);
4448   if (seq_for_prop != NULL && seq_for_prop->next == NULL)
4449   {
4450     for (sip = bsp->id; sip != NULL; sip = sip->next)
4451     {
4452       if (SeqIdIn (sip, (SeqIdPtr) seq_for_prop->data.ptrvalue))
4453       {
4454         Message (MSG_ERROR, "Can't propagate from a sequence to itself!");
4455         SafeShow (fdp->form);
4456         return;
4457       }
4458     }
4459   }
4460 
4461   SeqEntrySetScope (NULL);
4462 
4463   /* need to find alignment for each feature and row within that alignment for the feature */
4464 
4465   dsp = (DenseSegPtr)(salp->segs);
4466   sip = SeqIdFindBest (bsp->id, 0);
4467   sip_tmp = dsp->ids;
4468   sip_head = sip_prev = NULL;
4469   while (sip_tmp != NULL)
4470   {
4471     if (SeqIdComp(sip_tmp, bsp->id) == SIC_YES)
4472        sip_new = SeqIdDup(sip);
4473     else
4474        sip_new = SeqIdDup(sip_tmp);
4475     if (sip_head != NULL)
4476     {
4477        sip_prev->next = sip_new;
4478        sip_prev = sip_new;
4479     } else
4480        sip_head = sip_prev = sip_new;
4481     sip_tmp = sip_tmp->next;
4482   }
4483   dsp->ids = sip_head;
4484 
4485   if (sel != NULL) {
4486     for (ssp = sel; ssp != NULL; ssp = ssp->next) {
4487       sfp = SeqMgrGetDesiredFeature (ssp->entityID, NULL, ssp->itemID, 0, NULL, &fcontext);
4488       if (sfp != NULL) {
4489         cds3end = CDSgoesToEnd (bsp, &fcontext);
4490         PropagateOneFeat (sfp, gapSplit, fuse_joints, stopCDS, transPast,
4491                           cds3end, seq_for_prop, &warned_about_master);
4492       }
4493     }
4494   } else {
4495 
4496     /* propagate all features on bioseq */
4497 
4498     sfp = GetNextFeatureOnSegOrMaster (bsp, NULL, 0, 0, &fcontext);
4499     while (sfp != NULL) {
4500       cds3end = CDSgoesToEnd (bsp, &fcontext);
4501       PropagateOneFeat (sfp, gapSplit, fuse_joints, stopCDS, transPast,
4502                         cds3end, seq_for_prop, &warned_about_master);
4503 
4504       sfp = GetNextFeatureOnSegOrMaster (bsp, sfp, 0, 0, &fcontext);
4505     }
4506   }
4507 
4508   seq_for_prop = ValNodeFree (seq_for_prop);
4509   if (fixCDS) {
4510     entityID = ObjMgrGetEntityIDForPointer (bsp);
4511     sep = GetTopSeqEntryForEntityID (entityID);
4512     fdp->input_entityID = entityID;
4513     /* reindex before calling DoFixCDS */
4514     SeqMgrIndexFeatures (entityID, NULL);
4515     VisitFeaturesInSep (sep, fdp, DoFixCDS);
4516   }
4517 
4518   entityID = ObjMgrGetEntityIDForPointer (bsp);
4519   ObjMgrSetDirtyFlag (entityID, TRUE);
4520   ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
4521 
4522   if (GetStatus (fdp->leave_dlg_up)) {
4523     SafeShow (fdp->form);
4524   } else {
4525     Remove (fdp->form);
4526     Update();
4527   }
4528 }
4529 
SetFeaturePropagateAccept(Pointer userdata)4530 static void SetFeaturePropagateAccept (Pointer userdata)
4531 {
4532   FprDataPtr  fdp;
4533   ValNodePtr  err_list;
4534 
4535   fdp = (FprDataPtr) userdata;
4536   if (fdp == NULL)
4537   {
4538     return;
4539   }
4540   err_list = TestDialog (fdp->sequence_list_dlg);
4541   if (err_list == NULL)
4542   {
4543     Enable (fdp->accept);
4544   }
4545   else
4546   {
4547     Disable (fdp->accept);
4548   }
4549   ValNodeFree (err_list);
4550 }
4551 
FeaturePropagateFormMessage(ForM f,Int2 mssg)4552 static void FeaturePropagateFormMessage (ForM f, Int2 mssg)
4553 
4554 {
4555   BaseFormPtr        bfp;
4556   StdEditorProcsPtr  sepp;
4557 
4558   bfp = (BaseFormPtr) GetObjectExtra (f);
4559   if (bfp == NULL) return;
4560   switch (mssg) {
4561     case VIB_MSG_CLOSE :
4562       Remove (f);
4563       break;
4564     default :
4565       sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
4566       if (sepp != NULL && sepp->handleMessages != NULL) {
4567         sepp->handleMessages (f, mssg);
4568       }
4569       break;
4570   }
4571 }
4572 
4573 #ifdef WIN_MAC
UpdateSequenceFormActivated(WindoW w)4574 extern void UpdateSequenceFormActivated (WindoW w)
4575 
4576 {
4577   HANDLE openItem;
4578   HANDLE closeItem;
4579   BoolPtr pInitialFormsActive;
4580 
4581   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
4582 
4583   pInitialFormsActive = GetAppProperty (SEQFORM_INIT_ACTIVE);
4584   if (pInitialFormsActive != NULL)
4585   {
4586     *pInitialFormsActive = FALSE;
4587   }
4588 
4589   openItem = (HANDLE) GetAppProperty (SEQFORM_OPEN_ITEM);
4590   closeItem = (HANDLE) GetAppProperty (SEQFORM_CLOSE_ITEM);
4591 
4592   RepeatProcOnHandles (Enable,
4593                    (HANDLE) openItem,
4594                    (HANDLE) closeItem,
4595                    NULL);
4596 }
4597 
UpdateSequenceFormActivate(WindoW w)4598 extern void UpdateSequenceFormActivate (WindoW w)
4599 
4600 {
4601   BaseFormPtr  bfp;
4602 
4603   bfp = (BaseFormPtr) GetObjectExtra (w);
4604   if (bfp != NULL) {
4605     if (bfp->activate != NULL) {
4606       bfp->activate (w);
4607     }
4608   }
4609 }
4610 #endif
4611 
4612 
FeaturePropagateFormMsgFunc(OMMsgStructPtr ommsp)4613 static Int2 LIBCALLBACK FeaturePropagateFormMsgFunc (OMMsgStructPtr ommsp)
4614 {
4615   OMUserDataPtr  omudp;
4616   FprDataPtr     fp = NULL;
4617 
4618   omudp = (OMUserDataPtr)(ommsp->omuserdata);
4619   if (omudp == NULL) return OM_MSG_RET_ERROR;
4620   fp = (FprDataPtr) omudp->userdata.ptrvalue;
4621   if (fp == NULL) return OM_MSG_RET_ERROR;
4622 
4623   switch (ommsp->message)
4624   {
4625       case OM_MSG_UPDATE:
4626           break;
4627       case OM_MSG_DESELECT:
4628           break;
4629 
4630       case OM_MSG_SELECT:
4631           break;
4632       case OM_MSG_DEL:
4633           Remove (fp->form);
4634           break;
4635       case OM_MSG_HIDE:
4636           break;
4637       case OM_MSG_SHOW:
4638           break;
4639       case OM_MSG_FLUSH:
4640           Remove (fp->form);
4641           break;
4642       default:
4643           break;
4644   }
4645   return OM_MSG_RET_OK;
4646 }
4647 
4648 
CleanupFeaturePropagateForm(GraphiC g,VoidPtr data)4649 static void CleanupFeaturePropagateForm (GraphiC g, VoidPtr data)
4650 
4651 {
4652   FprDataPtr fp;
4653 
4654   fp = (FprDataPtr) data;
4655   if (fp != NULL) {
4656     ObjMgrFreeUserData (fp->input_entityID, fp->procid, fp->proctype, fp->userkey);
4657   }
4658   StdCleanupFormProc (g, data);
4659 }
4660 
4661 
FeaturePropagateForm(BioseqPtr bsp,SeqAlignPtr salp,Uint4 selFeatItemID)4662 extern ForM FeaturePropagateForm (
4663   BioseqPtr bsp,
4664   SeqAlignPtr salp,
4665   Uint4 selFeatItemID
4666 )
4667 
4668 {
4669   ButtoN      b;
4670   GrouP       c;
4671   GrouP       seq_choice_grp;
4672   FprDataPtr  fdp;
4673   GrouP       g;
4674   PrompT      ppt;
4675   SeqIdPtr    sip;
4676   Char        strid [41];
4677   Char        txt [128];
4678   WindoW      w;
4679   OMUserDataPtr  omudp;
4680 
4681   if (bsp == NULL) return NULL;
4682   fdp = (FprDataPtr) MemNew (sizeof (FprData));
4683   if (fdp == NULL) return NULL;
4684   w = FixedWindow (-50, -33, -10, -10, "Feature Propagate", NULL);
4685   if (w == NULL) return NULL;
4686 
4687   SetObjectExtra (w, (Pointer) fdp, CleanupFeaturePropagateForm);
4688   fdp->form = (ForM) w;
4689   fdp->formmessage = FeaturePropagateFormMessage;
4690 
4691 #ifdef WIN_MAC
4692   fdp->activate = UpdateSequenceFormActivated;
4693   SetActivate (w, UpdateSequenceFormActivate);
4694 #endif
4695 
4696   /* register to receive update messages */
4697   fdp->input_entityID = bsp->idx.entityID;
4698   fdp->userkey = OMGetNextUserKey ();
4699   fdp->procid = 0;
4700   fdp->proctype = OMPROC_EDIT;
4701   omudp = ObjMgrAddUserData (fdp->input_entityID, fdp->procid, fdp->proctype, fdp->userkey);
4702   if (omudp != NULL) {
4703     omudp->userdata.ptrvalue = (Pointer) fdp;
4704     omudp->messagefunc = FeaturePropagateFormMsgFunc;
4705   }
4706 
4707   fdp->bsp = bsp;
4708   fdp->salp = salp;
4709 
4710   sip = SeqIdFindWorst (bsp->id);
4711   SeqIdWrite (sip, strid, PRINTID_REPORT, sizeof (strid) - 1);
4712   if (ISA_na (bsp->mol)) {
4713     sprintf (txt, "Propagate from %s to", strid);
4714   } else {
4715     sprintf (txt, "Propagate from %s to", strid);
4716   }
4717 
4718   g = HiddenGroup (w, -1, 0, NULL);
4719   SetGroupSpacing (g, 5, 5);
4720 
4721   seq_choice_grp = HiddenGroup (g, 0, 2, NULL);
4722   ppt = StaticPrompt (seq_choice_grp, txt, 0, 0, programFont, 'c');
4723   fdp->sequence_list_dlg = SequenceSelectionDialog (seq_choice_grp,
4724                                                     SetFeaturePropagateAccept,
4725                                                     fdp,
4726                                                     TRUE,
4727                                                     ISA_na (bsp->mol),
4728                                                     ISA_aa (bsp->mol),
4729                                                     fdp->input_entityID);
4730 
4731   fdp->allOrSel = HiddenGroup (g, 2, 0, NULL);
4732   RadioButton (fdp->allOrSel, "All Features");
4733   b = RadioButton (fdp->allOrSel, "Selected Feature");
4734 #if 1
4735   SetValue (fdp->allOrSel, 1);
4736 #else
4737   if (ObjMgrGetSelected () != NULL) {
4738     SetValue (fdp->allOrSel, 2);
4739   } else {
4740     SetValue (fdp->allOrSel, 1);
4741   }
4742 #endif
4743 
4744   fdp->gapSplit = HiddenGroup (g, 2, 0, NULL);
4745   RadioButton (fdp->gapSplit, "Extend over gaps");
4746   RadioButton (fdp->gapSplit, "Split at gaps");
4747   SetValue (fdp->gapSplit, 1);
4748 
4749   fdp->stopCDS = CheckBox (g, "Stop CDS translation at internal stop codon", NULL);
4750   SetStatus (fdp->stopCDS, FALSE);
4751 
4752   fdp->transPast = CheckBox (g, "Translate CDS after partial 3' boundary", NULL);
4753 
4754   fdp->fixCDS = CheckBox (g, "Cleanup CDS partials after propagation", NULL);
4755   SetStatus (fdp->fixCDS, TRUE);
4756 
4757   fdp->fuseJoints = CheckBox (g, "Fuse adjacent propagated intervals", NULL);
4758   SetStatus (fdp->fuseJoints, FALSE);
4759 
4760   c = HiddenGroup (w, 4, 0, NULL);
4761   fdp->accept = DefaultButton (c, "Accept", AcceptFeatProp);
4762   SetObjectExtra (fdp->accept, (Pointer) fdp, NULL);
4763   PushButton (c, "Cancel", StdCancelButtonProc);
4764   fdp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
4765 
4766   AlignObjects (ALIGN_CENTER, (HANDLE) seq_choice_grp, (HANDLE) fdp->allOrSel,
4767                 (HANDLE) fdp->gapSplit, (HANDLE) fdp->stopCDS,
4768                 (HANDLE) fdp->transPast, (HANDLE) fdp->fixCDS,
4769 				(HANDLE) fdp->fuseJoints,
4770                 (HANDLE) c, NULL);
4771   RealizeWindow (w);
4772   SendMessageToDialog (fdp->sequence_list_dlg, NUM_VIB_MSG + 1);
4773 
4774 
4775   return (ForM) w;
4776 }
4777 
4778 typedef struct batchapplyfeaturedetailsdlg
4779 {
4780   DIALOG_MESSAGE_BLOCK
4781 
4782   TexT           defline;
4783   TexT           geneName;
4784   TexT           geneDesc;
4785   TexT           protName;
4786   TexT           protDesc;
4787   TexT           rnaName;
4788   TexT           featcomment;
4789   DialoG         featdef_choice_dlg;
4790   DialoG         rnaType;
4791   PopuP          reading_frame;
4792   Int4           feattype;
4793   Nlm_ChangeNotifyProc     change_notify;
4794   Pointer                  change_userdata;
4795 } BatchApplyFeatureDetailsDlgData, PNTR BatchApplyFeatureDetailsDlgPtr;
4796 
4797 extern BatchApplyFeatureDetailsPtr
BatchApplyFeatureDetailsFree(BatchApplyFeatureDetailsPtr bafdp)4798 BatchApplyFeatureDetailsFree
4799 (BatchApplyFeatureDetailsPtr bafdp)
4800 {
4801   if (bafdp != NULL)
4802   {
4803     bafdp->defline = MemFree (bafdp->defline);
4804     bafdp->geneName = MemFree (bafdp->geneName);
4805 	  bafdp->geneDesc = MemFree (bafdp->geneDesc);
4806     bafdp->protName = MemFree (bafdp->protName);
4807     bafdp->protDesc = MemFree (bafdp->protDesc);
4808     bafdp->rnaType = RnaTypeFree (bafdp->rnaType);
4809     bafdp->rnaName = MemFree (bafdp->rnaName);
4810     bafdp->featcomment = MemFree (bafdp->featcomment);
4811     bafdp->featdef_name = MemFree (bafdp->featdef_name);
4812     bafdp = MemFree (bafdp);
4813   }
4814   return bafdp;
4815 }
4816 
BatchApplyFeatureDetailsNew(void)4817 extern BatchApplyFeatureDetailsPtr BatchApplyFeatureDetailsNew (void)
4818 {
4819   BatchApplyFeatureDetailsPtr    bafdp;
4820 
4821   bafdp = (BatchApplyFeatureDetailsPtr) MemNew (sizeof (BatchApplyFeatureDetailsData));
4822   if (bafdp != NULL)
4823   {
4824     bafdp->defline = NULL;
4825     bafdp->geneName = NULL;
4826 	bafdp->geneDesc = NULL;
4827     bafdp->protName = NULL;
4828     bafdp->protDesc = NULL;
4829     bafdp->rnaName = NULL;
4830     bafdp->featcomment = NULL;
4831     bafdp->featdef_name = NULL;
4832     bafdp->featdef_choice = FEATDEF_GENE;
4833     bafdp->reading_frame = 4;
4834     bafdp->rnaType = NULL;
4835   }
4836   return bafdp;
4837 }
4838 
BatchApplyFeatureDetailsToDialog(DialoG d,Pointer data)4839 static void BatchApplyFeatureDetailsToDialog (DialoG d, Pointer data)
4840 {
4841   BatchApplyFeatureDetailsDlgPtr dlg;
4842   BatchApplyFeatureDetailsPtr    bafdp;
4843   ValNode                        vn;
4844 
4845   dlg = (BatchApplyFeatureDetailsDlgPtr) GetObjectExtra (d);
4846   bafdp = (BatchApplyFeatureDetailsPtr) data;
4847 
4848   if (dlg == NULL)
4849   {
4850     return;
4851   }
4852 
4853   vn.next = NULL;
4854 
4855   if (bafdp == NULL)
4856   {
4857     SafeSetTitle (dlg->defline, "");
4858     SafeSetTitle (dlg->geneName, "");
4859 	SafeSetTitle (dlg->geneDesc, "");
4860     SafeSetTitle (dlg->protName, "");
4861     SafeSetTitle (dlg->protDesc, "");
4862     SafeSetTitle (dlg->rnaName, "");
4863     SafeSetTitle (dlg->featcomment, "");
4864     SafeSetValue (dlg->reading_frame, 4);
4865     if (dlg->featdef_choice_dlg != NULL)
4866     {
4867       vn.choice = FEATDEF_GENE;
4868       vn.data.ptrvalue = NULL;
4869       PointerToDialog (dlg->featdef_choice_dlg, &vn);
4870     }
4871     PointerToDialog (dlg->rnaType, NULL);
4872   }
4873   else
4874   {
4875     if (StringHasNoText (bafdp->defline))
4876     {
4877       SafeSetTitle (dlg->defline, "");
4878     }
4879     else
4880     {
4881       SafeSetTitle (dlg->defline, bafdp->defline);
4882     }
4883 
4884     if (StringHasNoText (bafdp->geneName))
4885     {
4886       SafeSetTitle (dlg->geneName, "");
4887     }
4888     else
4889     {
4890       SafeSetTitle (dlg->geneName, bafdp->geneName);
4891     }
4892 
4893     if (StringHasNoText (bafdp->protName))
4894     {
4895       SafeSetTitle (dlg->protName, "");
4896     }
4897     else
4898     {
4899       SafeSetTitle (dlg->protName, bafdp->protName);
4900     }
4901 
4902     if (StringHasNoText (bafdp->protDesc))
4903     {
4904       SafeSetTitle (dlg->protDesc, "");
4905     }
4906     else
4907     {
4908       SafeSetTitle (dlg->protDesc, bafdp->protDesc);
4909     }
4910 
4911     if (StringHasNoText (bafdp->rnaName))
4912     {
4913       SafeSetTitle (dlg->rnaName, "");
4914     }
4915     else
4916     {
4917       SafeSetTitle (dlg->rnaName, bafdp->rnaName);
4918     }
4919 
4920     if (StringHasNoText (bafdp->featcomment))
4921     {
4922       SafeSetTitle (dlg->featcomment, "");
4923     }
4924     else
4925     {
4926       SafeSetTitle (dlg->featcomment, bafdp->featcomment);
4927     }
4928 
4929     SafeSetValue (dlg->reading_frame, bafdp->reading_frame);
4930     if (dlg->featdef_choice_dlg != NULL)
4931     {
4932       vn.choice = bafdp->featdef_choice;
4933       vn.data.ptrvalue = NULL;
4934       PointerToDialog (dlg->featdef_choice_dlg, &vn);
4935     }
4936     PointerToDialog (dlg->rnaType, bafdp->rnaType);
4937   }
4938   if (dlg->change_notify != NULL)
4939   {
4940     (dlg->change_notify)(dlg->change_userdata);
4941   }
4942 }
4943 
BatchApplyFeatureDetailsDialogToData(DialoG d)4944 static Pointer BatchApplyFeatureDetailsDialogToData (DialoG d)
4945 {
4946   BatchApplyFeatureDetailsDlgPtr dlg;
4947   BatchApplyFeatureDetailsPtr    bafdp;
4948   ValNodePtr                     vnp;
4949 
4950   dlg = (BatchApplyFeatureDetailsDlgPtr) GetObjectExtra (d);
4951   if (dlg == NULL)
4952   {
4953     return NULL;
4954   }
4955 
4956   bafdp = BatchApplyFeatureDetailsNew ();
4957   if (bafdp == NULL)
4958   {
4959     return NULL;
4960   }
4961 
4962   if (dlg->defline == NULL || TextHasNoText (dlg->defline))
4963   {
4964     bafdp->defline = NULL;
4965   }
4966   else
4967   {
4968     bafdp->defline = SaveStringFromTextAndStripNewlines (dlg->defline);
4969   }
4970 
4971   if (dlg->geneName == NULL || TextHasNoText (dlg->geneName))
4972   {
4973     bafdp->geneName = NULL;
4974   }
4975   else
4976   {
4977     bafdp->geneName = SaveStringFromText (dlg->geneName);
4978   }
4979 
4980   if (dlg->geneDesc == NULL || TextHasNoText (dlg->geneDesc))
4981   {
4982     bafdp->geneDesc = NULL;
4983   }
4984   else
4985   {
4986     bafdp->geneDesc = SaveStringFromText (dlg->geneDesc);
4987   }
4988 
4989  if (dlg->protName == NULL || TextHasNoText (dlg->protName))
4990   {
4991     bafdp->protName = NULL;
4992   }
4993   else
4994   {
4995     bafdp->protName = SaveStringFromText (dlg->protName);
4996   }
4997 
4998   if (dlg->protDesc == NULL || TextHasNoText (dlg->protDesc))
4999   {
5000     bafdp->protDesc = NULL;
5001   }
5002   else
5003   {
5004     bafdp->protDesc = SaveStringFromText (dlg->protDesc);
5005   }
5006 
5007   if (dlg->rnaName == NULL || TextHasNoText (dlg->rnaName))
5008   {
5009     bafdp->rnaName = NULL;
5010   }
5011   else
5012   {
5013     bafdp->rnaName = SaveStringFromText (dlg->rnaName);
5014   }
5015 
5016   if (dlg->featcomment == NULL || TextHasNoText (dlg->featcomment))
5017   {
5018     bafdp->featcomment = NULL;
5019   }
5020   else
5021   {
5022     bafdp->featcomment = SaveStringFromTextAndStripNewlines (dlg->featcomment);
5023   }
5024 
5025   if (dlg->reading_frame == NULL)
5026   {
5027     bafdp->reading_frame = 4;
5028   }
5029   else
5030   {
5031     bafdp->reading_frame = GetValue (dlg->reading_frame);
5032   }
5033 
5034   if (dlg->featdef_choice_dlg == NULL)
5035   {
5036     bafdp->featdef_choice = FEATDEF_GENE;
5037   }
5038   else
5039   {
5040     vnp = DialogToPointer (dlg->featdef_choice_dlg);
5041     if (vnp != NULL)
5042     {
5043       bafdp->featdef_choice = vnp->choice;
5044       bafdp->featdef_name = StringSave (vnp->data.ptrvalue);
5045       vnp = ValNodeFreeData (vnp);
5046     }
5047     else
5048     {
5049       bafdp->featdef_choice = FEATDEF_GENE;
5050       bafdp->featdef_name = StringSave ("Gene");
5051     }
5052   }
5053 
5054   bafdp->rnaType = DialogToPointer (dlg->rnaType);
5055 
5056   return bafdp;
5057 }
5058 
BatchApplyFeatureDetailsMessage(DialoG d,Int2 mssg)5059 static void BatchApplyFeatureDetailsMessage (DialoG d, Int2 mssg)
5060 
5061 {
5062   BatchApplyFeatureDetailsDlgPtr  dlg;
5063 
5064   dlg = (BatchApplyFeatureDetailsDlgPtr) GetObjectExtra (d);
5065   if (dlg != NULL) {
5066     switch (mssg) {
5067       case VIB_MSG_INIT :
5068         /* reset list */
5069         PointerToDialog (d, NULL);
5070         break;
5071       case VIB_MSG_ENTER :
5072         if (dlg->feattype == ADD_TITLE) {
5073           Select (dlg->defline);
5074         } else if (dlg->feattype == ADD_RRNA) {
5075           Select (dlg->rnaName);
5076         } else {
5077           Select (dlg->geneName);
5078         }
5079         break;
5080       default :
5081         break;
5082     }
5083   }
5084 }
5085 
5086 /* This section of code is used for managing lists of features.
5087  * Sometimes the features will be displayed alphabetically, sometimes
5088  * they will be displayed alphabetically with a list of the most used features
5089  * also appearing at the top of the list.
5090  */
5091 
5092 /* This is used to compare feature names with the special alphabetical order */
CompareFeatureNames(CharPtr cp1,CharPtr cp2)5093 static int CompareFeatureNames (CharPtr cp1, CharPtr cp2)
5094 {
5095   /* NULL name goes at the end */
5096   if (cp1 == NULL && cp2 == NULL) return 0;
5097   if (cp1 == NULL) return 1;
5098   if (cp2 == NULL) return -1;
5099 
5100   /* starts with a space goes at the beginning */
5101   if (cp1 [0] == ' ' && cp2 [0] == ' ') return 0;
5102   if (cp1 [0] == ' ') return -1;
5103   if (cp2 [0] == ' ') return 1;
5104 
5105   /* Is "All" or [ALL FEATURES] goes at the beginning */
5106   if ((StringCmp (cp1, "All") == 0
5107     || StringCmp (cp1, "[ALL FEATURES]") == 0)
5108     && (StringCmp (cp2, "All") == 0
5109     || StringCmp (cp2, "[ALL FEATURES]") == 0))
5110   {
5111     return 0;
5112   }
5113   if (StringCmp (cp1, "All") == 0
5114     || StringCmp (cp1, "[ALL FEATURES]") == 0)
5115   {
5116     return -1;
5117   }
5118   if (StringCmp (cp2, "All") == 0
5119     || StringCmp (cp2, "[ALL FEATURES]") == 0)
5120   {
5121     return 1;
5122   }
5123 
5124   /* starts with a number -> goes at the end */
5125   if (cp1 [0] >= '0' && cp1 [0] <= '9'
5126    && cp2 [0] >= '0' && cp2 [0] <= '9')
5127   {
5128     return StringICmp (cp1, cp2);
5129   }
5130   if (cp1 [0] >= '0' && cp1 [0] <= '9')
5131   {
5132     return 1;
5133   }
5134   if (cp2 [0] >= '0' && cp2 [0] <= '9')
5135   {
5136     return -1;
5137   }
5138 
5139   /* starts with a tilde or dash - sort with other tildes, put before numbers after alphas */
5140   if (cp1 [0] == '~' && cp2 [0] == '~')
5141   {
5142     return StringICmp (cp1 + 1, cp2 + 1);
5143   }
5144   if (cp1 [0] == '~') return 1;
5145   if (cp2 [0] == '~') return -1;
5146 
5147   if (cp1 [0] == '-' && cp2 [0] == '-')
5148   {
5149     return StringICmp (cp1 + 1, cp2 + 1);
5150   }
5151   if (cp1 [0] == '-') return 1;
5152   if (cp2 [0] == '-') return -1;
5153 
5154   return StringICmp (cp1, cp2);
5155 }
5156 
CompareFeatureValNodeStrings(VoidPtr ptr1,VoidPtr ptr2)5157 extern int LIBCALLBACK CompareFeatureValNodeStrings (VoidPtr ptr1, VoidPtr ptr2)
5158 {
5159   ValNodePtr vnp1, vnp2;
5160 
5161   if (ptr1 == NULL || ptr2 == NULL) return 0;
5162 
5163   vnp1 = *((ValNodePtr PNTR) ptr1);
5164   vnp2 = *((ValNodePtr PNTR) ptr2);
5165 
5166   if (vnp1 == NULL || vnp2 == NULL) return 0;
5167 
5168   return CompareFeatureNames (vnp1->data.ptrvalue, vnp2->data.ptrvalue);
5169 }
5170 
CompareImpFeatEnumFieldAssoc(VoidPtr ptr1,VoidPtr ptr2)5171 extern int LIBCALLBACK CompareImpFeatEnumFieldAssoc (VoidPtr ptr1, VoidPtr ptr2)
5172 {
5173   ValNodePtr        vnp1, vnp2;
5174   EnumFieldAssocPtr ap1, ap2;
5175 
5176   if (ptr1 == NULL || ptr2 == NULL) return 0;
5177 
5178   vnp1 = *((ValNodePtr PNTR) ptr1);
5179   vnp2 = *((ValNodePtr PNTR) ptr2);
5180   if (vnp1 == NULL || vnp2 == NULL) return 0;
5181 
5182   ap1 = (EnumFieldAssocPtr) vnp1->data.ptrvalue;
5183   ap2 = (EnumFieldAssocPtr) vnp2->data.ptrvalue;
5184   if (ap1 == NULL || ap2 == NULL) return 0;
5185 
5186   return CompareFeatureNames (ap1->name, ap2->name);
5187 }
5188 
SortEnumFieldAssocPtrArray(EnumFieldAssocPtr alist,CompareFunc compar)5189 extern void SortEnumFieldAssocPtrArray (EnumFieldAssocPtr alist, CompareFunc compar)
5190 {
5191   ValNodePtr        head, vnp;
5192   EnumFieldAssocPtr ap;
5193   Int4              index;
5194 
5195   /* first, create ValNode list so we can sort the data */
5196   head = NULL;
5197   for (ap = alist; ap != NULL && ap->name != NULL; ap++)
5198   {
5199     vnp = ValNodeNew (head);
5200     if (vnp == NULL) return;
5201     vnp->data.ptrvalue = MemNew (sizeof (EnumFieldAssoc));
5202     if (vnp->data.ptrvalue == NULL) return;
5203     MemCpy (vnp->data.ptrvalue, ap, sizeof (EnumFieldAssoc));
5204     if (head == NULL) head = vnp;
5205   }
5206 
5207   /* Now sort the ValNode list */
5208   head = SortValNode (head, compar);
5209 
5210   /* Now repopulate the EnumFieldAssoc list */
5211   index = 0;
5212   for (vnp = head; vnp != NULL; vnp = vnp->next)
5213   {
5214     MemCpy (alist + index++, vnp->data.ptrvalue, sizeof (EnumFieldAssoc));
5215   }
5216 
5217   /* And free the ValNode list */
5218   ValNodeFreeData (head);
5219 }
5220 
AddTextToComment(ButtoN b,CharPtr text)5221 static void AddTextToComment (ButtoN b, CharPtr text)
5222 {
5223   BatchApplyFeatureDetailsDlgPtr dlg;
5224   CharPtr                        orig_comment;
5225   CharPtr                        new_comment;
5226   RnaTypeData                    rtd;
5227 
5228   dlg = (BatchApplyFeatureDetailsDlgPtr) GetObjectExtra (b);
5229   if (dlg == NULL || StringHasNoText (text))
5230   {
5231     return;
5232   }
5233 
5234   orig_comment = SaveStringFromText (dlg->featcomment);
5235   if (StringHasNoText (orig_comment))
5236   {
5237     SetTitle (dlg->featcomment, text);
5238   }
5239   else
5240   {
5241     new_comment = (CharPtr) MemNew ((StringLen (orig_comment) + StringLen (text) + 3) * sizeof (Char));
5242     if (new_comment != NULL)
5243     {
5244       StringCpy (new_comment, orig_comment);
5245       StringCat (new_comment, "; ");
5246       StringCat (new_comment, text);
5247       SetTitle (dlg->featcomment, new_comment);
5248       new_comment = MemFree (new_comment);
5249     }
5250   }
5251   orig_comment = MemFree (orig_comment);
5252 
5253   rtd.ncrna_class = NULL;
5254   rtd.rna_featdef = FEATDEF_misc_RNA;
5255   PointerToDialog (dlg->rnaType, &rtd);
5256 }
5257 
Add18SITS28SToComment(ButtoN b)5258 static void Add18SITS28SToComment (ButtoN b)
5259 {
5260   AddTextToComment (b, "contains 18S ribosomal RNA, internal transcribed spacer 1, 5.8S ribosomal RNA, internal transcribed spacer 2, and 28S ribosomal RNA");
5261 }
5262 
Add16SIGS23SToComment(ButtoN b)5263 static void Add16SIGS23SToComment (ButtoN b)
5264 {
5265   AddTextToComment (b, "contains 16S ribosomal RNA, 16S-23S ribosomal RNA intergenic spacer, and 23S ribosomal RNA");
5266 }
5267 
5268 
OkToAcceptBatchApplyFeatureDetails(DialoG d)5269 extern Boolean OkToAcceptBatchApplyFeatureDetails (DialoG d)
5270 {
5271   BatchApplyFeatureDetailsDlgPtr dlg;
5272   ValNodePtr                     vnp;
5273   Boolean                        rval = TRUE;
5274 
5275   dlg = (BatchApplyFeatureDetailsDlgPtr) GetObjectExtra (d);
5276   if (dlg == NULL) return FALSE;
5277 
5278   if (dlg->feattype == ADD_IMP)
5279   {
5280     vnp = DialogToPointer (dlg->featdef_choice_dlg);
5281     if (vnp == NULL)
5282     {
5283       rval = FALSE;
5284     }
5285     vnp = ValNodeFree (vnp);
5286   }
5287   return rval;
5288 }
5289 
5290 extern DialoG
BatchApplyFeatureDetailsDialog(GrouP parent,Int4 feattype,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)5291 BatchApplyFeatureDetailsDialog (GrouP parent, Int4 feattype, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
5292 {
5293   BatchApplyFeatureDetailsDlgPtr dlg;
5294   GrouP                          p, r = NULL, text_group = NULL, comment_btns_grp = NULL;
5295   ButtoN                         comment_btn;
5296   Nlm_EnumFieldAssocPtr          ap;
5297   Int4                           j;
5298   Boolean                        is_indexer = FALSE;
5299   RnaTypeData                    rtd;
5300 
5301   dlg = (BatchApplyFeatureDetailsDlgPtr) MemNew (sizeof (BatchApplyFeatureDetailsDlgData));
5302   if (dlg == NULL)
5303   {
5304     return NULL;
5305   }
5306 
5307   if (GetAppProperty ("InternalNcbiSequin") != NULL)
5308   {
5309     is_indexer = TRUE;
5310   }
5311 
5312   p = HiddenGroup (parent, -1, 0, NULL);
5313   SetGroupSpacing (p, 10, 10);
5314   SetObjectExtra (p, dlg, StdCleanupExtraProc);
5315 
5316   dlg->dialog = (DialoG) p;
5317   dlg->todialog = BatchApplyFeatureDetailsToDialog;
5318   dlg->fromdialog = BatchApplyFeatureDetailsDialogToData;
5319   dlg->dialogmessage = NULL;
5320   dlg->testdialog = NULL;
5321 
5322   dlg->feattype = feattype;
5323 
5324   dlg->change_notify = change_notify;
5325   dlg->change_userdata = change_userdata;
5326 
5327   /* codon start controls */
5328   if (dlg->feattype == ADD_CDS)
5329   {
5330     r = HiddenGroup (p, 2, 0, NULL);
5331     StaticPrompt (r, "Codon Start", 0, dialogTextHeight, programFont, 'l');
5332     dlg->reading_frame = PopupList (r, TRUE, NULL);
5333     PopupItem (dlg->reading_frame, "1");
5334     PopupItem (dlg->reading_frame, "2");
5335     PopupItem (dlg->reading_frame, "3");
5336     PopupItem (dlg->reading_frame, "Best");
5337     SetValue (dlg->reading_frame, 4);
5338   }
5339   else if (dlg->feattype == ADD_RRNA)
5340   {
5341     dlg->rnaType = RnaTypeDialog (p, FALSE, change_notify, change_userdata);
5342     rtd.ncrna_class = NULL;
5343     rtd.rna_featdef = FEATDEF_rRNA;
5344     PointerToDialog (dlg->rnaType, &rtd);
5345   }
5346 
5347   text_group = HiddenGroup (p, 0, 2, NULL);
5348   if (dlg->feattype == ADD_TITLE) {
5349     StaticPrompt (text_group, "Title", 0, 0, programFont, 'c');
5350     dlg->defline = ScrollText (text_group, 20, 4, programFont, TRUE, NULL);
5351   } else {
5352     text_group = HiddenGroup (p, 2, 0, NULL);
5353     if (dlg->feattype == ADD_CDS) {
5354       StaticPrompt (text_group, "Gene Symbol", 0, dialogTextHeight, programFont, 'l');
5355       dlg->geneName = DialogText (text_group, "", 20, NULL);
5356 	  if (is_indexer)
5357 	  {
5358 		StaticPrompt (text_group, "Gene Description", 0, dialogTextHeight, programFont, 'l');
5359         dlg->geneDesc = DialogText (text_group, "", 20, NULL);
5360 	  }
5361 
5362       StaticPrompt (text_group, "Protein Name", 0, dialogTextHeight, programFont, 'l');
5363       dlg->protName = DialogText (text_group, "", 20, NULL);
5364       StaticPrompt (text_group, "Protein Description", 0, dialogTextHeight, programFont, 'l');
5365       dlg->protDesc = DialogText (text_group, "", 20, NULL);
5366     } else if (dlg->feattype == ADD_RRNA) {
5367       StaticPrompt (text_group, "RNA Name", 0, dialogTextHeight, programFont, 'l');
5368       dlg->rnaName = DialogText (text_group, "", 20, NULL);
5369       StaticPrompt (text_group, "Gene Symbol", 0, dialogTextHeight, programFont, 'l');
5370       dlg->geneName = DialogText (text_group, "", 20, NULL);
5371 	  if (is_indexer)
5372 	  {
5373 		StaticPrompt (text_group, "Gene Description", 0, dialogTextHeight, programFont, 'l');
5374         dlg->geneDesc = DialogText (text_group, "", 20, NULL);
5375 	  }
5376     } else if (dlg->feattype == ADD_IMP) {
5377       StaticPrompt (text_group, "Type", 0, 6 * Nlm_stdLineHeight, programFont, 'l');
5378       ap = import_featdef_alist (FALSE, FALSE, FALSE);
5379       SortEnumFieldAssocPtrArray (ap, CompareImpFeatEnumFieldAssoc);
5380       /* replace first item with Gene */
5381       ap [0].name = MemFree (ap [0].name);
5382       ap [0].name = StringSave ("Gene");
5383       ap [0].value = FEATDEF_GENE;
5384 
5385       dlg->featdef_choice_dlg = EnumAssocSelectionDialog (text_group, ap,
5386                                                   "feat_detail",
5387                                                    FALSE, dlg->change_notify, dlg->change_userdata);
5388       /* clean up enumassoc list - not needed any more */
5389       for (j = 0; ap [j].name != NULL; j++) {
5390         MemFree (ap [j].name);
5391       }
5392       MemFree (ap);
5393 
5394       StaticPrompt (text_group, "Gene Symbol", 0, dialogTextHeight, programFont, 'l');
5395       dlg->geneName = DialogText (text_group, "", 20, NULL);
5396 	  if (is_indexer)
5397 	  {
5398 		StaticPrompt (text_group, "Gene Description", 0, dialogTextHeight, programFont, 'l');
5399         dlg->geneDesc = DialogText (text_group, "", 20, NULL);
5400 	  }
5401     }
5402     StaticPrompt (text_group, "Comment", 0, 4 * Nlm_stdLineHeight, programFont, 'l');
5403     dlg->featcomment = ScrollText (text_group, 20, 4, programFont, TRUE, NULL);
5404 
5405   }
5406 
5407   if (dlg->feattype == ADD_RRNA && is_indexer)
5408   {
5409     comment_btns_grp = HiddenGroup (p, 2, 0, NULL);
5410     comment_btn = PushButton (comment_btns_grp, "Add '18S-ITS-5.8S-ITS-28S' to comment", Add18SITS28SToComment);
5411     SetObjectExtra (comment_btn, dlg, NULL);
5412     comment_btn = PushButton (comment_btns_grp, "Add '16S-IGS-23S' to comment", Add16SIGS23SToComment);
5413     SetObjectExtra (comment_btn, dlg, NULL);
5414   }
5415 
5416   AlignObjects (ALIGN_CENTER, (HANDLE) text_group, (HANDLE) r, (HANDLE) comment_btns_grp, NULL);
5417 
5418   return (DialoG) p;
5419 }
5420 
5421 typedef struct alreadyhas {
5422   Boolean        rsult;
5423   Uint1          featchoice;
5424   Uint1          descchoice;
5425   Uint1          rnatype;
5426 } AlreadyHas, PNTR AlreadyHasPtr;
5427 
SeeIfAlreadyHasGatherFunc(GatherContextPtr gcp)5428 static Boolean SeeIfAlreadyHasGatherFunc (GatherContextPtr gcp)
5429 
5430 {
5431   AlreadyHasPtr  ahp;
5432   RnaRefPtr      rrp;
5433   ValNodePtr     sdp;
5434   SeqFeatPtr     sfp;
5435 
5436   if (gcp == NULL) return TRUE;
5437 
5438   ahp = (AlreadyHasPtr) gcp->userdata;
5439   if (ahp == NULL ) return TRUE;
5440 
5441   if (gcp->thistype == OBJ_SEQFEAT && ahp->featchoice != 0) {
5442     sfp = (SeqFeatPtr) gcp->thisitem;
5443     if (sfp != NULL && sfp->data.choice == ahp->featchoice && sfp->data.value.ptrvalue != NULL) {
5444       if (sfp->data.choice == SEQFEAT_RNA) {
5445         rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
5446         if (rrp->type != ahp->rnatype) return TRUE;
5447       }
5448       ahp->rsult = TRUE;
5449       return FALSE;
5450     }
5451   } else if (gcp->thistype == OBJ_SEQDESC && ahp->descchoice != 0) {
5452     sdp = (ValNodePtr) gcp->thisitem;
5453     if (sdp != NULL && sdp->choice == ahp->descchoice && sdp->data.ptrvalue != NULL) {
5454       ahp->rsult = TRUE;
5455       return FALSE;
5456     }
5457   }
5458   return TRUE;
5459 }
5460 
AlreadyHasFeatOrDesc(SeqEntryPtr sep,Uint1 featchoice,Uint1 descchoice,Uint1 rnatype)5461 static Boolean AlreadyHasFeatOrDesc (SeqEntryPtr sep, Uint1 featchoice, Uint1 descchoice, Uint1 rnatype)
5462 
5463 {
5464   AlreadyHas   ah;
5465   BioseqPtr    bsp;
5466   GatherScope  gs;
5467   SeqEntryPtr  nsep;
5468   SeqIdPtr     sip;
5469   SeqLocPtr    slp;
5470 
5471   ah.rsult = FALSE;
5472   ah.featchoice = featchoice;
5473   ah.descchoice = descchoice;
5474   ah.rnatype = rnatype;
5475   if (sep == NULL) return FALSE;
5476   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
5477   gs.seglevels = 1;
5478   gs.get_feats_location = TRUE;
5479   MemSet ((Pointer) (gs.ignore), (int)(TRUE), (size_t) (OBJ_MAX * sizeof(Boolean)));
5480   gs.ignore[OBJ_BIOSEQ] = FALSE;
5481   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
5482   gs.ignore[OBJ_SEQFEAT] = FALSE;
5483   gs.ignore[OBJ_SEQDESC] = FALSE;
5484   gs.ignore[OBJ_SEQANNOT] = FALSE;
5485   gs.scope = sep;
5486   if (descchoice != 0) {
5487     nsep = FindNucSeqEntry (sep);
5488     if (nsep != NULL && IS_Bioseq (nsep)) {
5489       bsp = (BioseqPtr) nsep->data.ptrvalue;
5490       if (bsp != NULL) {
5491         slp = ValNodeNew (NULL);
5492         slp->choice = SEQLOC_WHOLE;
5493         sip = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
5494         slp->data.ptrvalue = sip;
5495         gs.target = slp;
5496       }
5497     }
5498   }
5499   GatherSeqEntry (sep, (Pointer) (&ah), SeeIfAlreadyHasGatherFunc, &gs);
5500   gs.target = SeqLocFree (gs.target);
5501   return ah.rsult;
5502 }
5503 
AddGeneXrefToFeat(SeqFeatPtr sfp,CharPtr str)5504 static void AddGeneXrefToFeat (SeqFeatPtr sfp, CharPtr str)
5505 {
5506   SeqFeatXrefPtr    xref;
5507   GeneRefPtr        grp;
5508 
5509   if (sfp == NULL || StringHasNoText (str)) return;
5510 
5511   /* add gene xref to feature */
5512   xref = SeqFeatXrefNew ();
5513   if (xref != NULL)
5514   {
5515     grp = CreateNewGeneRef (str, NULL, NULL, FALSE);
5516     if (grp != NULL)
5517     {
5518       xref->data.choice = SEQFEAT_GENE;
5519       xref->data.value.ptrvalue = grp;
5520       xref->next = sfp->xref;
5521       sfp->xref = xref;
5522     }
5523   }
5524 }
5525 
ApplyGene(CharPtr gene_name,BatchApplyFeatureDetailsPtr feature_details_data,SeqEntryPtr gene_sep,SeqFeatPtr sfp,SeqLocPtr slp)5526 static SeqFeatPtr ApplyGene
5527 (CharPtr gene_name,
5528  BatchApplyFeatureDetailsPtr feature_details_data,
5529  SeqEntryPtr gene_sep,
5530  SeqFeatPtr sfp,
5531  SeqLocPtr  slp)
5532 {
5533   GeneRefPtr        grp;
5534   SeqFeatPtr        gene_sfp;
5535   SeqFeatXrefPtr    xref;
5536   SeqMgrFeatContext fcontext;
5537   BioseqPtr         bsp = NULL;
5538   SeqFeatPtr        other_feat;
5539   SeqFeatPtr        overlap_gene;
5540   Boolean           added_xrefs = FALSE;
5541   SeqFeatPtr        misc_feat = NULL;
5542   SeqLocPtr         overlap_loc;
5543   Boolean           partial5, partial3;
5544 
5545   if (feature_details_data == NULL || gene_sep == NULL || slp == NULL
5546 	  || (StringHasNoText (gene_name) && StringHasNoText (feature_details_data->geneDesc))) return NULL;
5547 
5548   CheckSeqLocForPartial (slp, &partial5, &partial3);
5549 
5550   /* we need a location to use when we're checking for feature-stealing genes */
5551   if (sfp != NULL)
5552   {
5553     overlap_loc = sfp->location;
5554   }
5555   else
5556   {
5557     misc_feat = CreateNewFeature (gene_sep, NULL, SEQFEAT_COMMENT, NULL);
5558     if (NULL == misc_feat)
5559     return NULL;
5560     misc_feat->location = SeqLocCopy (slp);
5561 
5562     misc_feat->partial = (partial5 || partial3);
5563     overlap_loc = misc_feat->location;
5564   }
5565 
5566   /* first, add gene xrefs to all features on bioseq that are contained in the location */
5567   /* maintain list of features that had xrefs before, should not remove them later */
5568   if (IS_Bioseq (gene_sep))
5569   {
5570     bsp = (BioseqPtr) gene_sep->data.ptrvalue;
5571   }
5572   else if (sfp != NULL)
5573   {
5574     bsp = BioseqFindFromSeqLoc (sfp->location);
5575   }
5576   if (bsp != NULL)
5577   {
5578     other_feat = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
5579     while (other_feat != NULL)
5580     {
5581       if (other_feat != sfp && other_feat->data.choice != SEQFEAT_GENE)
5582       {
5583         for (xref = other_feat->xref;
5584              xref != NULL && xref->data.choice != SEQFEAT_GENE;
5585              xref = xref->next)
5586         {}
5587         if (xref == NULL
5588             && SeqLocCompare (other_feat->location, overlap_loc) == SLC_A_EQ_B)
5589         {
5590           overlap_gene = SeqMgrGetOverlappingGene (other_feat->location, NULL);
5591           if (overlap_gene != NULL)
5592           {
5593             AddGeneXrefToFeat (other_feat, fcontext.label);
5594             added_xrefs = TRUE;
5595           }
5596         }
5597       }
5598       other_feat = SeqMgrGetNextFeature (bsp, other_feat, 0, 0, &fcontext);
5599     }
5600   }
5601 
5602   if (misc_feat != NULL)
5603   {
5604     misc_feat->idx.deleteme = TRUE;
5605     DeleteMarkedObjects (0, OBJ_SEQENTRY, gene_sep);
5606   }
5607 
5608   grp = CreateNewGeneRef (gene_name, NULL, feature_details_data->geneDesc, FALSE);
5609   if (NULL == grp)
5610     return NULL;
5611 
5612   gene_sfp = CreateNewFeature (gene_sep, NULL, SEQFEAT_GENE, NULL);
5613   if (NULL == gene_sfp)
5614     return NULL;
5615 
5616   gene_sfp->data.value.ptrvalue = (Pointer) grp;
5617   gene_sfp->location = slp;
5618   gene_sfp->partial = partial5 | partial3;
5619 
5620   if (added_xrefs && sfp != NULL)
5621   {
5622     /* add gene xref to feature */
5623     AddGeneXrefToFeat (sfp, gene_name);
5624   }
5625 
5626   return gene_sfp;
5627 }
5628 
5629 static void
SetFrameForCodingRegion(SeqFeatPtr sfp,BioseqPtr bsp,BatchApplyFeatureDetailsPtr feature_details_data,Int4Ptr errcount,ValNodePtr PNTR ambigList)5630 SetFrameForCodingRegion
5631 (SeqFeatPtr                  sfp,
5632  BioseqPtr                   bsp,
5633  BatchApplyFeatureDetailsPtr feature_details_data,
5634  Int4Ptr                     errcount,
5635  ValNodePtr PNTR             ambigList)
5636 {
5637   CdRegionPtr        crp;
5638   ByteStorePtr       bs;
5639   Uint1              frame;
5640   Int2               i;
5641   Int4               len;
5642   Int4               lens [4];
5643   Int4               max;
5644   Char               str [128];
5645   SeqIdPtr           sip;
5646 
5647   if (sfp == NULL
5648       || sfp->data.choice != SEQFEAT_CDREGION
5649       || sfp->data.value.ptrvalue == NULL
5650       || bsp == NULL
5651       || feature_details_data == NULL
5652       || errcount == NULL || ambigList == NULL)
5653   {
5654     return;
5655   }
5656 
5657   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
5658 
5659   if (feature_details_data->reading_frame < 1
5660       || feature_details_data->reading_frame > 3)
5661   {
5662     max = 0;
5663     frame = 0;
5664     for (i = 1; i <= 3; i++) {
5665       crp->frame = (Uint1) i;
5666       bs = ProteinFromCdRegionEx (sfp, FALSE, FALSE);
5667       len = BSLen (bs);
5668       BSFree (bs);
5669       lens [i] = len;
5670       if (len > max) {
5671         max = len;
5672         frame = (Uint1) i;
5673       }
5674     }
5675     str [0] = '\0';
5676     sip = SeqIdFindBest (bsp->id, 0);
5677     SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str) - 1);
5678     for (i = 1; i <= 3; i++) {
5679       if (lens [i] == max && i != frame) {
5680         (*errcount)++;
5681         ValNodeCopyStr (ambigList, 0, str);
5682       }
5683     }
5684     crp->frame = frame;
5685   }
5686   else
5687   {
5688     crp->frame = feature_details_data->reading_frame;
5689   }
5690 }
5691 
5692 static void
AddProductForCDS(SeqFeatPtr sfp,BatchApplyFeatureDetailsPtr feature_details_data,SeqEntryPtr sep,SeqEntryPtr nsep,Uint2 entityID)5693 AddProductForCDS
5694 (SeqFeatPtr                  sfp,
5695  BatchApplyFeatureDetailsPtr feature_details_data,
5696  SeqEntryPtr                 sep,
5697  SeqEntryPtr                 nsep,
5698  Uint2                       entityID)
5699 {
5700   ByteStorePtr       bs;
5701   Char               ch;
5702   ValNodePtr         descr;
5703   Int2               i;
5704   MolInfoPtr         mip;
5705   SeqEntryPtr        old;
5706   CharPtr            prot;
5707   ProtRefPtr         prp;
5708   SeqEntryPtr        psep;
5709   CharPtr            ptr;
5710   ValNodePtr         vnp;
5711   SeqEntryPtr        parent_sep;
5712   SeqFeatPtr         prot_sfp;
5713   BioseqPtr          bsp;
5714   Boolean            partial5, partial3;
5715 
5716   if (sfp == NULL
5717       || sfp->data.choice != SEQFEAT_CDREGION
5718       || feature_details_data == NULL
5719       || sep == NULL || nsep == NULL)
5720   {
5721     return;
5722   }
5723 
5724   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5725 
5726   /* determine the parent of this sequence (for use when segmented) */
5727   parent_sep = NULL;
5728   if (IS_Bioseq (sep))
5729   {
5730     parent_sep = GetBestTopParentForData (entityID, sep->data.ptrvalue);
5731   }
5732   if (parent_sep == NULL)
5733   {
5734     parent_sep = sep;
5735   }
5736 
5737   /* Create corresponding protein sequence data for the CDS */
5738 
5739   bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
5740   if (NULL == bs)
5741     return;
5742 
5743   prot = BSMerge (bs, NULL);
5744   bs = BSFree (bs);
5745   if (NULL == prot)
5746     return;
5747 
5748   ptr = prot;
5749   ch = *ptr;
5750   while (ch != '\0') {
5751     *ptr = TO_UPPER (ch);
5752     ptr++;
5753     ch = *ptr;
5754   }
5755   i = (Int2) StringLen (prot);
5756   if (i > 0 && prot [i - 1] == '*') {
5757     prot [i - 1] = '\0';
5758   }
5759   bs = BSNew (1000);
5760   if (bs != NULL) {
5761     ptr = prot;
5762     BSWrite (bs, (VoidPtr) ptr, (Int4) StringLen (ptr));
5763   }
5764 
5765   /* Create the product protein Bioseq */
5766 
5767   bsp = BioseqNew ();
5768   if (NULL == bsp)
5769     return;
5770 
5771   bsp->repr = Seq_repr_raw;
5772   bsp->mol = Seq_mol_aa;
5773   bsp->seq_data_type = Seq_code_ncbieaa;
5774   bsp->seq_data = (SeqDataPtr) bs;
5775   bsp->length = BSLen (bs);
5776   bs = NULL;
5777   old = SeqEntrySetScope (NULL);
5778   bsp->id = MakeNewProteinSeqId (sfp->location, NULL);
5779   SeqMgrAddToBioseqIndex (bsp);
5780   SeqEntrySetScope (old);
5781 
5782   /* Create a new SeqEntry for the Prot Bioseq */
5783 
5784   psep = SeqEntryNew ();
5785   if (NULL == psep)
5786     return;
5787 
5788   psep->choice = 1;
5789   psep->data.ptrvalue = (Pointer) bsp;
5790   SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, psep);
5791 
5792   /* Add a descriptor to the protein Bioseq */
5793 
5794   mip = MolInfoNew ();
5795   if (NULL == mip)
5796     return;
5797 
5798   mip->biomol = 8;
5799   mip->tech = 8;
5800   if (partial5 && partial3) {
5801     mip->completeness = 5;
5802   } else if (partial5) {
5803     mip->completeness = 3;
5804   } else if (partial3) {
5805     mip->completeness = 4;
5806   }
5807   vnp = CreateNewDescriptor (psep, Seq_descr_molinfo);
5808   if (NULL == vnp)
5809     return;
5810 
5811   vnp->data.ptrvalue = (Pointer) mip;
5812 
5813   /**/
5814 
5815   descr = ExtractBioSourceAndPubs (parent_sep);
5816 
5817   AddSeqEntryToSeqEntry (parent_sep, psep, TRUE);
5818   nsep = FindNucSeqEntry (parent_sep);
5819   ReplaceBioSourceAndPubs (parent_sep, descr);
5820   SetSeqFeatProduct (sfp, bsp);
5821 
5822   /* create a full-length protein feature for the new protein sequence */
5823   if (! StringHasNoText (feature_details_data->protName)
5824       && ! StringHasNoText (feature_details_data->protDesc))
5825   {
5826     prp = CreateNewProtRef (feature_details_data->protName,
5827                             feature_details_data->protDesc,
5828                             NULL, NULL);
5829   }
5830   else if (!StringHasNoText (feature_details_data->protName))
5831   {
5832     prp = CreateNewProtRef (feature_details_data->protName, NULL, NULL, NULL);
5833   }
5834   else if (!StringHasNoText (feature_details_data->protDesc))
5835   {
5836     prp = CreateNewProtRef (NULL, feature_details_data->protDesc, NULL, NULL);
5837   }
5838   else
5839   {
5840     prp = ProtRefNew ();
5841   }
5842 
5843   if (prp != NULL) {
5844     prot_sfp = CreateNewFeature (psep, NULL, SEQFEAT_PROT, NULL);
5845     if (prot_sfp != NULL) {
5846       prot_sfp->data.value.ptrvalue = (Pointer) prp;
5847       SetSeqLocPartial (prot_sfp->location, partial5, partial3);
5848       prot_sfp->partial = (partial5 || partial3);
5849     }
5850   }
5851 }
5852 
5853 
5854 static SeqFeatPtr
ApplyOneCodingRegion(BatchApplyFeatureDetailsPtr feature_details_data,BioseqPtr bsp,SeqEntryPtr sep,SeqEntryPtr nsep,Uint2 entityID,Boolean suppressDups)5855 ApplyOneCodingRegion
5856 (BatchApplyFeatureDetailsPtr feature_details_data,
5857  BioseqPtr                   bsp,
5858  SeqEntryPtr                 sep,
5859  SeqEntryPtr                 nsep,
5860  Uint2                       entityID,
5861  Boolean                     suppressDups)
5862 {
5863   CdRegionPtr        crp;
5864   Int2               genCode;
5865   SeqFeatPtr         sfp;
5866   SeqEntryPtr        parent_sep;
5867 
5868   if (feature_details_data == NULL || sep == NULL || nsep == NULL)
5869   {
5870     return NULL;
5871   }
5872 
5873   /* If necessary then check for duplication before adding */
5874   if (suppressDups &&
5875       entityID > 0 &&
5876       AlreadyHasFeatOrDesc (sep, SEQFEAT_CDREGION, 0, 0))
5877     return NULL;
5878 
5879   /* determine the parent of this sequence (for use when segmented) */
5880   parent_sep = NULL;
5881   if (IS_Bioseq (sep))
5882   {
5883     parent_sep = GetBestTopParentForData (entityID, sep->data.ptrvalue);
5884   }
5885   if (parent_sep == NULL)
5886   {
5887     parent_sep = sep;
5888   }
5889 
5890   /*Create a new CDS feature */
5891 
5892   genCode = SeqEntryToGeneticCode (parent_sep, NULL, NULL, 0);
5893   crp = CreateNewCdRgn (1, FALSE, genCode);
5894   if (NULL == crp)
5895     return NULL;
5896 
5897   sfp = CreateNewFeature (nsep, NULL, SEQFEAT_CDREGION, NULL);
5898 
5899   if (NULL == sfp)
5900     return NULL;
5901 
5902   sfp->data.value.ptrvalue = (Pointer) crp;
5903 
5904   return sfp;
5905 }
5906 
5907 
5908 typedef struct hasrna {
5909   Boolean hasrna;
5910   RnaTypePtr rtp;
5911 } HasRnaData, PNTR HasRnaPtr;
5912 
AlreadyHasRNACallback(SeqFeatPtr sfp,Pointer userdata)5913 static void AlreadyHasRNACallback (SeqFeatPtr sfp, Pointer userdata)
5914 {
5915   HasRnaPtr hp;
5916 
5917   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || userdata == NULL)
5918   {
5919     return;
5920   }
5921 
5922   hp = (HasRnaPtr) userdata;
5923 
5924   if (!hp->hasrna && MatchesRnaType (sfp, hp->rtp))
5925   {
5926     hp->hasrna = TRUE;
5927   }
5928 }
5929 
5930 
AlreadyHasRNA(SeqEntryPtr sep,RnaTypePtr rtp)5931 extern Boolean AlreadyHasRNA (SeqEntryPtr sep, RnaTypePtr rtp)
5932 {
5933   HasRnaData hrd;
5934 
5935   hrd.rtp = NULL;
5936   hrd.hasrna = FALSE;
5937   VisitFeaturesInSep (sep, &hrd, AlreadyHasRNACallback);
5938   return hrd.hasrna;
5939 }
5940 
5941 
ApplyOneRNA(BatchApplyFeatureDetailsPtr feature_details_data,SeqEntryPtr sep,SeqEntryPtr nsep,Uint2 entityID,Boolean suppressDups)5942 static SeqFeatPtr ApplyOneRNA
5943 (BatchApplyFeatureDetailsPtr feature_details_data,
5944  SeqEntryPtr                 sep,
5945  SeqEntryPtr                 nsep,
5946  Uint2                       entityID,
5947  Boolean                     suppressDups)
5948 {
5949   RnaRefPtr  rrp;
5950   SeqFeatPtr sfp;
5951 
5952   if (feature_details_data == NULL || sep == NULL || nsep == NULL)
5953   {
5954     return NULL;
5955   }
5956 
5957   if (suppressDups && entityID > 0 && AlreadyHasRNA (sep, feature_details_data->rnaType))
5958   {
5959     return NULL;
5960   }
5961 
5962   rrp = RnaRefNew ();
5963   sfp = CreateNewFeature (nsep, NULL, SEQFEAT_RNA, NULL);
5964   if (sfp != NULL) {
5965     sfp->data.value.ptrvalue = (Pointer) rrp;
5966   }
5967   ApplyRnaTypeToSeqFeat (sfp, feature_details_data->rnaType);
5968   if (! StringHasNoText (feature_details_data->rnaName)) {
5969     ApplyProductToRNA (sfp, feature_details_data->rnaName);
5970   }
5971 
5972   return sfp;
5973 }
5974 
GBQualListCopy(GBQualPtr gbqual_list)5975 static GBQualPtr GBQualListCopy (GBQualPtr gbqual_list)
5976 {
5977   GBQualPtr gbqual_orig, gbqual_newlist = NULL, gbqual_new = NULL;
5978 
5979   gbqual_orig = gbqual_list;
5980   while (gbqual_orig != NULL)
5981   {
5982     if (gbqual_newlist == NULL)
5983     {
5984       gbqual_newlist = GBQualNew ();
5985       gbqual_new = gbqual_newlist;
5986     }
5987     else
5988     {
5989       gbqual_new->next = GBQualNew ();
5990       gbqual_new = gbqual_new->next;
5991     }
5992 
5993     if (gbqual_new == NULL)
5994     {
5995       gbqual_orig = NULL;
5996     }
5997     else
5998     {
5999       gbqual_new->qual = StringSave (gbqual_orig->qual);
6000       gbqual_new->val = StringSave (gbqual_orig->val);
6001       gbqual_orig = gbqual_orig->next;
6002     }
6003   }
6004 
6005   return gbqual_newlist;
6006 }
6007 
ApplyOtherFeature(BatchApplyFeatureDetailsPtr feature_details_data,SeqEntryPtr nsep,GBQualPtr gbqual_list)6008 static SeqFeatPtr ApplyOtherFeature
6009 (BatchApplyFeatureDetailsPtr feature_details_data,
6010  SeqEntryPtr                 nsep,
6011  GBQualPtr                   gbqual_list)
6012 {
6013   ImpFeatPtr ifp;
6014   SeqFeatPtr sfp = NULL;
6015 
6016   if (feature_details_data == NULL
6017       || nsep == NULL
6018       || feature_details_data->featdef_choice == FEATDEF_GENE)
6019   {
6020     return NULL;
6021   }
6022 
6023   ifp = ImpFeatNew ();
6024   if (ifp == NULL)
6025   {
6026     return NULL;
6027   }
6028 
6029   ifp->key = StringSave (feature_details_data->featdef_name);
6030   sfp = CreateNewFeature (nsep, NULL, SEQFEAT_IMP, NULL);
6031   if (sfp != NULL) {
6032     sfp->data.value.ptrvalue = (Pointer) ifp;
6033     sfp->qual = GBQualListCopy (gbqual_list);
6034   }
6035   return sfp;
6036 }
6037 
GetImpFeatureGBQuals(BatchApplyFeatureDetailsPtr feature_details_data)6038 static GBQualPtr GetImpFeatureGBQuals (BatchApplyFeatureDetailsPtr feature_details_data)
6039 {
6040   WindoW                w;
6041   DialoG                dlg;
6042   GrouP                 h, c;
6043   ButtoN                b;
6044   ModalAcceptCancelData acd;
6045   GBQualPtr             gbqual_list = NULL;
6046 
6047   if (feature_details_data == NULL
6048       || feature_details_data->featdef_choice == FEATDEF_GENE)
6049   {
6050     return NULL;
6051   }
6052 
6053   w = MovableModalWindow(-20, -13, -10, -10, "Qualifiers", NULL);
6054   h = HiddenGroup (w, -1, 0, NULL);
6055   SetGroupSpacing (h, 10, 10);
6056   dlg = CreateImportFields (h, feature_details_data->featdef_name, NULL, FALSE);
6057   c = HiddenGroup (h, 2, 0, NULL);
6058   b = PushButton(c, "OK", ModalAcceptButton);
6059   SetObjectExtra (b, &acd, NULL);
6060   b = PushButton(c, "Cancel", ModalCancelButton);
6061   SetObjectExtra (b, &acd, NULL);
6062   AlignObjects (ALIGN_CENTER, (HANDLE) dlg, (HANDLE) c, NULL);
6063   RealizeWindow (w);
6064   Show (w);
6065   Select (w);
6066   acd.accepted = FALSE;
6067   acd.cancelled = FALSE;
6068   while (!acd.accepted && ! acd.cancelled)
6069   {
6070     ProcessExternalEvent ();
6071     Update ();
6072   }
6073   ProcessAnEvent ();
6074 
6075   if (acd.accepted)
6076   {
6077     gbqual_list = DialogToPointer (dlg);
6078   }
6079 
6080   Remove (w);
6081 
6082   return gbqual_list;
6083 }
6084 
6085 typedef struct applyalignmentfeature
6086 {
6087   FORM_MESSAGE_BLOCK
6088   DialoG      location_dlg;
6089   DialoG      feature_details;
6090   ButtoN      accept;
6091   ButtoN      leave_dlg_up;
6092   SeqEntryPtr sep;
6093   SeqAlignPtr salp;
6094   Int4        feattype;
6095   Uint2       entityID;
6096 } ApplyAlignmentFeatureDlgData, PNTR ApplyAlignmentFeatureDlgPtr;
6097 
6098 static Boolean
OkToContinueWithFeatureApply(SeqLocPtr seqloc_list,SeqAlignPtr salp)6099 OkToContinueWithFeatureApply
6100 (SeqLocPtr   seqloc_list,
6101  SeqAlignPtr salp)
6102 {
6103   Int4       num_missing = 0, seq_num, start_num;
6104   SeqLocPtr  slp;
6105   SeqIdPtr   sip;
6106   Int4Ptr    found_list;
6107   Boolean    found_this;
6108   Int4       msg_len = 0;
6109   CharPtr    msg_txt = NULL;
6110   CharPtr    msg_start = "The following sequence(s) are all gaps at this position: ";
6111   CharPtr    msg_end = ". Do you want to continue?";
6112   ValNodePtr id_list = NULL, id_vnp;
6113   Char       id_txt [255];
6114   Boolean    rval = TRUE;
6115   BioseqPtr  bsp;
6116 
6117   if (salp == NULL || seqloc_list == NULL)
6118   {
6119     return FALSE;
6120   }
6121 
6122   found_list = (Int4Ptr) MemNew (salp->dim * sizeof (Int4));
6123   if (found_list == NULL)
6124   {
6125     return FALSE;
6126   }
6127 
6128   for (seq_num = 1; seq_num <= salp->dim; seq_num++)
6129   {
6130     found_list [seq_num - 1] = 0;
6131   }
6132 
6133   for (slp = seqloc_list, start_num = 1; slp != NULL; slp = slp->next, start_num++)
6134   {
6135     if (slp->choice == SEQLOC_NULL)
6136     {
6137       continue;
6138     }
6139     found_this = FALSE;
6140     if (start_num <= salp->dim)
6141     {
6142       sip = AlnMgr2GetNthSeqIdPtr (salp, start_num);
6143       if (SeqIdComp (sip, SeqLocId (slp)) == SIC_YES)
6144       {
6145         found_list [start_num - 1] = 1;
6146         found_this = TRUE;
6147       }
6148     }
6149 
6150     for (seq_num = 1; seq_num <= salp->dim && ! found_this; seq_num++)
6151     {
6152       sip = AlnMgr2GetNthSeqIdPtr (salp, seq_num);
6153       if (SeqIdComp (sip, SeqLocId (slp)) == SIC_YES)
6154       {
6155         found_list [seq_num - 1] = 1;
6156         found_this = TRUE;
6157       }
6158     }
6159   }
6160 
6161   for (seq_num = 1; seq_num <= salp->dim; seq_num++)
6162   {
6163     if (found_list [seq_num - 1] == 0)
6164     {
6165       sip = AlnMgr2GetNthSeqIdPtr (salp, seq_num);
6166       bsp = BioseqFind (sip);
6167       if (bsp != NULL && bsp->id != NULL)
6168       {
6169         sip = SeqIdFindBest (bsp->id, 0);
6170       }
6171       SeqIdWrite (sip, id_txt, PRINTID_REPORT, sizeof (id_txt));
6172       msg_len += StringLen (id_txt) + 3;
6173       ValNodeAddPointer (&id_list, 0, StringSave (id_txt));
6174     }
6175   }
6176 
6177   if (msg_len > 0)
6178   {
6179     msg_len += StringLen (msg_start) + StringLen (msg_end);
6180     msg_txt = (CharPtr) MemNew (msg_len * sizeof (Char));
6181     if (msg_txt != NULL)
6182     {
6183       StringCpy (msg_txt, msg_start);
6184       for (id_vnp = id_list; id_vnp != NULL; id_vnp = id_vnp->next)
6185       {
6186         StringCat (msg_txt, id_vnp->data.ptrvalue);
6187         if (id_vnp->next != NULL)
6188         {
6189           StringCat (msg_txt, ", ");
6190         }
6191       }
6192       StringCat (msg_txt, msg_end);
6193       if (ANS_NO == Message (MSG_YN, msg_txt))
6194       {
6195         rval = FALSE;
6196       }
6197       msg_txt = MemFree (msg_txt);
6198     }
6199   }
6200   id_list = ValNodeFreeData (id_list);
6201   found_list = MemFree (found_list);
6202 
6203   return rval;
6204 }
6205 
DoApplyFeatureToAlignment(ButtoN b)6206 static void DoApplyFeatureToAlignment (ButtoN b)
6207 {
6208   ApplyAlignmentFeatureDlgPtr aafdp;
6209   BatchApplyFeatureDetailsPtr feature_details_data;
6210   SeqLocPtr                   seqloc_list, slp_next, slp_this, gene_slp;
6211   Int4                        errcount = 0;
6212   ValNodePtr                  ambigList = NULL;
6213   Boolean                     suppressDups = FALSE;
6214   Boolean                     partial5, partial3;
6215   SeqEntryPtr                 sep, nsep, gene_sep;
6216   BioseqPtr                   bsp;
6217   SeqFeatPtr                  sfp, gene_sfp;
6218   GBQualPtr                   gbqual_list = NULL;
6219   Boolean                     found_null = FALSE;
6220 
6221   aafdp = (ApplyAlignmentFeatureDlgPtr) GetObjectExtra (b);
6222   if (aafdp == NULL)
6223   {
6224     return;
6225   }
6226 
6227   feature_details_data = (BatchApplyFeatureDetailsPtr) DialogToPointer (aafdp->feature_details);
6228   seqloc_list = (SeqLocPtr) DialogToPointer (aafdp->location_dlg);
6229 
6230   if (! OkToContinueWithFeatureApply (seqloc_list, aafdp->salp))
6231   {
6232     /* Free data and loclist */
6233     feature_details_data = BatchApplyFeatureDetailsFree (feature_details_data);
6234     slp_this = seqloc_list;
6235     while (slp_this != NULL)
6236     {
6237       slp_next = slp_this->next;
6238       slp_this->next = NULL;
6239       slp_this = SeqLocFree (slp_this);
6240       slp_this = slp_next;
6241     }
6242     return;
6243   }
6244 
6245   if (feature_details_data == NULL || seqloc_list == NULL)
6246   {
6247     /* Free data and loclist */
6248     feature_details_data = BatchApplyFeatureDetailsFree (feature_details_data);
6249     slp_this = seqloc_list;
6250     while (slp_this != NULL)
6251     {
6252       slp_next = slp_this->next;
6253       slp_this->next = NULL;
6254       slp_this = SeqLocFree (slp_this);
6255       slp_this = slp_next;
6256     }
6257     return;
6258   }
6259 
6260   if (aafdp->feattype == ADD_IMP)
6261   {
6262     gbqual_list = GetImpFeatureGBQuals (feature_details_data);
6263   }
6264 
6265   slp_this = seqloc_list;
6266   while (slp_this != NULL)
6267   {
6268     slp_next = slp_this->next;
6269     slp_this->next = NULL;
6270     sfp = NULL;
6271 
6272     bsp = BioseqFindFromSeqLoc (slp_this);
6273     sep = SeqMgrGetSeqEntryForData (bsp);
6274 
6275     if (sep != NULL)
6276     {
6277       nsep = FindNucSeqEntry (sep);
6278       if (nsep != NULL)
6279       {
6280         if (aafdp->feattype == ADD_CDS)
6281         {
6282           sfp = ApplyOneCodingRegion (feature_details_data, bsp, sep, nsep,
6283                                       aafdp->entityID, suppressDups);
6284         }
6285         else if (aafdp->feattype == ADD_RRNA)
6286         {
6287           sfp = ApplyOneRNA (feature_details_data, sep, nsep,
6288                              aafdp->entityID, suppressDups);
6289         }
6290         else if (aafdp->feattype == ADD_IMP)
6291         {
6292           sfp = ApplyOtherFeature (feature_details_data, nsep, gbqual_list);
6293         }
6294       }
6295     }
6296     if (sfp != NULL)
6297     {
6298       /* set location */
6299       sfp->location = SeqLocFree (sfp->location);
6300       sfp->location = slp_this;
6301       CheckSeqLocForPartial (slp_this, &partial5, &partial3);
6302       sfp->partial = partial5 || partial3;
6303 
6304       if (aafdp->feattype == ADD_CDS)
6305       {
6306         SetFrameForCodingRegion (sfp, bsp, feature_details_data,
6307                                  &errcount, &ambigList);
6308         AddProductForCDS (sfp, feature_details_data, sep, nsep, aafdp->entityID);
6309       }
6310       else if (aafdp->feattype == ADD_RRNA)
6311       {
6312 /*        ConvertToOldRNAFormat (sfp); */
6313       }
6314     }
6315 
6316     if (sfp != NULL
6317         || (aafdp->feattype == ADD_IMP
6318             && feature_details_data->featdef_choice == FEATDEF_GENE
6319             && sep != NULL))
6320     {
6321       if (! StringHasNoText (feature_details_data->geneName) || ! StringHasNoText (feature_details_data->geneDesc))
6322       {
6323         /* Create a Gene ref feature on the nuc seq or segment */
6324         /* we can only create a feature where the sep->choice is 1 */
6325         if (sep->choice == 1)
6326         {
6327           gene_sep = sep;
6328         }
6329         else
6330         {
6331           /* if we have added a product, nsep may no longer point to the nucseq entry */
6332           gene_sep = FindNucSeqEntry (sep);
6333         }
6334 
6335         if (aafdp->entityID > 0
6336             && suppressDups
6337             && AlreadyHasFeatOrDesc (gene_sep, SEQFEAT_GENE, 0, 0))
6338         {
6339           /* do not create */
6340         }
6341         else
6342         {
6343           CheckSeqLocForPartial (slp_this, &partial5, &partial3);
6344 
6345           if (sfp == NULL)
6346           {
6347             gene_slp = slp_this;
6348           }
6349           else
6350           {
6351             gene_slp = SeqLocMerge (bsp, slp_this, NULL, TRUE, FALSE, FALSE);
6352             SetSeqLocPartial (gene_slp, partial5, partial3);
6353           }
6354           gene_sfp = ApplyGene (feature_details_data->geneName,
6355                                 feature_details_data,
6356                                 gene_sep, sfp, gene_slp);
6357           gene_sfp->partial = partial5 || partial3;
6358 
6359           if (sfp == NULL)
6360           {
6361             sfp = gene_sfp;
6362           }
6363         }
6364       }
6365     }
6366 
6367     if (sfp == NULL)
6368     {
6369       /* remove location that will not be used */
6370       slp_this = SeqLocFree (slp_this);
6371     }
6372     else
6373     {
6374       /* add comment */
6375       AddToComment (sfp, feature_details_data->featcomment);
6376     }
6377 
6378     slp_this = slp_next;
6379   }
6380 
6381   feature_details_data = BatchApplyFeatureDetailsFree (feature_details_data);
6382 
6383   /* free gbqual_list */
6384   gbqual_list = GBQualFree (gbqual_list);
6385 
6386   ObjMgrSetDirtyFlag (aafdp->entityID, TRUE);
6387   ObjMgrSendMsg (OM_MSG_UPDATE, aafdp->entityID, 0, 0);
6388 
6389   if (!GetStatus (aafdp->leave_dlg_up))
6390   {
6391     Remove (aafdp->form);
6392   }
6393 }
6394 
6395 
EnableApplyFeatureAccept(Pointer data)6396 static void EnableApplyFeatureAccept (Pointer data)
6397 {
6398   ApplyAlignmentFeatureDlgPtr aafdp;
6399 
6400   aafdp = (ApplyAlignmentFeatureDlgPtr) data;
6401   if (aafdp == NULL) return;
6402 
6403   if (OkToAcceptBatchApplyFeatureDetails (aafdp->feature_details))
6404   {
6405     Enable (aafdp->accept);
6406   }
6407   else
6408   {
6409     Disable (aafdp->accept);
6410   }
6411 }
6412 
6413 
ApplyFeatureToAlignment(Uint2 entityID,SeqAlignPtr salp,SeqLocPtr slp,Int4 feattype)6414 extern void ApplyFeatureToAlignment (Uint2 entityID, SeqAlignPtr salp, SeqLocPtr slp, Int4 feattype)
6415 {
6416   ApplyAlignmentFeatureDlgPtr aafdp;
6417   WindoW                      w;
6418   GrouP                       h, c;
6419   Boolean                     nucsOK = TRUE;  /* LATER, figure out whether alignment */
6420   Boolean                     protsOK = TRUE; /* contains nucs or prots */
6421   ButtoN                      b;
6422 
6423   aafdp = (ApplyAlignmentFeatureDlgPtr) MemNew (sizeof (ApplyAlignmentFeatureDlgData));
6424   if (aafdp == NULL) return;
6425 
6426   aafdp->sep = GetTopSeqEntryForEntityID (entityID);
6427   if (aafdp->sep == NULL)
6428   {
6429     aafdp = MemFree (aafdp);
6430     return;
6431   }
6432   aafdp->entityID = entityID;
6433   aafdp->feattype = feattype;
6434   aafdp->salp = salp;
6435 
6436   w = FixedWindow (-50, -33, -10, -10, "Apply Features to Alignment", StdCloseWindowProc);
6437   SetObjectExtra (w, aafdp, StdCleanupExtraProc);
6438   SetObjectExtra (w, aafdp, NULL);
6439   aafdp->form = (ForM) w;
6440   aafdp->input_entityID = entityID;
6441 
6442   h = HiddenGroup (w, -1, 0, NULL);
6443   SetGroupSpacing (h, 10, 10);
6444 
6445   aafdp->location_dlg = CreateIntervalEditorDialogExEx (h, "Location",
6446                                                         4, 2, aafdp->sep,
6447                                                         nucsOK, protsOK,
6448                                                         TRUE, TRUE, TRUE, NULL, NULL,
6449                                                         TRUE, FALSE, NULL, NULL,
6450                                                         TRUE);
6451   PointerToDialog (aafdp->location_dlg, slp);
6452 
6453   aafdp->feature_details = BatchApplyFeatureDetailsDialog (h, feattype, EnableApplyFeatureAccept, aafdp);
6454 
6455   c = HiddenGroup (h, 3, 0, NULL);
6456   aafdp->accept = PushButton (c, "Accept", DoApplyFeatureToAlignment);
6457   SetObjectExtra (aafdp->accept, aafdp, NULL);
6458   b = PushButton (c, "Cancel", StdCancelButtonProc);
6459   aafdp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
6460 
6461   AlignObjects (ALIGN_CENTER, (HANDLE) aafdp->location_dlg,
6462                               (HANDLE) aafdp->feature_details,
6463                               (HANDLE) c,
6464                                NULL);
6465 
6466   EnableApplyFeatureAccept (aafdp);
6467   Show (w);
6468 }
6469 
6470 
GetSeqAnnotForAlignment(SeqAlignPtr sap)6471 extern SeqAnnotPtr GetSeqAnnotForAlignment (SeqAlignPtr sap)
6472 {
6473   SeqAnnotPtr  sanp = NULL;
6474   BioseqPtr    bsp;
6475   BioseqSetPtr bssp;
6476   Boolean      found = FALSE;
6477 
6478   if (sap == NULL)
6479   {
6480     return NULL;
6481   }
6482 
6483   if (sap->idx.parenttype == OBJ_BIOSEQ)
6484   {
6485     bsp = (BioseqPtr) sap->idx.parentptr;
6486     if (bsp != NULL)
6487     {
6488       sanp = bsp->annot;
6489     }
6490   }
6491   else if (sap->idx.parenttype == OBJ_BIOSEQSET)
6492   {
6493     bssp = (BioseqSetPtr) sap->idx.parentptr;
6494     if (bssp != NULL)
6495     {
6496       sanp = bssp->annot;
6497     }
6498   }
6499   else if (sap->idx.parenttype == OBJ_SEQANNOT)
6500   {
6501     sanp = (SeqAnnotPtr) sap->idx.parentptr;
6502   }
6503   while (sanp != NULL && !found)
6504   {
6505     if (sanp->type == 2 && sanp->data == sap)
6506     {
6507       found = TRUE;
6508     }
6509     else
6510     {
6511       sanp = sanp->next;
6512     }
6513   }
6514   return sanp;
6515 }
6516 
ConvertPairwiseToMultipleAlignment(SeqAlignPtr sap)6517 extern void ConvertPairwiseToMultipleAlignment (SeqAlignPtr sap)
6518 {
6519   SeqAlignPtr salp, salp_next;
6520 
6521   salp = sap;
6522   while (salp != NULL)
6523   {
6524      if (salp->saip != NULL)
6525      {
6526         SeqAlignIndexFree(salp->saip);
6527         salp->saip = NULL;
6528      }
6529      salp = salp->next;
6530   }
6531   AlnMgr2IndexSeqAlign (sap);
6532 
6533   salp = AlnMgr2GetSubAlign (sap, 0, -1, 0, FALSE);
6534   if (salp == NULL) return;
6535   AlnMgr2IndexSeqAlign (salp);
6536 
6537   if (sap->idx.prevlink != NULL) {
6538     *(sap->idx.prevlink) = (Pointer) salp;
6539   }
6540 
6541   while (sap != NULL) {
6542     salp_next = sap->next;
6543     sap->next = NULL;
6544     SeqAlignFree (sap);
6545     sap = salp_next;
6546   }
6547 }
6548