1 /*   sequin9.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:  sequin9.c
27 *
28 * Author:  Jonathan Kans
29 *
30 * Version Creation Date:   4/20/99
31 *
32 * $Revision: 6.529 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date     Name        Description of modification
39 * -------  ----------  -----------------------------------------------------
40 *
41 *
42 * ==========================================================================
43 */
44 
45 #include <subutil.h>
46 #include <explore.h>
47 #include <alignmgr.h>
48 #include <urkptpf.h>
49 #include <entrez.h>
50 #include <accentr.h>
51 #include <urlquery.h>
52 #include <vecscrn.h>
53 #include <vecscnapi.h>
54 #include <qblastapi.h>
55 #include <edutil.h>
56 #include <actutils.h>
57 #include <findrepl.h>
58 #include <rpsutil.h>
59 #include "sequin.h"
60 #include <seqpanel.h>
61 #include <salpanel.h>
62 #include <assert.h>
63 #include <pmfapi.h>
64 #include <vsm.h>
65 #define NLM_GENERATED_CODE_PROTO
66 #include <objmacro.h>
67 #include <macrodlg.h>
68 #include <macroapi.h>
69 
70 /*-------------------*/
71 /* Defined Constants */
72 /*-------------------*/
73 
74 #define MAX_ID_LEN 84
75 #define FASTA_READ_OK     0
76 #define FASTA_READ_ERROR -1
77 #define FASTA_READ_DONE   1
78 
79 #define CONVERTPUBS_NOT_SET 0
80 #define CONVERTPUBS_YES     1
81 #define CONVERTPUBS_NO      2
82 
83 /* constants for update sequence */
84 #define UPDATE_CHOICE_NOT_SET        0
85 #define UPDATE_SEQUENCE_ONLY         1
86 #define UPDATE_FEATURES_ONLY         2
87 #define UPDATE_SEQUENCE_AND_FEATURES 3
88 
89 #define UPDATE_REPLACE               1
90 #define UPDATE_EXTEND5               2
91 #define UPDATE_EXTEND3               3
92 #define UPDATE_PATCH                 4
93 
94 enum update_dup_feat_type
95 {
96   UPDATE_FEAT_DUP_NOT_SET = 0,
97   UPDATE_FEAT_DUP_USE_NEW,
98   UPDATE_FEAT_DUP_USE_OLD,
99   UPDATE_FEAT_DUP_USE_BOTH,
100   UPDATE_FEAT_DUP_MERGE,
101   UPDATE_FEAT_DUP_REPLACE
102 };
103 
104 
105 /*-----------------*/
106 /* Data Structures */
107 /*-----------------*/
108 
109 typedef struct {
110   Char       newId[MAX_ID_LEN];
111   BioseqPtr  matchingBsp;
112 } UpdateData, PNTR UpdateDataPtr;
113 
114 typedef struct upsdata {
115   FORM_MESSAGE_BLOCK
116   ButtoN              accept;
117   ButtoN              acceptAll;
118   CharPtr             aln1;
119   CharPtr             aln2;
120   Int4                aln_length;
121   Int2                charwidth;
122   Int2                convertPubs;
123   VieweR              details;
124   Boolean             diffOrgs;
125   SegmenT             dtpict;
126   FILE                *fp;
127   ValNodePtr          indels;
128   Boolean             isSet;
129   ButtoN              keepProteinIDs;
130   PaneL               letters;
131   Int2                lineheight;
132   Int4                log10_aln_length;
133   Int2                maxchars;
134   ValNodePtr          mismatches;
135   Int4                new3;
136   Int4                new5;
137   Int4                newa;
138   BioseqPtr           newbsp;
139   ButtoN              replace_all;
140   GrouP               nobm;
141   Int4                old3;
142   Int4                old5;
143   Int4                olda;
144   BioseqPtr           oldbsp;
145   VieweR              overview;
146   SegmenT             ovpict;
147   Int4                recomb1;
148   Int4                recomb2;
149   Boolean             revcomp;
150   GrouP               rmc;
151   SeqAlignPtr         salp;
152   Int4                scaleX;
153   CharPtr             seq1;
154   CharPtr             seq2;
155   GrouP               sfb;
156   Int4                startmax;
157   Int4                stopmax;
158   Uint1               strandnew;
159   Uint1               strandold;
160   Boolean             useGUI;
161   Boolean             do_update;
162   ButtoN              add_cit_subs;
163   ButtoN              update_proteins;
164   Boolean             suppress_continue_msg;
165   Boolean             suppress_instant_refresh;
166   ButtoN              update_quality_scores_btn;
167   FILE                *log_fp;
168   Char                log_path [PATH_MAX];
169   Boolean             data_in_log;
170   ButtoN              truncate_proteins_btn;
171   ButtoN              extend_proteins5_btn;
172   ButtoN              extend_proteins3_btn;
173   ButtoN              correct_cds_genes_btn;
174   Boolean             truncate_proteins;
175   Boolean             extend_proteins5;
176   Boolean             extend_proteins3;
177   Boolean             correct_cds_genes;
178   ValNodePtr          transl_except_list;
179   Int2                rmcval;      /* This is the choice selected from the
180                                     * rmc radio button group.
181                                     * We store it so that we can use it in
182                                     * Accept All.
183                                     */
184 
185   SeqEntryPtr         seqsubsep;   /* when we are updating from a Sequin record
186                                     * that contains a set, store the set here.
187                                     */
188   Int4                seqsubpos;   /* when we are updating from a Sequin record
189                                     * that contains a set, store the number of
190                                     * Bioseqs already processed here.
191                                     */
192 
193   Int2                no_aln_choice; /* what to do when updating a set and no
194                                       * alignment is found.
195                                       */
196 
197   ValNodePtr          affected_variation_features;   /* list of variation features
198                                                       * affected by this update.
199                                                       * by "affected" we mean that
200                                                       * an insertion, deletion,
201                                                       * or replacement takes place
202                                                       * either inside the variation
203                                                       * location, or immediately
204                                                       * to the left or right of the
205                                                       * location.
206                                                       */
207 } UpsData, PNTR UpsDataPtr;
208 
209 /*---------------------*/
210 /* Function prototypes */
211 /*---------------------*/
212 
213 static Int2 UpdateNextBioseqInFastaSet (UpsDataPtr udp);
214 static void FreeUdpFields (UpsDataPtr udp);
215 static void TruncateCDS (SeqFeatPtr sfp, Uint1 frame, BioseqPtr pbsp);
216 
217 extern void SubmitToNCBI (IteM i);
218 extern void QuitProc (void);
219 extern void NewFeaturePropagate (IteM i);
220 extern void FuseSlpJoins (IteM i);
221 
222 /*-----------*/
223 /* Functions */
224 /*-----------*/
225 
226 /*
227  * This function is called by HandleOneNewAsnProc, CommonHandleMultBioseqs,
228  * and DoReadAnythingLoop in sequin1.c
229  */
HandleProjectAsn(ProjectPtr proj,Uint2 entityID)230 extern void HandleProjectAsn (ProjectPtr proj, Uint2 entityID)
231 
232 {
233   Int2              db = -1;
234   EntrezGlobalsPtr  egp;
235   Int4              i;
236   ValNodePtr        list;
237   Int4              num;
238   ValNodePtr        pip;
239   Int4Ptr           uids;
240   ValNodePtr        vnp;
241 
242   if (proj == NULL) return;
243   if (! useEntrez) return;
244   egp = (EntrezGlobalsPtr) GetAppProperty ("EntrezGlobals");
245   if (egp == NULL) return;
246   pip = proj->data;
247   if (pip == NULL) return;
248   list = (ValNodePtr) pip->data.ptrvalue;
249   if (list == NULL) return;
250   if (pip->choice >= ProjectItem_protent && pip->choice <= ProjectItem_genomeent) {
251     if (egp->retrieveProjectProc == NULL) return;
252     /*
253     if (! EntrezIsInited ()) {
254       SequinEntrezInit ("Sequin", FALSE, NULL);
255     }
256     */
257     egp->retrieveProjectProc (NULL, (Pointer) proj);
258     Update ();
259     return;
260   }
261   if (egp->retrieveDocsProc == NULL) return;
262   switch (pip->choice) {
263     case ProjectItem_pmuid :
264       db = 0;
265       break;
266     case ProjectItem_protuid :
267       db = 1;
268       break;
269     case ProjectItem_nucuid :
270       db = 2;
271       break;
272     case ProjectItem_genomeuid :
273       db = 4;
274       break;
275     case ProjectItem_structuid :
276       db = 3;
277       break;
278     default :
279       break;
280   }
281   if (db == -1) return;
282   /*
283   if (! EntrezIsInited ()) {
284     SequinEntrezInit ("Sequin", FALSE, NULL);
285   }
286   */
287   num = ValNodeLen (list);
288   uids = MemNew ((size_t) (num * sizeof (Int4)));
289   if (uids == NULL) return;
290   for (i = 0, vnp = list; i < 32766 && vnp != NULL; i++, vnp = vnp->next) {
291     uids [i] = vnp->data.intvalue;
292   }
293   if (egp->retrieveDocsProc != NULL) {
294     egp->retrieveDocsProc (NULL, (Int2) num, 0, uids, db);
295   }
296   MemFree (uids);
297   Update ();
298 }
299 
300 /* BioseqViewOrDocSumChoice allows a single callback for each analysis item */
BioseqViewOrDocSumChoice(NewObjectPtr nop)301 static Int2 BioseqViewOrDocSumChoice (NewObjectPtr nop)
302 
303 {
304   Int2  which = 0;   /* 1 = bioseq viewer, 2 = docsum window */
305 
306   if (nop == NULL) return 0;
307 #ifdef WIN_MAC
308   if (bioseqViewUp) {
309     which = 1;
310   } else if (docSumUp) {
311     which = 2;
312   }
313 #else
314   if (nop->bspOK) {
315     which = 1;
316   } else if (nop->dsmOK) {
317     which = 2;
318   }
319 #endif
320   return which;
321 }
322 
323 /*
324 #define TEST_APPLE_EVENT_MESSAGING
325 */
326 
327 #ifndef TEST_APPLE_EVENT_MESSAGING
AddRestrictionSite(SeqAnnotPtr annot,PackSeqPntPtr pspp,CharPtr name)328 static void AddRestrictionSite (SeqAnnotPtr annot, PackSeqPntPtr pspp, CharPtr name)
329 
330 {
331   DbtagPtr     dbt;
332   ObjectIdPtr  oip;
333   RsiteRefPtr  rrp;
334   SeqFeatPtr   sfp, lastsfp;
335   SeqLocPtr    slp;
336 
337   if (annot == NULL || pspp == NULL || name == NULL) return;
338   slp = ValNodeNew (NULL);
339   if (slp == NULL) return;
340   slp->choice = SEQLOC_PACKED_PNT;
341   slp->data.ptrvalue = (Pointer) pspp;
342   sfp = SeqFeatNew ();
343   if (sfp == NULL) return;
344 
345   sfp->data.choice = SEQFEAT_RSITE;
346   sfp->location = slp;
347   dbt = DbtagNew ();
348   if (dbt != NULL) {
349     dbt->db = StringSave ("REBASE");
350     oip = ObjectIdNew ();
351     if (oip != NULL) {
352       oip->str = StringSave (name);
353     }
354     dbt->tag = oip;
355   }
356   rrp = ValNodeNew (NULL);
357   if (rrp != NULL) {
358     rrp->choice = 2;
359     rrp->data.ptrvalue = dbt;
360   }
361   sfp->data.value.ptrvalue = (Pointer) rrp;
362 
363   if (annot->data == NULL) {
364     annot->data = (Pointer) sfp;
365   } else {
366     lastsfp = (SeqFeatPtr) annot->data;
367     while (lastsfp->next != NULL) {
368       lastsfp = lastsfp->next;
369     }
370     lastsfp->next = sfp;
371   }
372 }
373 
RestrictionSearchProc(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)374 static void RestrictionSearchProc (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
375 
376 {
377   SeqAnnotPtr    annot;
378   BioseqPtr      bsp;
379   ComPatPtr      cpp, cpph;
380   ValNodePtr     desc;
381   SeqAnnotPtr    lastannot;
382   PackSeqPntPtr  pspp;
383   Int4           pt;
384   SeqAlignPtr    sap;
385   SeqLocPtr      slp, slpn;
386 
387   if (sep == NULL) return;
388   if (! IS_Bioseq (sep)) return;
389   bsp = (BioseqPtr) sep->data.ptrvalue;
390   if (bsp == NULL) return;
391   if (! ISA_na (bsp->mol)) return;
392 
393   desc = SeqDescrNew (NULL);
394   desc->choice = Annot_descr_name;
395   desc->data.ptrvalue = StringSave ("cutsites");
396 
397   annot = SeqAnnotNew ();
398   annot->type = 1;
399   annot->desc = desc;
400   annot->data = NULL;
401 
402   cpph = (ComPatPtr) mydata;
403   cpp = cpph;
404   while (cpp != NULL) {
405     sap = PatternMatchBioseq (bsp, cpp, 0);
406     slp = MatchSa2Sl (&sap);
407     if (slp != NULL) {
408       pspp = PackSeqPntNew ();
409       pspp->id = SeqIdDup (SeqIdFindBest (bsp->id, 0));
410       while (slp != NULL) {
411         pt = SeqLocStart (slp);
412         PackSeqPntPut (pspp, pt);
413         slpn = slp->next;
414         SeqLocFree (slp);
415         slp = slpn;
416       }
417       AddRestrictionSite (annot, pspp, cpp->name);
418     }
419     cpp = cpp->nextpattern;
420   }
421 
422   if (annot->data == NULL) {
423     SeqAnnotFree (annot);
424     return;
425   }
426   if (bsp->annot == NULL) {
427     bsp->annot = annot;
428   } else {
429     lastannot = bsp->annot;
430     while (lastannot->next != NULL) {
431       lastannot = lastannot->next;
432     }
433     lastannot->next = annot;
434   }
435 }
436 #endif
437 
SimpleRsiteProc(IteM i)438 static void SimpleRsiteProc (IteM i)
439 
440 {
441   BaseFormPtr   bfp;
442   BioseqPtr     bsp;
443   NewObjectPtr  nop;
444   SeqEntryPtr   sep = NULL;
445   Int2          which;
446 #ifdef TEST_APPLE_EVENT_MESSAGING
447   AsnIoPtr      aip;
448   Char          tmp [PATH_MAX];
449 #else
450   ComPatPtr     cpph;
451   Char          enzyme [64];
452   Int2          j;
453   Char          temp [32];
454   ValNodePtr    enzymes;
455 #endif
456 
457   nop = (NewObjectPtr) GetObjectExtra (i);
458   if (nop == NULL) return;
459 #ifdef WIN_MAC
460   bfp = (BaseFormPtr) currentFormDataPtr;
461 #else
462   bfp = nop->bfp;
463 #endif
464   if (bfp == NULL) return;
465   which = BioseqViewOrDocSumChoice (nop);
466   if (which != 1) return;
467   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
468   if (bsp != NULL) {
469     sep = SeqMgrGetSeqEntryForData (bsp);
470   } else {
471     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
472   }
473   if (sep == NULL) return;
474 
475 #ifdef TEST_APPLE_EVENT_MESSAGING
476   TmpNam (tmp);
477   aip = AsnIoOpen (tmp, "w");
478   if (aip != NULL) {
479     SeqEntryAsnWrite (sep, aip, NULL);
480     AsnIoClose (aip);
481     /* Nlm_SendOpenDocAppleEventEx (tmp, "REST", NULL, TRUE); */
482     Nlm_SendOpenDocAppleEventEx (tmp, NULL, "RsiteFind", TRUE);
483   }
484 #else
485   enzymes = NULL;
486   j = 1;
487   sprintf (temp, "ENZ_%d", (int) j);
488   while (GetAppParam ("SEQNCGIS", "ENZYMES", temp, NULL, enzyme, sizeof (enzyme) - 1)) {
489     ValNodeCopyStr (&enzymes, 0, enzyme);
490     j++;
491     sprintf (temp, "ENZ_%d", (int) j);
492   }
493   if (enzymes == NULL) {
494     ValNodeCopyStr (&enzymes, 0, "BamHI");
495     ValNodeCopyStr (&enzymes, 0, "EcoRI");
496     ValNodeCopyStr (&enzymes, 0, "HindIII");
497   }
498   cpph = ReadRENPattern ("ncbiren.dat", FALSE, enzymes);
499   /* PalindromeCheck (cpph); */
500   SeqEntryExplore (sep, (Pointer) cpph, RestrictionSearchProc);
501   ComPatFree (cpph);
502   ValNodeFreeData (enzymes);
503 
504   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
505   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
506   Update ();
507 #endif
508 }
509 
510 static VQUEUE  vsquerylist = NULL;
511 
512 static Int2 vsquerynum = 0;
513 
514 /*
515 static void LIBCALLBACK AnnounceCallback (CharPtr requestID, CharPtr seqID, Int2 estimatedSeconds)
516 
517 {
518   if (StringHasNoText (requestID)) {
519     requestID = "?";
520   }
521   if (StringHasNoText (seqID)) {
522     seqID = "?";
523   }
524   Message (MSG_POST, "Queued rID %s, seqID %s, estimated seconds = %d",
525            requestID, seqID, (int) estimatedSeconds);
526 
527   vsquerynum++;
528 }
529 
530 static Boolean LIBCALLBACK VecScreenCallback (
531   CharPtr filename,
532   VoidPtr userdata,
533   CharPtr requestID,
534   CharPtr seqID,
535   Boolean success
536 )
537 
538 {
539   if (StringHasNoText (requestID)) {
540     requestID = "?";
541   }
542   if (StringHasNoText (seqID)) {
543     seqID = "?";
544   }
545   if (success) {
546     if (! SequinHandleNetResults (filename)) {
547     }
548   } else {
549     Message (MSG_POST, "Failure of rID '%s', seqID %s", requestID, seqID);
550   }
551   return TRUE;
552 }
553 
554 static void DoVecScreens (BioseqPtr bsp, Pointer userdata)
555 
556 {
557   CharPtr  service;
558 
559   if (bsp == NULL || ISA_aa (bsp->mol)) return;
560   service = (CharPtr) userdata;
561   VecScreenAsynchronousRequest (service, bsp, &vsquerylist, VecScreenCallback, AnnounceCallback, NULL);
562 }
563 
564 static void SimpleVecScreenCommon (IteM i, CharPtr service)
565 
566 {
567   BaseFormPtr   bfp;
568   BioseqPtr     bsp;
569   NewObjectPtr  nop;
570   SeqEntryPtr   sep = NULL;
571   Int2          which;
572 
573   nop = (NewObjectPtr) GetObjectExtra (i);
574   if (nop == NULL) return;
575 #ifdef WIN_MAC
576   bfp = (BaseFormPtr) currentFormDataPtr;
577 #else
578   bfp = nop->bfp;
579 #endif
580   if (bfp == NULL) return;
581   which = BioseqViewOrDocSumChoice (nop);
582   if (which != 1) return;
583   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
584   if (bsp != NULL) {
585     sep = SeqMgrGetSeqEntryForData (bsp);
586     if (sep == NULL) return;
587     VecScreenAsynchronousRequest (service, bsp, &vsquerylist, VecScreenCallback, AnnounceCallback, NULL);
588   } else {
589     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
590     if (sep == NULL) return;
591     VisitBioseqsInSep (sep, (Pointer) service, DoVecScreens);
592   }
593 }
594 */
595 
596 typedef struct vsdata {
597   CharPtr     date;
598   CharPtr     path;
599   CharPtr     database;
600   Boolean     changed;
601   Int4        count;
602   MonitorPtr  mon;
603 } VsData, PNTR VsDataPtr;
604 
605 static CharPtr vectorStrengths [6] = {
606   NULL,
607   "Strong match",
608   "Moderate match",
609   "Weak match",
610   "Suspect origin",
611   "Unknown vector match"
612 };
613 
CountVecScreens(BioseqPtr bsp,Pointer userdata)614 static void CountVecScreens (BioseqPtr bsp, Pointer userdata)
615 
616 {
617   Int4Ptr  maxp;
618 
619   if (bsp == NULL || ISA_aa (bsp->mol)) return;
620   maxp = (Int4Ptr) userdata;
621   (*maxp)++;
622 }
623 
DoVecScreens(BioseqPtr bsp,Pointer userdata)624 static void DoVecScreens (BioseqPtr bsp, Pointer userdata)
625 
626 {
627   AnnotDescrPtr   desc;
628   GeneRefPtr      grp;
629   Int2            hits;
630   ImpFeatPtr      ifp;
631   ValNodePtr      locs = NULL;
632   Char            note [128];
633   SeqAnnotPtr     prevsap;
634   SeqFeatPtr      prevsfp;
635   SeqAnnotPtr     sap = NULL;
636   SeqFeatPtr      sfp = NULL;
637   SeqIdPtr        sip;
638   SeqLocPtr       slp;
639   Int4            start;
640   Int4            stop;
641   Uint1           strength;
642   SeqLocPtr       tmp;
643   VsDataPtr       vsp;
644   ValNodePtr      vnp;
645   SeqFeatXrefPtr  xref;
646 
647   if (bsp == NULL || ISA_aa (bsp->mol)) return;
648   vsp = (VsDataPtr) userdata;
649   if (vsp == NULL) return;
650   sip = SeqIdFindBest (bsp->id, 0);
651   if (sip == NULL) return;
652 
653   if (vsp->mon != NULL) {
654     MonitorIntValue (vsp->mon, vsp->count);
655   }
656   (vsp->count)++;
657 
658   hits = VSScreenSequence (bsp, NULL, vsp->path, NULL, &locs, NULL, NULL);
659   for (vnp = locs; vnp != NULL; vnp = vnp->next) {
660     strength = vnp->choice;
661     if (strength < 1 || strength > 4) {
662       strength = 5;
663     }
664     slp = (SeqLocPtr) vnp->data.ptrvalue;
665     if (slp == NULL) continue;
666     if (slp->choice == SEQLOC_PACKED_INT) {
667       for (tmp = (SeqLocPtr) slp->data.ptrvalue; tmp != NULL; tmp = tmp->next) {
668         start = SeqLocStart (tmp);
669         stop = SeqLocStop (tmp);
670         if (start < 0 || stop < 0) continue;
671         vsp->changed = TRUE;
672 
673         if (sap == NULL) {
674           sap = SeqAnnotNew ();
675           if (sap != NULL) {
676             sap->type = 1;
677             desc = AnnotDescrNew (NULL);
678             if (desc != NULL) {
679               desc->choice = Annot_descr_name;
680               desc->data.ptrvalue = StringSave ("VecScreen");
681               sap->desc = desc;
682             }
683           }
684         }
685 
686         sfp = SeqFeatNew ();
687         if (sfp != NULL) {
688 
689           /* make misc_feature for now */
690 
691           sfp->data.choice = SEQFEAT_IMP;
692           ifp = ImpFeatNew ();
693           if (ifp != NULL) {
694             ifp->key = StringSave ("misc_feature");
695           }
696           AddQualifierToFeature (sfp, "standard_name", "Vector Contamination");
697           AddQualifierToFeature (sfp, "phenotype", vectorStrengths [(int) strength]);
698 
699           sprintf (note, "Screened against %s using VecScreen on %s", vsp->database, vsp->date);
700           sfp->comment = StringSave (note);
701 
702           /* suppress /gene */
703 
704           grp = GeneRefNew ();
705           if (grp != NULL) {
706             xref = SeqFeatXrefNew ();
707             sfp->xref = xref;
708             if (xref != NULL) {
709               xref->data.choice = SEQFEAT_GENE;
710               xref->data.value.ptrvalue = (Pointer) grp;
711             }
712           }
713 
714           sfp->data.value.ptrvalue = (Pointer) ifp;
715 
716           if (sap != NULL) {
717             if (sap->data != NULL) {
718               prevsfp = sap->data;
719               while (prevsfp->next != NULL) {
720                 prevsfp = prevsfp->next;
721               }
722               prevsfp->next = sfp;
723             } else {
724               sap->data = (Pointer) sfp;
725             }
726           }
727 
728           sfp->location = AddIntervalToLocation (NULL, sip, (Int4) start, (Int4) stop, FALSE, FALSE);
729         }
730       }
731     }
732     SeqLocFree (slp);
733   }
734   locs = ValNodeFree (locs);
735 
736   if (sap != NULL) {
737     if (bsp->annot != NULL) {
738       prevsap = bsp->annot;
739       while (prevsap->next != NULL) {
740         prevsap = prevsap->next;
741       }
742       prevsap->next = sap;
743     } else {
744       bsp->annot = sap;
745     }
746   }
747 }
748 
749 
VsDataFree(VsDataPtr vsp)750 static VsDataPtr VsDataFree (VsDataPtr vsp)
751 {
752   if (vsp != NULL) {
753     vsp->date = MemFree (vsp->date);
754     vsp->path = MemFree (vsp->path);
755     vsp = MemFree (vsp);
756   }
757   return vsp;
758 }
759 
760 
InitVecScreenData(CharPtr database)761 static VsDataPtr InitVecScreenData (CharPtr database)
762 
763 {
764   VsDataPtr     vsp;
765   Char          path [PATH_MAX];
766   CharPtr       pathplusone;
767   Char          quote [4];
768   Char          date [32];
769   DatePtr       dp;
770   CharPtr       check_existence;
771   CharPtr       ptr;
772   Boolean       no_ncbi_data = FALSE;
773   struct stat   buffer;
774 
775   vsp = (VsDataPtr) MemNew (sizeof (VsData));
776   MemSet (vsp, 0, sizeof (VsData));
777   path [0] = '"';
778   path [1] = '\0';
779   pathplusone = &(path [1]);
780   GetAppParam ("NCBI", "NCBI", "DATA", "", pathplusone, sizeof (path) - 1);
781   if (StringHasNoText (pathplusone)) {
782     no_ncbi_data = TRUE;
783   }
784 
785   /*
786   if (StringChr (path, ' ') != NULL) {
787     Message (MSG_OK, "Unable to process because vector database file\npath must not have a space character.  Path is:\n'%s'", path);
788     return;
789   }
790   */
791 
792   FileBuildPath (pathplusone, NULL, database);
793 
794   quote [0] = '"';
795   quote [1] = '\0';
796   StringCat (pathplusone, quote);
797 
798   date [0] = '\0';
799   dp = DateCurr ();
800   DatePrint (dp, date);
801   DateFree (dp);
802 
803   check_existence = (CharPtr) MemNew (sizeof (Char) * (StringLen (pathplusone) + 5));
804   StringNCpy (check_existence, pathplusone, StringLen (pathplusone) - 1);
805   StringCat (check_existence, ".nsq");
806 
807   if (stat (check_existence, &buffer) != 0) {
808     if (no_ncbi_data) {
809       ProgramPath (path, sizeof (path));
810       ptr = StringRChr (path, DIRDELIMCHR);
811       if (ptr != NULL) {
812         ptr++;
813         *ptr = '\0';
814       }
815       Message (MSG_ERROR, "No database files at %s", path);
816     } else {
817       Message (MSG_ERROR, "No database files at %s", check_existence);
818     }
819     vsp = VsDataFree(vsp);
820     check_existence = MemFree (check_existence);
821     return vsp;
822   }
823   check_existence = MemFree (check_existence);
824 
825   vsp->date = StringSave(date);
826   vsp->path = StringSave(path);
827   vsp->database = database;
828   vsp->changed = FALSE;
829   vsp->count = 0;
830   vsp->mon = NULL;
831   return vsp;
832 }
833 
834 
VecScreenAll(Uint2 entityID)835 NLM_EXTERN void VecScreenAll (Uint2 entityID)
836 
837 {
838   SeqEntryPtr   sep;
839   Int4          max;
840   VsDataPtr     vsp;
841 
842   vsp = InitVecScreenData("UniVec_Core");
843   if (vsp == NULL) {
844     return;
845   }
846   sep = GetTopSeqEntryForEntityID (entityID);
847   if (sep == NULL) return;
848   max = 0;
849   VisitBioseqsInSep (sep, (Pointer) &max, CountVecScreens);
850   if (max > 2) {
851     vsp->mon = MonitorIntNewEx ("VecScreen Progress", 0, max - 1, FALSE);
852   }
853   VisitBioseqsInSep (sep, (Pointer) vsp, DoVecScreens);
854   if (vsp->mon != NULL) {
855     vsp->mon = MonitorFree (vsp->mon);
856     Update ();
857   }
858   if (vsp->changed) {
859     ObjMgrSetDirtyFlag (entityID, TRUE);
860     ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
861     Update ();
862   } else {
863     Message (MSG_POST, "No vector contamination found");
864   }
865   vsp = VsDataFree(vsp);
866 }
867 
868 
CountWizardVecScreen(SeqEntryPtr sep)869 static Int4 CountWizardVecScreen (SeqEntryPtr sep)
870 {
871   Int4 max = 0;
872   BioseqSetPtr bssp;
873 
874   while (sep != NULL) {
875     if (IS_Bioseq (sep)) {
876       CountVecScreens(sep->data.ptrvalue, &max);
877     } else if (IS_Bioseq_set (sep)) {
878       bssp = (BioseqSetPtr) sep->data.ptrvalue;
879       max += CountWizardVecScreen (bssp->seq_set);
880     }
881     sep = sep->next;
882   }
883   return max;
884 }
885 
886 
WizardDoVecScreen(SeqEntryPtr sep,VsDataPtr vsp)887 static void WizardDoVecScreen (SeqEntryPtr sep, VsDataPtr vsp)
888 {
889   BioseqSetPtr bssp;
890 
891   while (sep != NULL) {
892     if (IS_Bioseq (sep)) {
893       DoVecScreens(sep->data.ptrvalue, vsp);
894     } else if (IS_Bioseq_set (sep)) {
895       bssp = (BioseqSetPtr) sep->data.ptrvalue;
896       WizardDoVecScreen (bssp->seq_set, vsp);
897     }
898     sep = sep->next;
899   }
900 }
901 
902 
VecScreenWizard(SeqEntryPtr sep)903 NLM_EXTERN Boolean VecScreenWizard (SeqEntryPtr sep)
904 {
905   Int4          max;
906   VsDataPtr     vsp;
907   Boolean       rval = FALSE;
908 
909   vsp = InitVecScreenData("UniVec");
910   if (vsp == NULL) {
911     return FALSE;
912   }
913   if (sep == NULL) {
914     vsp = VsDataFree(vsp);
915     return FALSE;
916   }
917   max = CountWizardVecScreen(sep);
918   if (max > 2) {
919     vsp->mon = MonitorIntNewEx ("VecScreen Progress", 0, max - 1, FALSE);
920   }
921   WizardDoVecScreen (sep, vsp);
922   if (vsp->mon != NULL) {
923     vsp->mon = MonitorFree (vsp->mon);
924     Update ();
925   }
926   rval = vsp->changed;
927   vsp = VsDataFree(vsp);
928   return rval;
929 }
930 
931 
SimpleVecScreenCommon(IteM i,CharPtr database)932 static void SimpleVecScreenCommon (IteM i, CharPtr database)
933 
934 {
935   BaseFormPtr   bfp;
936   BioseqPtr     bsp;
937   Int4          max;
938   SeqEntryPtr   sep;
939   VsDataPtr     vsp;
940 
941 #ifdef WIN_MAC
942   bfp = (BaseFormPtr) currentFormDataPtr;
943 #else
944   bfp = (BaseFormPtr) GetObjectExtra (i);
945 #endif
946   if (bfp == NULL) return;
947 
948   vsp = InitVecScreenData(database);
949   if (vsp == NULL) {
950     return;
951   }
952   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
953   if (bsp != NULL) {
954     DoVecScreens (bsp, (Pointer) vsp);
955   } else {
956     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
957     if (sep == NULL) return;
958     max = 0;
959     VisitBioseqsInSep (sep, (Pointer) &max, CountVecScreens);
960     if (max > 2) {
961       vsp->mon = MonitorIntNewEx ("VecScreen Progress", 0, max - 1, FALSE);
962     }
963     VisitBioseqsInSep (sep, (Pointer) vsp, DoVecScreens);
964     if (vsp->mon != NULL) {
965       vsp->mon = MonitorFree (vsp->mon);
966       Update ();
967     }
968   }
969 
970   if (vsp->changed) {
971     ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
972     ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
973     Update ();
974   } else {
975     Message (MSG_POST, "No vector contamination found");
976   }
977   vsp = VsDataFree (vsp);
978 }
979 
SimpleUniVecScreenProc(IteM i)980 extern void SimpleUniVecScreenProc (IteM i)
981 
982 {
983   SimpleVecScreenCommon (i, "UniVec");
984 }
985 
SimpleUniVecCoreScreenProc(IteM i)986 extern void SimpleUniVecCoreScreenProc (IteM i)
987 
988 {
989   SimpleVecScreenCommon (i, "UniVec_Core");
990 }
991 
992 static QBQUEUE  qbquerylist = NULL;
993 
QBAnnounceCallback(CharPtr requestID,CharPtr seqID,Int2 estimatedSeconds)994 static void LIBCALLBACK QBAnnounceCallback (CharPtr requestID, CharPtr seqID, Int2 estimatedSeconds)
995 
996 {
997   if (StringHasNoText (requestID)) {
998     requestID = "?";
999   }
1000   if (StringHasNoText (seqID)) {
1001     seqID = "?";
1002   }
1003   Message (MSG_POST, "Queued rID %s, seqID %s, estimated seconds = %d",
1004            requestID, seqID, (int) estimatedSeconds);
1005 }
1006 
QBCallback(CharPtr filename,VoidPtr userdata,CharPtr requestID,CharPtr seqID,Boolean success)1007 static Boolean LIBCALLBACK QBCallback (
1008   CharPtr filename,
1009   VoidPtr userdata,
1010   CharPtr requestID,
1011   CharPtr seqID,
1012   Boolean success
1013 )
1014 
1015 {
1016   if (StringHasNoText (requestID)) {
1017     requestID = "?";
1018   }
1019   if (StringHasNoText (seqID)) {
1020     seqID = "?";
1021   }
1022   if (success) {
1023     if (! SequinHandleNetResults (filename)) {
1024       /* LaunchGeneralTextViewer (path, "QueueFastaQueryToURL failed"); */
1025     }
1026   } else {
1027     Message (MSG_POST, "Failure of rID '%s', seqID %s", requestID, seqID);
1028   }
1029   return TRUE;
1030 }
1031 
SimpleQBlastProc(IteM i)1032 static void SimpleQBlastProc (IteM i)
1033 
1034 {
1035   BaseFormPtr   bfp;
1036   BioseqPtr     bsp;
1037   NewObjectPtr  nop;
1038   SeqEntryPtr   sep = NULL;
1039   Int2          which;
1040 
1041   nop = (NewObjectPtr) GetObjectExtra (i);
1042   if (nop == NULL) return;
1043 #ifdef WIN_MAC
1044   bfp = (BaseFormPtr) currentFormDataPtr;
1045 #else
1046   bfp = nop->bfp;
1047 #endif
1048   if (bfp == NULL) return;
1049   which = BioseqViewOrDocSumChoice (nop);
1050   if (which != 1) return;
1051   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
1052   if (bsp != NULL) {
1053     sep = SeqMgrGetSeqEntryForData (bsp);
1054   } else {
1055     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1056   }
1057   if (sep == NULL) return;
1058 
1059   QBlastAsynchronousRequest ("nr", "blastn", bsp, &qbquerylist, QBCallback, QBAnnounceCallback, NULL);
1060 }
1061 
1062 /* Analysis menu can launch external programs or use Web services */
1063 
1064 static QUEUE  urlquerylist = NULL;
1065 
1066 static Int4 pendingqueries = 0;
1067 
SubmitToNCBIResultProc(CONN conn,VoidPtr userdata,EIO_Status status)1068 static Boolean LIBCALLBACK SubmitToNCBIResultProc (CONN conn, VoidPtr userdata, EIO_Status status)
1069 
1070 {
1071   AsnIoPtr     aop;
1072   FILE         *fp;
1073   Char         path [PATH_MAX];
1074   SeqEntryPtr  sep;
1075 
1076   TmpNam (path);
1077   fp = FileOpen (path, "wb");
1078   QUERY_CopyResultsToFile (conn, fp);
1079   FileClose (fp);
1080   aop = AsnIoOpen (path, "rb");
1081   sep = SeqEntryAsnRead (aop, NULL);
1082   AsnIoClose (aop);
1083   aop = AsnIoOpen (path, "w");
1084   SeqEntryAsnWrite (sep, aop, NULL);
1085   AsnIoFlush (aop);
1086   AsnIoClose (aop);
1087   LaunchGeneralTextViewer (path, "Echo binary transformation of Seq-entry");
1088   FileRemove (path);
1089   return TRUE;
1090 }
1091 
SubmitToNCBI(IteM i)1092 extern void SubmitToNCBI (IteM i)
1093 
1094 {
1095   AsnIoPtr     aop;
1096   BaseFormPtr  bfp;
1097   CONN         conn;
1098   FILE         *fp;
1099   Char         path [PATH_MAX];
1100   Char         progname [64];
1101   SeqEntryPtr  sep;
1102 
1103 #ifdef WIN_MAC
1104   bfp = currentFormDataPtr;
1105 #else
1106   bfp = GetObjectExtra (i);
1107 #endif
1108   if (bfp == NULL) return;
1109   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1110   if (sep == NULL) return;
1111 
1112   sprintf (progname, "Sequin/%s", SEQUIN_APPLICATION);
1113 
1114   TmpNam (path);
1115 
1116   aop = AsnIoOpen (path, "wb");
1117   SeqEntryAsnWrite (sep, aop, NULL);
1118   AsnIoFlush (aop);
1119   AsnIoClose (aop);
1120 
1121   conn = QUERY_OpenUrlQuery ("cruncher.nlm.nih.gov", 0,
1122                              "/cgi-bin/Sequin/testcgi.cgi", "request=echo",
1123                              progname, 30, eMIME_T_NcbiData, eMIME_AsnBinary,
1124                              eENCOD_Url,
1125                              fHCC_UrlDecodeInput | fHCC_UrlEncodeOutput);
1126 
1127   fp = FileOpen (path, "rb");
1128   QUERY_CopyFileToQuery (conn, fp);
1129   FileClose (fp);
1130 
1131   QUERY_SendQuery (conn);
1132 
1133   QUERY_AddToQueue (&urlquerylist, conn, SubmitToNCBIResultProc, NULL, TRUE);
1134 
1135   pendingqueries++;
1136 
1137   FileRemove (path);
1138 }
1139 
1140 static QUEUE  cddquerylist = NULL;
1141 
1142 static Int2  cddquerynum = 0;
1143 
1144 #include <cddapi.h>
1145 
1146 #define CDD_EXPECT_VALUE 0.01
1147 
CddProc(CONN conn,VoidPtr userdata,EIO_Status status)1148 static Boolean LIBCALLBACK CddProc (
1149   CONN conn,
1150   VoidPtr userdata,
1151   EIO_Status status
1152 )
1153 
1154 {
1155   BioseqPtr    bsp;
1156   SeqAnnotPtr  prev;
1157   SeqAnnotPtr  sap;
1158 
1159   if (conn == NULL || userdata == NULL) return TRUE;
1160   if (status != eIO_Success) return TRUE;
1161   sap = CddReadReply (conn, status);
1162   if (sap == NULL) return FALSE;
1163 
1164   bsp = (BioseqPtr) userdata;
1165   CddCorrectIDs (bsp, sap);
1166 
1167   prev = bsp->annot;
1168   if (prev == NULL) {
1169     bsp->annot = sap;
1170   } else {
1171     while (prev->next != NULL) {
1172       prev = prev->next;
1173     }
1174     prev->next = sap;
1175   }
1176 
1177   ObjMgrSetDirtyFlag (bsp->idx.entityID, TRUE);
1178   ObjMgrSendMsg (OM_MSG_UPDATE, bsp->idx.entityID, 0, 0);
1179 
1180   return TRUE;
1181 }
1182 
SearchCDD(BioseqPtr bsp,Pointer userdata)1183 static void SearchCDD (BioseqPtr bsp, Pointer userdata)
1184 
1185 {
1186   BoolPtr  dofeats;
1187 
1188   if (bsp == NULL) return;
1189   if (! ISA_aa (bsp->mol)) return;
1190 
1191   dofeats = (BoolPtr) userdata;
1192   if (! CddAsynchronousQuery (bsp, CDD_EXPECT_VALUE, TRUE, TRUE, *dofeats, "cdd", FALSE, &cddquerylist, CddProc, (Pointer) bsp)) {
1193     ErrPostEx (SEV_ERROR, 0, 0, "Unable to run CDD search");
1194   } else {
1195     cddquerynum++;
1196   }
1197 }
1198 
1199 /*
1200 static void SearchCDD (BioseqPtr bsp, Pointer userdata)
1201 
1202 {
1203   BoolPtr      dofeats;
1204   SeqAnnotPtr  prev;
1205   SeqAnnotPtr  sap;
1206 
1207   if (bsp == NULL) return;
1208   if (! ISA_aa (bsp->mol)) return;
1209 
1210   dofeats = (BoolPtr) userdata;
1211   sap = CddSynchronousQuery (bsp, CDD_EXPECT_VALUE, TRUE, TRUE, *dofeats, "cdd", FALSE);
1212   if (sap == NULL) return;
1213   CddCorrectIDs (bsp, sap);
1214 
1215   prev = bsp->annot;
1216   if (prev == NULL) {
1217     bsp->annot = sap;
1218   } else {
1219     while (prev->next != NULL) {
1220       prev = prev->next;
1221     }
1222     prev->next = sap;
1223   }
1224 }
1225 */
1226 
SimpleCDDSearchCommonProc(IteM i,Boolean makeFeats)1227 static void SimpleCDDSearchCommonProc (IteM i, Boolean makeFeats)
1228 
1229 {
1230   BaseFormPtr  bfp;
1231   Boolean      dofeats;
1232   SeqEntryPtr  sep;
1233 
1234 #ifdef WIN_MAC
1235   bfp = currentFormDataPtr;
1236 #else
1237   bfp = GetObjectExtra (i);
1238 #endif
1239   if (bfp == NULL) return;
1240   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1241   if (sep == NULL) return;
1242 
1243   WatchCursor ();
1244   Update ();
1245 
1246   if (makeFeats) {
1247     FreeCDDRegions (sep);
1248   } else {
1249     FreeCDDAligns (sep);
1250   }
1251 
1252   dofeats = makeFeats;
1253   VisitBioseqsInSep (sep, (Pointer) &dofeats, SearchCDD);
1254 
1255   /*
1256   RemoveDuplicateCDDs (sep);
1257 
1258   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1259   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1260   */
1261   ArrowCursor ();
1262   Update ();
1263  }
1264 
SimpleCDDSearchFeatProc(IteM i)1265 void SimpleCDDSearchFeatProc (IteM i)
1266 
1267 {
1268   SimpleCDDSearchCommonProc (i, TRUE);
1269 }
1270 
SimpleCDDSearchAlignProc(IteM i)1271 void SimpleCDDSearchAlignProc (IteM i)
1272 
1273 {
1274   SimpleCDDSearchCommonProc (i, FALSE);
1275 }
1276 
SequinCheckSocketsProc(void)1277 extern void SequinCheckSocketsProc (void)
1278 
1279 {
1280   Int4  remaining;
1281 
1282   remaining = QUERY_CheckQueue (&urlquerylist);
1283   if (remaining < pendingqueries) {
1284     Beep ();
1285     pendingqueries--;
1286   }
1287   remaining = VecScreenCheckQueue (&vsquerylist);
1288   if (remaining < vsquerynum) {
1289     vsquerynum = remaining;
1290     Message (MSG_POST, "There are %d vector screens remaining", (int) vsquerynum);
1291   }
1292   remaining = QBlastCheckQueue (&qbquerylist);
1293   remaining = CddCheckQueue (&cddquerylist);
1294   if (remaining < cddquerynum) {
1295     cddquerynum = remaining;
1296     Message (MSG_POST, "There are %d cdd searches remaining", (int) cddquerynum);
1297   }
1298 }
1299 
DemoModeResultProc(CONN conn,VoidPtr userdata,EIO_Status status)1300 static Boolean LIBCALLBACK DemoModeResultProc (CONN conn, VoidPtr userdata, EIO_Status status)
1301 
1302 {
1303   FILE  *fp;
1304   Char  path [PATH_MAX];
1305 
1306   TmpNam (path);
1307   fp = FileOpen (path, "w");
1308   QUERY_CopyResultsToFile (conn, fp);
1309   FileClose (fp);
1310   LaunchGeneralTextViewer (path, "QueueFastaQueryToURL results");
1311   FileRemove (path);
1312   return TRUE;
1313 }
1314 
SequinHandleURLResults(CONN conn,VoidPtr userdata,EIO_Status status)1315 static Boolean LIBCALLBACK SequinHandleURLResults (CONN conn, VoidPtr userdata, EIO_Status status)
1316 
1317 {
1318   FILE  *fp;
1319   Char  path [PATH_MAX];
1320 
1321   TmpNam (path);
1322   fp = FileOpen (path, "w");
1323   QUERY_CopyResultsToFile (conn, fp);
1324   FileClose (fp);
1325   if (! SequinHandleNetResults (path)) {
1326     /* LaunchGeneralTextViewer (path, "QueueFastaQueryToURL failed"); */
1327   }
1328   FileRemove (path);
1329   return TRUE;
1330 }
1331 
1332 #define DEBUG_SEQN_BUFLEN 4096
1333 
FinishURLProc(NewObjectPtr nop,CharPtr arguments,CharPtr path)1334 static void FinishURLProc (NewObjectPtr nop, CharPtr arguments, CharPtr path)
1335 
1336 {
1337   Char             buf [DEBUG_SEQN_BUFLEN + 4];
1338   CONN             conn;
1339   size_t           ct;
1340   FILE             *fp, *fpp;
1341   Char             pth [PATH_MAX];
1342   Char             progname [64];
1343   QueryResultProc  resultproc;
1344   EMIME_SubType    subtype;
1345 
1346   sprintf (progname, "Sequin/%s", SEQUIN_APPLICATION);
1347 
1348   if (nop->demomode) {
1349     resultproc = DemoModeResultProc;
1350   } else {
1351     resultproc = nop->resultproc;
1352   }
1353   if (nop->format == 1) {
1354     subtype = eMIME_Fasta;
1355   } else if (nop->format == 2) {
1356     subtype = eMIME_AsnText;
1357   } else {
1358     subtype = eMIME_Unknown;
1359   }
1360 
1361   conn = QUERY_OpenUrlQuery (nop->host_machine, nop->host_port,
1362                              nop->host_path, arguments,
1363                              progname, nop->timeoutsec,
1364                              eMIME_T_NcbiData, subtype, eENCOD_Url,
1365                              fHCC_UrlDecodeInput | fHCC_UrlEncodeOutput);
1366   if (conn == NULL) return;
1367 
1368   fp = FileOpen (path, "r");
1369   QUERY_CopyFileToQuery (conn, fp);
1370   FileClose (fp);
1371 
1372   QUERY_SendQuery (conn);
1373 
1374   QUERY_AddToQueue (&urlquerylist, conn, resultproc, NULL, TRUE);
1375 
1376   pendingqueries++;
1377 
1378   if (nop->demomode) {
1379     TmpNam (pth);
1380     fpp = FileOpen (pth, "w");
1381     fprintf (fpp, "%s\n", nop->host_machine);
1382     fprintf (fpp, "%s\n", nop->host_path);
1383     fprintf (fpp, "%s\n", arguments);
1384     fp = FileOpen (path, "r");
1385     if (fp != NULL) {
1386       while ((ct = FileRead (buf, 1, DEBUG_SEQN_BUFLEN, fp)) > 0) {
1387         FileWrite (buf, 1, ct, fpp);
1388       }
1389       fprintf (fpp, "\n");
1390       FileClose (fp);
1391     }
1392     FileClose (fpp);
1393     LaunchGeneralTextViewer (pth, "QueueFastaQueryToURL request");
1394     FileRemove (pth);
1395   }
1396 }
1397 
DoAnalysisProc(NewObjectPtr nop,BaseFormPtr bfp,Int2 which,CharPtr arguments,ResultProc dotheanalysis)1398 static void DoAnalysisProc (NewObjectPtr nop, BaseFormPtr bfp, Int2 which, CharPtr arguments, ResultProc dotheanalysis)
1399 
1400 {
1401   AsnIoPtr     aop;
1402   BioseqPtr    bsp;
1403   Char         path1 [PATH_MAX];
1404   SeqEntryPtr  sep;
1405 
1406   if (nop == NULL || bfp == NULL) return;
1407   switch (which) {
1408     case 1 :
1409       if (BioseqViewCanSaveFasta (bfp->form, nop->fastaNucOK, nop->fastaProtOK, nop->onlyBspTarget)) {
1410         TmpNam (path1);
1411         switch (nop->format) {
1412           case 1 :
1413             ExportBioseqViewFasta (bfp->form, path1, nop->fastaNucOK, nop->fastaProtOK, nop->onlyBspTarget);
1414             break;
1415           case 2 :
1416             sep = NULL;
1417             if (nop->onlyBspTarget) {
1418               bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
1419               sep = SeqMgrGetSeqEntryForData (bsp);
1420             } else {
1421               sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1422             }
1423             if (sep != NULL) {
1424               aop = AsnIoOpen (path1, "w");
1425               SeqEntryAsnWrite (sep, aop, NULL);
1426               AsnIoFlush (aop);
1427               AsnIoClose (aop);
1428             }
1429             break;
1430           default :
1431             break;
1432         }
1433         if (dotheanalysis != NULL) {
1434           dotheanalysis (path1);
1435         } else {
1436           FinishURLProc (nop, arguments, path1);
1437         }
1438         FileRemove (path1);
1439       } else {
1440         ErrPostEx (SEV_ERROR, 0, 0, "BioseqView cannot save fasta format");
1441       }
1442       break;
1443     case 2 :
1444       /*
1445       if (DocSumCanSaveFasta (bfp->form, nop->fastaNucOK, nop->fastaProtOK)) {
1446         TmpNam (path1);
1447         ExportDocSumFasta (bfp->form, path1, nop->fastaNucOK, nop->fastaProtOK);
1448         if (dotheanalysis != NULL) {
1449           dotheanalysis (path1);
1450         } else {
1451           FinishURLProc (nop, arguments, path1);
1452         }
1453         FileRemove (path1);
1454       } else {
1455         ErrPostEx (SEV_ERROR, 0, 0, "DocSum cannot save fasta format");
1456       }
1457       */
1458       ErrPostEx (SEV_ERROR, 0, 0, "DocSum cannot save fasta format");
1459       break;
1460     default :
1461       break;
1462   }
1463 }
1464 
1465 /* encodes spaces as %20 in URLs */
StrSaveNoNullEncodeSpaces(CharPtr from)1466 static CharPtr StrSaveNoNullEncodeSpaces (CharPtr from)
1467 
1468 {
1469   Char     ch;
1470   size_t   len = 0;
1471   CharPtr  p;
1472   CharPtr  q;
1473   CharPtr  to;
1474 
1475   if (StringHasNoText (from)) return NULL;
1476   p = from;
1477   ch = *p;
1478   while (ch != '\0') {
1479     if (ch == ' ') {
1480       len += 3;
1481     } else {
1482       len++;
1483     }
1484     p++;
1485     ch = *p;
1486   }
1487   to = MemNew (len + 1);
1488   if (to == NULL) return NULL;
1489 
1490   q = to;
1491   p = from;
1492   ch = *p;
1493   while (ch != '\0') {
1494     if (ch == ' ') {
1495       *q = '%';
1496       q++;
1497       *q = '2';
1498       q++;
1499       *q = '0';
1500       q++;
1501     } else {
1502       *q = ch;
1503       q++;
1504     }
1505     p++;
1506     ch = *p;
1507   }
1508   *q = '\0';
1509   return to;
1510 }
1511 
1512 typedef struct urlargform {
1513   FORM_MESSAGE_BLOCK
1514 
1515   NewObjectPtr nop;
1516   BaseFormPtr  bfp;
1517   ValNodePtr   controls;
1518   ValNodePtr   helps;
1519   Int2         which;
1520 } UrlArgForm, PNTR UrlArgFormPtr;
1521 
AcceptArgumentFormProc(ButtoN b)1522 static void AcceptArgumentFormProc (ButtoN b)
1523 
1524 {
1525   CharPtr        args = NULL;
1526   CharPtr        arguments = NULL;
1527   ButtoN         btn;
1528   Char           ch;
1529   Int2           choice;
1530   Char           cpy [256];
1531   GrouP          grp;
1532   ValNodePtr     head = NULL;
1533   Int2           i;
1534   CharPtr        itms;
1535   CharPtr        last;
1536   size_t         len;
1537   LisT           lst;
1538   NewObjectPtr   nop;
1539   Boolean        notFirst = FALSE;
1540   PopuP          pop;
1541   ValNodePtr     ppt;
1542   CharPtr        ptr;
1543   CharPtr        str;
1544   Char           tmp [256];
1545   TexT           txt;
1546   UrlArgFormPtr  ufp;
1547   UrlParamPtr    upp;
1548   Int2           val;
1549   ValNodePtr     vnp;
1550 
1551   ufp = (UrlArgFormPtr) GetObjectExtra (b);
1552   if (ufp == NULL) return;
1553   Hide (ufp->form);
1554   Update ();
1555   nop = ufp->nop;
1556   if (nop != NULL) {
1557     if (! StringHasNoText (nop->prefix)) {
1558       ValNodeCopyStr (&head, 0, nop->prefix);
1559     }
1560     for (vnp = ufp->controls, ppt = nop->paramlist;
1561          vnp != NULL && ppt != NULL;
1562          vnp = vnp->next, ppt = ppt->next) {
1563       upp = (UrlParamPtr) ppt->data.ptrvalue;
1564       if (upp == NULL) continue;
1565       choice = vnp->choice;
1566       switch (upp->type) {
1567         case 1 :
1568           txt = (TexT) vnp->data.ptrvalue;
1569           str = SaveStringFromText (txt);
1570           if (str != NULL) {
1571             sprintf (tmp, "%s=%s", upp->param, str);
1572             ValNodeCopyStr (&head, ppt->choice, tmp);
1573             MemFree (str);
1574           }
1575           break;
1576         case 2 :
1577           btn = (ButtoN) vnp->data.ptrvalue;
1578           if (GetStatus (btn)) {
1579             sprintf (tmp, "%s=TRUE", upp->param);
1580           } else {
1581             sprintf (tmp, "%s=FALSE", upp->param);
1582           }
1583           ValNodeCopyStr (&head, ppt->choice, tmp);
1584           break;
1585         case 3 :
1586           pop = (PopuP) vnp->data.ptrvalue;
1587           val = GetValue (pop);
1588           if (val > 0) {
1589             i = 0;
1590             itms = upp->choices;
1591             StringNCpy_0 (tmp, itms, sizeof (tmp));
1592             last = tmp;
1593             ptr = last;
1594             ch = *ptr;
1595             while (ch != '\0') {
1596               if (ch == ',') {
1597                 *ptr = '\0';
1598                 i++;
1599                 if (val == i) {
1600                   sprintf (cpy, "%s=%s", upp->param, last);
1601                   ValNodeCopyStr (&head, ppt->choice, cpy);
1602                 }
1603                 ptr++;
1604                 last = ptr;
1605                 ch = *ptr;
1606               } else {
1607                 ptr++;
1608                 ch = *ptr;
1609               }
1610             }
1611             if (! StringHasNoText (last)) {
1612               i++;
1613               if (val == i) {
1614                 sprintf (cpy, "%s=%s", upp->param, last);
1615                 ValNodeCopyStr (&head, ppt->choice, cpy);
1616               }
1617             }
1618           }
1619           break;
1620         case 4 :
1621           grp = (GrouP) vnp->data.ptrvalue;
1622           val = GetValue (grp);
1623           if (val > 0) {
1624             i = 0;
1625             itms = upp->choices;
1626             StringNCpy_0 (tmp, itms, sizeof (tmp));
1627             last = tmp;
1628             ptr = last;
1629             ch = *ptr;
1630             while (ch != '\0') {
1631               if (ch == ',') {
1632                 *ptr = '\0';
1633                 i++;
1634                 if (val == i) {
1635                   sprintf (cpy, "%s=%s", upp->param, last);
1636                   ValNodeCopyStr (&head, ppt->choice, cpy);
1637                 }
1638                 ptr++;
1639                 last = ptr;
1640                 ch = *ptr;
1641               } else {
1642                 ptr++;
1643                 ch = *ptr;
1644               }
1645             }
1646             if (! StringHasNoText (last)) {
1647               i++;
1648               if (val == i) {
1649                 sprintf (cpy, "%s=%s", upp->param, last);
1650                 ValNodeCopyStr (&head, ppt->choice, cpy);
1651               }
1652             }
1653           }
1654           break;
1655         case 5 :
1656           lst = (LisT) vnp->data.ptrvalue;
1657           val = GetValue (lst);
1658           if (val > 0) {
1659             i = 0;
1660             itms = upp->choices;
1661             StringNCpy_0 (tmp, itms, sizeof (tmp));
1662             last = tmp;
1663             ptr = last;
1664             ch = *ptr;
1665             while (ch != '\0') {
1666               if (ch == ',') {
1667                 *ptr = '\0';
1668                 i++;
1669                 if (val == i) {
1670                   sprintf (cpy, "%s=%s", upp->param, last);
1671                   ValNodeCopyStr (&head, ppt->choice, cpy);
1672                 }
1673                 ptr++;
1674                 last = ptr;
1675                 ch = *ptr;
1676               } else {
1677                 ptr++;
1678                 ch = *ptr;
1679               }
1680             }
1681             if (! StringHasNoText (last)) {
1682               i++;
1683               if (val == i) {
1684                 sprintf (cpy, "%s=%s", upp->param, last);
1685                 ValNodeCopyStr (&head, ppt->choice, cpy);
1686               }
1687             }
1688           }
1689           break;
1690         default :
1691           break;
1692       }
1693     }
1694     head = SortValNode (head, SortByVnpChoice);
1695     if (! StringHasNoText (nop->suffix)) {
1696       ValNodeCopyStr (&head, 0, nop->suffix);
1697     }
1698     for (len = 0, vnp = head; vnp != NULL; vnp = vnp->next) {
1699       len += StringLen ((CharPtr) vnp->data.ptrvalue) + 1;
1700     }
1701     if (len > 0) {
1702       arguments = MemNew (len + 5);
1703       if (arguments != NULL) {
1704         vnp = head;
1705         notFirst = FALSE;
1706         while (vnp != NULL) {
1707           if (notFirst) {
1708             StringCat (arguments, "&");
1709           }
1710           StringCat (arguments, (CharPtr) vnp->data.ptrvalue);
1711           notFirst = TRUE;
1712           vnp = vnp->next;
1713         }
1714       }
1715     }
1716     args = /* StrSaveNoNullEncodeSpaces */ StringSave (arguments);
1717     MemFree (arguments);
1718     DoAnalysisProc (nop, ufp->bfp, ufp->which, args, NULL);
1719     MemFree (args);
1720   }
1721   Remove (ufp->form);
1722 }
1723 
ShowArgumentHelp(ButtoN b)1724 static void ShowArgumentHelp (ButtoN b)
1725 
1726 {
1727   NewObjectPtr   nop;
1728   ValNodePtr     ppt;
1729   CharPtr        str;
1730   UrlArgFormPtr  ufp;
1731   UrlParamPtr    upp;
1732   ValNodePtr     vnp;
1733 
1734   ufp = (UrlArgFormPtr) GetObjectExtra (b);
1735   if (ufp == NULL) return;
1736   nop = ufp->nop;
1737   if (nop == NULL) return;
1738   for (vnp = ufp->helps, ppt = nop->paramlist;
1739          vnp != NULL && ppt != NULL;
1740          vnp = vnp->next, ppt = ppt->next) {
1741     upp = (UrlParamPtr) ppt->data.ptrvalue;
1742     if (upp == NULL) continue;
1743     if ((Pointer) b == (Pointer) vnp->data.ptrvalue) {
1744       str = upp->help;
1745       Message (MSG_OK, "%s", str);
1746       return;
1747     }
1748   }
1749   Beep ();
1750 }
1751 
ArgumentFormMessage(ForM f,Int2 mssg)1752 static void ArgumentFormMessage (ForM f, Int2 mssg)
1753 
1754 {
1755   UrlArgFormPtr  ufp;
1756 
1757   ufp = (UrlArgFormPtr) GetObjectExtra (f);
1758   if (ufp != NULL) {
1759     switch (mssg) {
1760       case VIB_MSG_CLOSE :
1761         Remove (f);
1762         break;
1763       default :
1764         if (ufp->appmessage != NULL) {
1765           ufp->appmessage (f, mssg);
1766         }
1767         break;
1768     }
1769   }
1770 }
1771 
CleanupArgumentForm(GraphiC g,VoidPtr data)1772 static void CleanupArgumentForm (GraphiC g, VoidPtr data)
1773 
1774 {
1775   UrlArgFormPtr  ufp;
1776 
1777   ufp = (UrlArgFormPtr) data;
1778   if (ufp != NULL) {
1779     ValNodeFree (ufp->controls);
1780     ValNodeFree (ufp->helps);
1781   }
1782   StdCleanupFormProc (g, data);
1783 }
1784 
RearrangeParamList(ValNodePtr paramlist)1785 static ValNodePtr RearrangeParamList (ValNodePtr paramlist)
1786 
1787 {
1788   ValNodePtr       curr;
1789   CharPtr          group;
1790   ValNodePtr       head = NULL;
1791   ValNodePtr       list;
1792   ValNodePtr       next;
1793   ValNodePtr PNTR  prev;
1794   ValNodePtr       ppt;
1795   UrlParamPtr      upp;
1796 
1797   ppt = paramlist;
1798   while (ppt != NULL) {
1799     list = ppt->next;
1800     ppt->next = NULL;
1801     ValNodeLink (&head, ppt);
1802     upp = (UrlParamPtr) ppt->data.ptrvalue;
1803     if (upp == NULL) {
1804       ppt = list;
1805       continue;
1806     }
1807     group = upp->group;
1808     curr = list;
1809     prev = &list;
1810     while (curr != NULL) {
1811       next = curr->next;
1812       upp = (UrlParamPtr) curr->data.ptrvalue;
1813       if (upp == NULL) {
1814         prev = &(curr->next);
1815         curr = next;
1816         continue;
1817       }
1818       if (StringICmp (upp->group, group) == 0) {
1819         *prev = next;
1820         curr->next = NULL;
1821         ValNodeLink (&head, curr);
1822       } else {
1823         prev = &(curr->next);
1824       }
1825       curr = next;
1826     }
1827     ppt = list;
1828   }
1829   return head;
1830 }
1831 
BuildArgumentForm(NewObjectPtr nop,BaseFormPtr bfp,Int2 which)1832 static void BuildArgumentForm (NewObjectPtr nop, BaseFormPtr bfp, Int2 which)
1833 
1834 {
1835   ButtoN             b;
1836   ButtoN             btn;
1837   GrouP              c;
1838   Char               ch;
1839   CharPtr            def;
1840   Int2               delta;
1841   TexT               first = NULL;
1842   GrouP              g;
1843   GrouP              grp;
1844   GrouP              h;
1845   ValNodePtr         hlp;
1846   Int2               i;
1847   CharPtr            itms;
1848   CharPtr            last;
1849   CharPtr            lastGroup = " ";
1850   LisT               lst;
1851   GrouP              m;
1852   Int2               max;
1853   Int2               min;
1854   ValNodePtr         moveMe = NULL;
1855   Nlm_Handle         obj1, obj2;
1856   PopuP              pop;
1857   PrompT             prmpt;
1858   ValNodePtr         ppt;
1859   CharPtr            ptr;
1860   RecT               r;
1861   StdEditorProcsPtr  sepp;
1862   CharPtr            str;
1863   Char               tmp [128];
1864   TexT               txt;
1865   UrlArgFormPtr      ufp;
1866   UrlParamPtr        upp;
1867   Int2               val;
1868   ValNodePtr         vnp;
1869   WindoW             w;
1870 
1871   if (nop == NULL || bfp == NULL) return;
1872   ufp = (UrlArgFormPtr) MemNew (sizeof (UrlArgForm));
1873   if (ufp == NULL) return;
1874 
1875   nop->paramlist = RearrangeParamList (nop->paramlist);
1876 
1877   w = FixedWindow (-50, -33, -10, -10, "Arguments", NULL);
1878   SetObjectExtra (w, ufp, CleanupArgumentForm);
1879   ufp->form = (ForM) w;
1880   ufp->formmessage = ArgumentFormMessage;
1881 
1882   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
1883   if (sepp != NULL) {
1884     SetActivate (w, sepp->activateForm);
1885     ufp->appmessage = sepp->handleMessages;
1886   }
1887 
1888   ufp->bfp = bfp;
1889   ufp->nop = nop;
1890   ufp->which = which;
1891 
1892   m = HiddenGroup (w, 1, 0, NULL);
1893 
1894   g = NULL;
1895   for (ppt = nop->paramlist;
1896        ppt != NULL;
1897        ppt = ppt->next) {
1898     upp = (UrlParamPtr) ppt->data.ptrvalue;
1899     if (upp == NULL) continue;
1900     if (StringICmp (upp->group, lastGroup) != 0) {
1901       if (StringHasNoText (upp->group)) {
1902         if (StringHasNoText (lastGroup)) {
1903           g = HiddenGroup (m, 3, 0, NULL);
1904         } else {
1905           g = NormalGroup (m, 3, 0, "", programFont, NULL);
1906         }
1907       } else {
1908         g = NormalGroup (m, 3, 0, upp->group, programFont, NULL);
1909       }
1910       lastGroup = upp->group;
1911     }
1912     if (g == NULL) {
1913       g = HiddenGroup (m, 3, 0, NULL);
1914     }
1915     switch (upp->type) {
1916       case 1 :
1917         str = upp->prompt;
1918         StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
1919         def = upp->dfault;
1920         if (StringHasNoText (def)) {
1921           def = "";
1922         }
1923         txt = DialogText (g, def, 10, NULL);
1924         if (first == NULL) {
1925           first = txt;
1926         }
1927         ValNodeAddPointer (&(ufp->controls), 1, (Pointer) txt);
1928         ValNodeAddPointer (&moveMe, 0, (Pointer) txt);
1929         b = PushButton (g, "?", ShowArgumentHelp);
1930         SetObjectExtra (b, ufp, NULL);
1931         ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1932         break;
1933       case 2 :
1934         str = upp->prompt;
1935         btn = CheckBox (g, str, NULL);
1936         def = upp->dfault;
1937         if (StringICmp (def, "TRUE") == 0) {
1938           SetStatus (btn, TRUE);
1939         }
1940         prmpt = StaticPrompt (g, "", 0, 0, programFont, 'l');
1941         ValNodeAddPointer (&moveMe, 0, (Pointer) prmpt);
1942         ValNodeAddPointer (&(ufp->controls), 2, (Pointer) btn);
1943         b = PushButton (g, "?", ShowArgumentHelp);
1944         SetObjectExtra (b, ufp, NULL);
1945         ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1946         break;
1947       case 3 :
1948         str = upp->prompt;
1949         StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
1950         h = HiddenGroup (g, 1, 0, NULL);
1951         pop = PopupList (h, TRUE, NULL);
1952         def = upp->dfault;
1953         val = 0;
1954         i = 0;
1955         itms = upp->choices;
1956         StringNCpy_0 (tmp, itms, sizeof (tmp));
1957         last = tmp;
1958         ptr = last;
1959         ch = *ptr;
1960         while (ch != '\0') {
1961           if (ch == ',') {
1962             *ptr = '\0';
1963             PopupItem (pop, last);
1964             i++;
1965             if (StringICmp (def, last) == 0) {
1966               val = i;
1967             }
1968             ptr++;
1969             last = ptr;
1970             ch = *ptr;
1971           } else {
1972             ptr++;
1973             ch = *ptr;
1974           }
1975         }
1976         if (! StringHasNoText (last)) {
1977           PopupItem (pop, last);
1978           i++;
1979           if (StringICmp (def, last) == 0) {
1980             val = i;
1981           }
1982         }
1983         if (val > 0) {
1984           SetValue (pop, val);
1985         }
1986         ValNodeAddPointer (&(ufp->controls), 3, (Pointer) pop);
1987         ValNodeAddPointer (&moveMe, 0, (Pointer) pop);
1988         b = PushButton (g, "?", ShowArgumentHelp);
1989         SetObjectExtra (b, ufp, NULL);
1990         ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1991         break;
1992       case 4 :
1993         str = upp->prompt;
1994         StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
1995         h = HiddenGroup (g, 1, 0, NULL);
1996         grp = HiddenGroup (h, -5, 0, NULL);
1997         def = upp->dfault;
1998         val = 0;
1999         i = 0;
2000         itms = upp->choices;
2001         StringNCpy_0 (tmp, itms, sizeof (tmp));
2002         last = tmp;
2003         ptr = last;
2004         ch = *ptr;
2005         while (ch != '\0') {
2006           if (ch == ',') {
2007             *ptr = '\0';
2008             RadioButton (grp, last);
2009             i++;
2010             if (StringICmp (def, last) == 0) {
2011               val = i;
2012             }
2013             ptr++;
2014             last = ptr;
2015             ch = *ptr;
2016           } else {
2017             ptr++;
2018             ch = *ptr;
2019           }
2020         }
2021         if (! StringHasNoText (last)) {
2022           RadioButton (grp, last);
2023           i++;
2024           if (StringICmp (def, last) == 0) {
2025             val = i;
2026           }
2027         }
2028         if (val > 0) {
2029           SetValue (grp, val);
2030         }
2031         ValNodeAddPointer (&(ufp->controls), 4, (Pointer) grp);
2032         ValNodeAddPointer (&moveMe, 0, (Pointer) grp);
2033         b = PushButton (g, "?", ShowArgumentHelp);
2034         SetObjectExtra (b, ufp, NULL);
2035         ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
2036         break;
2037       case 5 :
2038         str = upp->prompt;
2039         StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
2040         h = HiddenGroup (g, 1, 0, NULL);
2041         lst = SingleList (h, 10, 3, NULL);
2042         def = upp->dfault;
2043         val = 0;
2044         i = 0;
2045         itms = upp->choices;
2046         StringNCpy_0 (tmp, itms, sizeof (tmp));
2047         last = tmp;
2048         ptr = last;
2049         ch = *ptr;
2050         while (ch != '\0') {
2051           if (ch == ',') {
2052             *ptr = '\0';
2053             ListItem (lst, last);
2054             i++;
2055             if (StringICmp (def, last) == 0) {
2056               val = i;
2057             }
2058             ptr++;
2059             last = ptr;
2060             ch = *ptr;
2061           } else {
2062             ptr++;
2063             ch = *ptr;
2064           }
2065         }
2066         if (! StringHasNoText (last)) {
2067           ListItem (lst, last);
2068           i++;
2069           if (StringICmp (def, last) == 0) {
2070             val = i;
2071           }
2072         }
2073         if (val > 0) {
2074           SetValue (lst, val);
2075         }
2076         ValNodeAddPointer (&(ufp->controls), 5, (Pointer) lst);
2077         ValNodeAddPointer (&moveMe, 0, (Pointer) lst);
2078         b = PushButton (g, "?", ShowArgumentHelp);
2079         SetObjectExtra (b, ufp, NULL);
2080         ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
2081         break;
2082       default :
2083         break;
2084     }
2085   }
2086 
2087   min = 0;
2088   max = 0;
2089   for (vnp = moveMe; vnp != NULL; vnp = vnp->next) {
2090     obj1 = (Nlm_Handle) vnp->data.ptrvalue;
2091     GetPosition (obj1, &r);
2092     min = MAX (min, r.left);
2093   }
2094   for (vnp = moveMe; vnp != NULL; vnp = vnp->next) {
2095     obj1 = (Nlm_Handle) vnp->data.ptrvalue;
2096     GetPosition (obj1, &r);
2097     delta = min - r.left;
2098     OffsetRect (&r, delta, 0);
2099     SetPosition (obj1, &r);
2100     AdjustPrnt (obj1, &r, FALSE);
2101     max = MAX (max, r.right);
2102   }
2103   max += 3;
2104   for (vnp = moveMe, hlp = ufp->helps;
2105        vnp != NULL && hlp != NULL;
2106        vnp = vnp->next, hlp = hlp->next) {
2107     obj2 = (Nlm_Handle) hlp->data.ptrvalue;
2108     GetPosition (obj2, &r);
2109     delta = max - r.left;
2110     OffsetRect (&r, delta, 0);
2111     SetPosition (obj2, &r);
2112     AdjustPrnt (obj2, &r, TRUE);
2113   }
2114 
2115   c = HiddenGroup (w, 2, 0, NULL);
2116   SetGroupSpacing (c, 10, 3);
2117   b = DefaultButton (c, "Accept", AcceptArgumentFormProc);
2118   SetObjectExtra (b, ufp, NULL);
2119   PushButton (c, "Cancel", StdCancelButtonProc);
2120 
2121   AlignObjects (ALIGN_CENTER, (HANDLE) m, (HANDLE) c, NULL);
2122   RealizeWindow (w);
2123   Show (w);
2124   Select (w);
2125   if (first != NULL) {
2126     Select (first);
2127   }
2128 }
2129 
DoURLProc(IteM i)2130 static void DoURLProc (IteM i)
2131 
2132 {
2133   CharPtr       args = NULL;
2134   BaseFormPtr   bfp;
2135   size_t        len;
2136   NewObjectPtr  nop;
2137   Int2          which;
2138 
2139   nop = (NewObjectPtr) GetObjectExtra (i);
2140   if (nop == NULL) return;
2141 #ifdef WIN_MAC
2142   bfp = (BaseFormPtr) currentFormDataPtr;
2143 #else
2144   bfp = nop->bfp;
2145 #endif
2146   if (bfp == NULL) return;
2147   which = BioseqViewOrDocSumChoice (nop);
2148   if (nop->paramlist == NULL) {
2149     len = StringLen (nop->prefix) + StringLen (nop->suffix);
2150     if (len > 0) {
2151       args = MemNew (sizeof (Char) * (len + 2));
2152       StringCpy (args, nop->prefix);
2153       if (! StringHasNoText (nop->suffix)) {
2154         StringCat (args, "&");
2155         StringCat (args, nop->suffix);
2156       }
2157     }
2158     DoAnalysisProc (nop, bfp, which, args, NULL);
2159   } else {
2160     BuildArgumentForm (nop, bfp, which);
2161   }
2162 }
2163 
EnableAnalysisItems(BaseFormPtr bfp,Boolean isDocSum)2164 extern void EnableAnalysisItems (BaseFormPtr bfp, Boolean isDocSum)
2165 
2166 {
2167   Boolean       hasFastaNuc;
2168   Boolean       hasFastaProt;
2169   NewObjectPtr  nop;
2170 
2171   if (bfp == NULL) return;
2172 #ifdef WIN_MAC
2173   nop = (NewObjectPtr) macUserDataPtr;
2174 #else
2175   nop = (NewObjectPtr) bfp->userDataPtr;
2176 #endif
2177   if (isDocSum) {
2178   } else {
2179   }
2180   while (nop != NULL) {
2181     if (nop->kind == 1) {
2182       /* annotate menu item, ignore it */
2183     } else if (isDocSum) {
2184       if (nop->dsmOK) {
2185         /*
2186         hasFastaNuc = DocSumCanSaveFasta (bfp->form, TRUE, FALSE);
2187         hasFastaProt = DocSumCanSaveFasta (bfp->form, FALSE, TRUE);
2188         if (nop->fastaNucOK && hasFastaNuc) {
2189           SafeEnable (nop->item);
2190         } else if (nop->fastaProtOK && hasFastaProt) {
2191           SafeEnable (nop->item);
2192         } else {
2193           SafeDisable (nop->item);
2194         }
2195         */
2196         SafeDisable (nop->item);
2197       } else {
2198         SafeDisable (nop->item);
2199       }
2200     } else {
2201       if (nop->bspOK) {
2202         hasFastaNuc = BioseqViewCanSaveFasta (bfp->form, TRUE, FALSE, nop->onlyBspTarget);
2203         hasFastaProt = BioseqViewCanSaveFasta (bfp->form, FALSE, TRUE, nop->onlyBspTarget);
2204         if (nop->fastaNucOK && hasFastaNuc) {
2205           SafeEnable (nop->item);
2206         } else if (nop->fastaProtOK && hasFastaProt) {
2207           SafeEnable (nop->item);
2208         } else {
2209           SafeDisable (nop->item);
2210         }
2211       } else {
2212         SafeDisable (nop->item);
2213       }
2214     }
2215     nop = nop->next;
2216   }
2217 }
2218 
LinkNewObjectLists(NewObjectPtr list1,NewObjectPtr list2)2219 static VoidPtr LinkNewObjectLists (NewObjectPtr list1, NewObjectPtr list2)
2220 
2221 {
2222   NewObjectPtr  nop;
2223 
2224   if (list1 == NULL) return list2;
2225   nop = list1;
2226   while (nop->next != NULL) {
2227     nop = nop->next;
2228   }
2229   nop->next = list2;
2230   return list1;
2231 }
2232 
CleanupAnalysisExtraProc(GraphiC g,VoidPtr data)2233 static void CleanupAnalysisExtraProc (GraphiC g, VoidPtr data)
2234 
2235 {
2236   NewObjectPtr  nop;
2237   ValNodePtr    ppt;
2238   UrlParamPtr   upp;
2239 
2240   nop = (NewObjectPtr) data;
2241   if (nop != NULL) {
2242     MemFree (nop->host_machine);
2243     MemFree (nop->host_path);
2244     for (ppt = nop->paramlist; ppt != NULL; ppt = ppt->next) {
2245       upp = (UrlParamPtr) ppt->data.ptrvalue;
2246       if (upp == NULL) continue;
2247       MemFree (upp->param);
2248       MemFree (upp->prompt);
2249       MemFree (upp->dfault);
2250       MemFree (upp->choices);
2251       MemFree (upp->group);
2252       MemFree (upp->help);
2253     }
2254     ValNodeFreeData (nop->paramlist);
2255     MemFree (nop->prefix);
2256     MemFree (nop->suffix);
2257   }
2258   MemFree (data);
2259 }
2260 
2261 typedef struct sbstruc {
2262   CharPtr    name;
2263   MenU       menu;
2264 } Sbstruc, PNTR SbstrucPtr;
2265 
2266 static ValNodePtr  analysissubmenulist = NULL;
2267 
AddAnalysisItem(MenU m,BaseFormPtr bfp,Boolean bspviewOK,Boolean docsumOK,Boolean nucOK,Boolean protOK,Boolean onlyBspTarget,CharPtr host_machine,Uint2 host_port,CharPtr host_path,CharPtr program,Uint2 timeoutsec,Int2 format,Boolean demomode,QueryResultProc resultproc,ValNodePtr paramlist,CharPtr prefix,CharPtr suffix,CharPtr title,CharPtr submenu,ItmActnProc actn,NewObjectPtr PNTR head)2268 static void AddAnalysisItem (MenU m, BaseFormPtr bfp,
2269                              Boolean bspviewOK, Boolean docsumOK,
2270                              Boolean nucOK, Boolean protOK, Boolean onlyBspTarget,
2271                              CharPtr host_machine, Uint2 host_port,
2272                              CharPtr host_path, CharPtr program,
2273                              Uint2 timeoutsec, Int2 format, Boolean demomode,
2274                              QueryResultProc resultproc, ValNodePtr paramlist,
2275                              CharPtr prefix, CharPtr suffix,
2276                              CharPtr title, CharPtr submenu,
2277                              ItmActnProc actn, NewObjectPtr PNTR head)
2278 
2279 {
2280   IteM          i;
2281   NewObjectPtr  last;
2282   size_t        len;
2283   NewObjectPtr  nop;
2284   SbstrucPtr    sbp;
2285   CharPtr       tmp;
2286   ValNodePtr    vnp;
2287   MenU          x;
2288 
2289   if (m == NULL || actn == NULL) return;
2290   x = NULL;
2291   if (! StringHasNoText (submenu)) {
2292     vnp = analysissubmenulist;
2293     while (vnp != NULL && x == NULL) {
2294       sbp = (SbstrucPtr) vnp->data.ptrvalue;
2295       if (sbp != NULL && StringICmp (sbp->name, submenu) == 0) {
2296         x = sbp->menu;
2297       }
2298       vnp = vnp->next;
2299     }
2300     if (x == NULL) {
2301       sbp = (SbstrucPtr) MemNew (sizeof (Sbstruc));
2302       if (sbp != NULL) {
2303         sbp->name = StringSave (submenu);
2304         sbp->menu = SubMenu (m, sbp->name);
2305         x = sbp->menu;
2306         ValNodeAddPointer (&analysissubmenulist, 0, (VoidPtr) sbp);
2307       }
2308     }
2309   }
2310   if (x == NULL) {
2311     x = m;
2312   }
2313   i = CommandItem (x, title, actn);
2314   nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
2315   if (nop != NULL) {
2316     nop->kind = 2; /* analysis menu item */
2317     nop->bfp = bfp;
2318     nop->item = i;
2319     nop->bspOK = bspviewOK;
2320     nop->dsmOK = docsumOK;
2321     nop->fastaNucOK = nucOK;
2322     nop->fastaProtOK = protOK;
2323     nop->onlyBspTarget = onlyBspTarget;
2324     nop->host_machine = /* StrSaveNoNullEncodeSpaces */ StringSave (host_machine);
2325     nop->host_port = host_port;
2326     len = StringLen (host_path);
2327     tmp = MemNew (len + StringLen (program) + 5);
2328     if (tmp != NULL) {
2329       StringCpy (tmp, host_path);
2330       if (len > 1 && tmp [len - 1] != '/') {
2331         StringCat (tmp, "/");
2332       }
2333       StringCat (tmp, program);
2334     }
2335     nop->host_path = /* StrSaveNoNullEncodeSpaces */ StringSave (tmp);
2336     MemFree (tmp);
2337     nop->query = NULL;
2338     /*
2339     nop->host_path = StrSaveNoNullEncodeSpaces (host_path);
2340     nop->query = StrSaveNoNullEncodeSpaces (program);
2341     */
2342     nop->timeoutsec = timeoutsec;
2343     nop->format = format;
2344     nop->demomode = demomode;
2345     nop->resultproc = resultproc;
2346     nop->paramlist = paramlist;
2347     nop->prefix = StringSaveNoNull (prefix);
2348     nop->suffix = StringSaveNoNull (suffix);
2349   }
2350   SetObjectExtra (i, (Pointer) nop, CleanupAnalysisExtraProc);
2351   if (head == NULL) return;
2352   last = *head;
2353   if (last != NULL) {
2354     while (last->next != NULL) {
2355      last = last->next;
2356     }
2357     last->next = nop;
2358   } else {
2359     *head = nop;
2360   }
2361 }
2362 
2363 /* Sample seqncgis.cnf/seqncgis.ini/.seqncgisrc/sequincgi.cfg config file.
2364    PATH can contain query (separated by ? symbol), or separate QUERY item can
2365    be used, or multiple QUERY and TITLE items can also be used.
2366 
2367 [SERVICES]
2368 PATH=mydisk:Common Files:services:
2369 
2370 [ORDER]
2371 ORDER_1=tRNAscan
2372 ORDER_2=Seg
2373 
2374 [tRNAscan]
2375 PROGRAM=testcgi.cgi?request=trnascan
2376 HOST=www.myserver.myschool.edu
2377 PORT=80
2378 PATH=/MyServices/cgi-bin/testcgi.cgi
2379 SUBMENU=Search
2380 FORMATIN=FASTA
2381 FLAGS=SEQ,NUC,TRG
2382 TIMEOUT=30
2383 
2384 [Seg]
2385 PROGRAM=segify
2386 HOST=www.myserver.myschool.edu
2387 PORT=80
2388 PATH=/MyServices/cgi-bin/testcgi.cgi
2389 FORMATIN=fasta
2390 FLAGS=SEQ,DOC,PRT,TRG
2391 SUBMENU=Secondary structure prediction
2392 PROMPT_1=Window Size
2393 PARAM_1=window
2394 DESCRIPTION_1=window size for determining low-complexity segments
2395 TYPE_1=text
2396 DEFAULT_1=12
2397 REQUIRED_1=FALSE
2398 IMPORTANCE_1=
2399 GROUP_1=Algorithm
2400 HELP_1=window size for determining low-complexity segments
2401 PROMPT_2=Trigger Complexity
2402 PARAM_2=trigger
2403 DESCRIPTION_2=trigger complexity for determining low-complexity segments
2404 TYPE_2=text
2405 DEFAULT_2=2.2
2406 REQUIRED_2=FALSE
2407 IMPORTANCE_2=
2408 GROUP_2=Algorithm
2409 HELP_2=trigger complexity for determining low-complexity segments
2410 ...
2411 
2412 [ENZYMES]
2413 ENZ_1=BamHI
2414 ENZ_2=EcoRI
2415 ENZ_3=HindIII
2416 
2417 */
2418 
GetServiceParam(ValNodePtr head,CharPtr type,CharPtr buf,Int2 buflen)2419 static Int2 GetServiceParam (ValNodePtr head, CharPtr type, CharPtr buf, Int2 buflen)
2420 
2421 {
2422   size_t      len;
2423   Boolean     seenBracket = FALSE;
2424   CharPtr     str;
2425   ValNodePtr  vnp;
2426 
2427   if (buf == NULL || buflen <= 0) return 0;
2428   *buf = '\0';
2429   len = StringLen (type);
2430   for (vnp = head; vnp != NULL; vnp = vnp->next) {
2431     str = (CharPtr) vnp->data.ptrvalue;
2432     if (str != NULL) {
2433       if (str [0] == '[') {
2434         if (seenBracket) return 0;
2435         seenBracket = TRUE;
2436       } else if (StringNICmp (str, type, len) == 0) {
2437         str += len;
2438         StringNCpy_0 (buf, str, buflen);
2439         return (Int2) StringLen (buf);
2440       }
2441     }
2442   }
2443   return 0;
2444 }
2445 
GetConfigParamAndPromptLists(CharPtr sect)2446 static ValNodePtr GetConfigParamAndPromptLists (CharPtr sect)
2447 
2448 {
2449   Int2         i;
2450   ValNodePtr   paramlist = NULL;
2451   Uint1        paramtype;
2452   Char         title [512];
2453   Char         tmp [32];
2454   UrlParamPtr  upp;
2455 
2456   if (sect == NULL) return NULL;
2457   i = 1;
2458   sprintf (tmp, "PARAM_%d", (int) i);
2459   while (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2460     upp = (UrlParamPtr) MemNew (sizeof (UrlParamData));
2461     if (upp == NULL) continue;
2462     upp->param = StringSave (title);
2463     sprintf (tmp, "TYPE_%d", (int) i);
2464     paramtype = 1;
2465     if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2466       if (StringICmp (title, "text") == 0) {
2467         paramtype = 1;
2468       } else if (StringICmp (title, "checkbox") == 0) {
2469         paramtype = 2;
2470       } else if (StringICmp (title, "popup") == 0) {
2471         paramtype = 3;
2472       } else if (StringICmp (title, "radio") == 0) {
2473         paramtype = 4;
2474       } else if (StringICmp (title, "list") == 0) {
2475         paramtype = 5;
2476       }
2477     }
2478     upp->type = paramtype;
2479     sprintf (tmp, "PROMPT_%d", (int) i);
2480     if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2481       upp->prompt = StringSave (title);
2482     } else {
2483       upp->prompt = StringSave (upp->param);
2484     }
2485     sprintf (tmp, "DEFAULT_%d", (int) i);
2486     if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2487       upp->dfault = StringSave (title);
2488     } else {
2489       upp->dfault = StringSave (" ");
2490     }
2491     sprintf (tmp, "CHOICES_%d", (int) i);
2492     if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2493       upp->choices = StringSave (title);
2494     } else {
2495       upp->choices = StringSave (" ");
2496     }
2497     sprintf (tmp, "GROUP_%d", (int) i);
2498     if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2499       upp->group = StringSave (title);
2500     } else {
2501       upp->group = StringSave (" ");
2502     }
2503     sprintf (tmp, "HELP_%d", (int) i);
2504     if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2505       upp->help = StringSave (title);
2506     } else {
2507       upp->help = StringSave (" ");
2508     }
2509     ValNodeAddPointer (&paramlist, i, (Pointer) upp);
2510     i++;
2511     sprintf (tmp, "PARAM_%d", (int) i);
2512   }
2513   return paramlist;
2514 }
2515 
GetServiceParamAndPromptLists(ValNodePtr list)2516 static ValNodePtr GetServiceParamAndPromptLists (ValNodePtr list)
2517 
2518 {
2519   Int2         i;
2520   ValNodePtr   paramlist = NULL;
2521   Uint1        paramtype;
2522   Char         title [512];
2523   Char         tmp [32];
2524   UrlParamPtr  upp;
2525 
2526   if (list == NULL) return NULL;
2527   i = 1;
2528   sprintf (tmp, "PARAM_%d=", (int) i);
2529   while (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2530     upp = (UrlParamPtr) MemNew (sizeof (UrlParamData));
2531     if (upp == NULL) continue;
2532     upp->param = StringSave (title);
2533     sprintf (tmp, "TYPE_%d", (int) i);
2534     paramtype = 1;
2535     if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2536       if (StringICmp (title, "text") == 0) {
2537         paramtype = 1;
2538       } else if (StringICmp (title, "checkbox") == 0) {
2539         paramtype = 2;
2540       } else if (StringICmp (title, "popup") == 0) {
2541         paramtype = 3;
2542       } else if (StringICmp (title, "radio") == 0) {
2543         paramtype = 4;
2544       } else if (StringICmp (title, "list") == 0) {
2545         paramtype = 5;
2546       }
2547     }
2548     upp->type = paramtype;
2549     sprintf (tmp, "PROMPT_%d=", (int) i);
2550     if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2551       upp->prompt = StringSave (title);
2552     } else {
2553       upp->prompt = StringSave (upp->param);
2554     }
2555     sprintf (tmp, "DEFAULT_%d=", (int) i);
2556     if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2557       upp->dfault = StringSave (title);
2558     } else {
2559       upp->dfault = StringSave (" ");
2560     }
2561     sprintf (tmp, "CHOICES_%d=", (int) i);
2562     if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2563       upp->choices = StringSave (title);
2564     } else {
2565       upp->choices = StringSave (" ");
2566     }
2567     sprintf (tmp, "GROUP_%d=", (int) i);
2568     if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2569       upp->group = StringSave (title);
2570     } else {
2571       upp->group = StringSave (" ");
2572     }
2573     sprintf (tmp, "HELP_%d=", (int) i);
2574     if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2575       upp->help = StringSave (title);
2576     } else {
2577       upp->help = StringSave (" ");
2578     }
2579     ValNodeAddPointer (&paramlist, i, (Pointer) upp);
2580     i++;
2581     sprintf (tmp, "PARAM_%d=", (int) i);
2582   }
2583   return paramlist;
2584 }
2585 
ReadAnalysisConfigFile(CharPtr sect,MenU m,BaseFormPtr bfp,Boolean bspviewOK,Boolean docsumOK,NewObjectPtr PNTR head)2586 static void ReadAnalysisConfigFile (CharPtr sect, MenU m, BaseFormPtr bfp,
2587                                     Boolean bspviewOK, Boolean docsumOK,
2588                                     NewObjectPtr PNTR head)
2589 
2590 {
2591   Boolean     demomode = FALSE;
2592   Int2        format = 1;
2593   Char        host [128];
2594   Boolean     nucOK = FALSE;
2595   Boolean     onlyBspTarget = FALSE;
2596   ValNodePtr  paramlist = NULL;
2597   Char        program [128];
2598   Char        path [256];
2599   Uint2       port = 80;
2600   Char        prefix [128];
2601   Boolean     protOK = FALSE;
2602   Char        submenu [128];
2603   Char        suffix [128];
2604   Uint2       timeoutsec = 30;
2605   Char        title [128];
2606   Char        tmp [32];
2607   unsigned    int  val;
2608 
2609   if (! GetAppParam ("SEQNCGIS", sect, "TITLE", NULL, title, sizeof (title) - 1)) {
2610     StringNCpy_0 (title, sect, sizeof (title));
2611   }
2612   if (GetAppParam ("SEQNCGIS", sect, "HOST", NULL, host, sizeof (host) - 1)) {
2613     if (GetAppParam ("SEQNCGIS", sect, "FLAGS", NULL, tmp, sizeof (tmp) - 1)) {
2614       if (StringStr (tmp, "SEQ") == NULL) {
2615         bspviewOK = FALSE;
2616       }
2617       if (StringStr (tmp, "DOC") == NULL) {
2618         docsumOK = FALSE;
2619       }
2620       if (StringStr (tmp, "NUC") != NULL) {
2621         nucOK = TRUE;
2622       }
2623       if (StringStr (tmp, "PRT") != NULL) {
2624         protOK = TRUE;
2625       }
2626       if (StringStr (tmp, "TRG") != NULL) {
2627         onlyBspTarget = TRUE;
2628       }
2629     }
2630 
2631     if ((! bspviewOK) && (! docsumOK)) return;
2632 
2633     if (GetAppParam ("SEQNCGIS", sect, "PORT", NULL, tmp, sizeof (tmp) - 1) &&
2634         sscanf (tmp, "%u", &val) == 1) {
2635       port = (Uint2) val;
2636     } else {
2637       port = 80;
2638     }
2639     if (GetAppParam ("SEQNCGIS", sect, "FORMATIN", NULL, tmp, sizeof (tmp) - 1)) {
2640       if (StringICmp (tmp, "FASTA") == 0) {
2641         format = 1;
2642       } else if (StringICmp (tmp, "ASN.1") == 0) {
2643         format = 2;
2644       }
2645     }
2646     if (GetAppParam ("SEQNCGIS", sect, "TIMEOUT", NULL, tmp, sizeof (tmp) - 1) &&
2647         sscanf (tmp, "%u", &val) == 1) {
2648       timeoutsec = (Uint2) val;
2649     } else {
2650       timeoutsec = 30;
2651     }
2652     submenu [0] = '\0';
2653     GetAppParam ("SEQNCGIS", sect, "SUBMENU", NULL, submenu, sizeof (submenu) - 1);
2654     if (GetAppParam ("SEQNCGIS", sect, "DEMO", NULL, tmp, sizeof (tmp) - 1)) {
2655       if (StringICmp (tmp, "TRUE") == 0) {
2656         demomode = TRUE;
2657       }
2658     }
2659 
2660     if (GetAppParam ("SEQNCGIS", sect, "PATH", NULL, path, sizeof (path) - 1)) {
2661       if (GetAppParam ("SEQNCGIS", sect, "PROGRAM", NULL, program, sizeof (program) - 1)) {
2662         paramlist = GetConfigParamAndPromptLists (sect);
2663         prefix [0] = '\0';
2664         GetAppParam ("SEQNCGIS", sect, "PREFIX", NULL, prefix, sizeof (prefix) - 1);
2665         suffix [0] = '\0';
2666         GetAppParam ("SEQNCGIS", sect, "SUFFIX", NULL, suffix, sizeof (suffix) - 1);
2667         AddAnalysisItem (m, bfp, bspviewOK, docsumOK,
2668                          nucOK, protOK, onlyBspTarget,
2669                          host, port, path, program, timeoutsec, format, demomode,
2670                          SequinHandleURLResults, paramlist, prefix, suffix,
2671                          title, submenu, DoURLProc, head);
2672       }
2673     }
2674   }
2675 }
2676 
ReadServiceConfigFile(CharPtr pathbase,ValNodePtr config,MenU m,BaseFormPtr bfp,Boolean bspviewOK,Boolean docsumOK,NewObjectPtr PNTR head)2677 static void ReadServiceConfigFile (CharPtr pathbase, ValNodePtr config,
2678                                    MenU m, BaseFormPtr bfp,
2679                                    Boolean bspviewOK, Boolean docsumOK,
2680                                    NewObjectPtr PNTR head)
2681 
2682 {
2683   Char          ch;
2684   Boolean       demomode = FALSE;
2685   Int2          format = 1;
2686   FILE          *fp;
2687   Boolean       goOn = TRUE;
2688   Char          host [128];
2689   Boolean       keepGoing;
2690   ValNodePtr    list = NULL;
2691   Boolean       nucOK = FALSE;
2692   Boolean       onlyBspTarget = FALSE;
2693   ValNodePtr    paramlist = NULL;
2694   Char          program [128];
2695   Char          path [PATH_MAX];
2696   Uint2         port = 0;
2697   Char          prefix [128];
2698   Boolean       protOK = FALSE;
2699   CharPtr       ptr;
2700   Boolean       seenBracket;
2701   Char          str [256];
2702   Char          submenu [128];
2703   Char          suffix [128];
2704   Uint2         timeoutsec = 30;
2705   Char          title [128];
2706   Char          tmp [32];
2707   unsigned int  val;
2708   ValNodePtr    vnp;
2709 
2710   if (path == NULL || config == NULL || config->data.ptrvalue == NULL) return;
2711   StringNCpy_0 (path, pathbase, sizeof (path));
2712   FileBuildPath (path, NULL, (CharPtr) config->data.ptrvalue);
2713   fp = FileOpen (path, "r");
2714   if (fp == NULL) return;
2715   while (FileGets (str, sizeof (str), fp) != NULL) {
2716     ptr = str;
2717     ch = *ptr;
2718     while (ch != '\0' && ch != '\n' && ch != '\r') {
2719       ptr++;
2720       ch = *ptr;
2721     }
2722     *ptr = '\0';
2723     ValNodeCopyStr (&list, 1, str);
2724   }
2725   FileClose (fp);
2726   while (goOn) {
2727     goOn = FALSE;
2728     title [0] = '\0';
2729     if (GetServiceParam (list, "TITLE=", tmp, sizeof (tmp) - 1)) {
2730       StringNCpy_0 (title, tmp, sizeof (title));
2731     }
2732     if (StringHasNoText (title)) {
2733       if (GetServiceParam (list, "[", title, sizeof (title) - 1)) {
2734         ptr = StringChr (title, ']');
2735         if (ptr != NULL) {
2736           *ptr = '\0';
2737         }
2738       }
2739     }
2740     if (title [0] != '\0' && GetServiceParam (list, "HOST=", host, sizeof (host) - 1)) {
2741       if (GetServiceParam (list, "FLAGS=", tmp, sizeof (tmp) - 1)) {
2742         if (StringStr (tmp, "SEQ") == NULL) {
2743           bspviewOK= FALSE;
2744         }
2745         if (StringStr (tmp, "DOC") == NULL) {
2746           docsumOK= FALSE;
2747         }
2748         if (StringStr (tmp, "NUC") != NULL) {
2749           nucOK= TRUE;
2750         }
2751         if (StringStr (tmp, "PRT") != NULL) {
2752           protOK= TRUE;
2753         }
2754         if (StringStr (tmp, "TRG") != NULL) {
2755           onlyBspTarget= TRUE;
2756         }
2757       }
2758 
2759       if (bspviewOK || docsumOK) {
2760 
2761         if (GetServiceParam (list, "PORT=", tmp, sizeof (tmp) - 1) &&
2762             sscanf (tmp, "%u", &val) == 1) {
2763           port = (Uint2) val;
2764         } else {
2765           port = 0;
2766         }
2767         if (GetServiceParam (list, "FORMATIN=", tmp, sizeof (tmp) - 1)) {
2768           if (StringICmp (tmp, "FASTA") == 0) {
2769             format = 1;
2770           } else if (StringICmp (tmp, "ASN.1") == 0) {
2771             format = 2;
2772           }
2773         }
2774        if (GetServiceParam (list, "TIMEOUT=", tmp, sizeof (tmp) - 1) &&
2775             sscanf (tmp, "%u", &val) == 1) {
2776           timeoutsec = (Uint2) val;
2777         } else {
2778           timeoutsec = 30;
2779         }
2780         submenu [0] = '\0';
2781         GetServiceParam (list, "SUBMENU=", submenu, sizeof (submenu) - 1);
2782         if (GetServiceParam (list, "DEMO=", tmp, sizeof (tmp) - 1)) {
2783           if (StringICmp (tmp, "TRUE") == 0) {
2784             demomode = TRUE;
2785           }
2786         }
2787 
2788         if (GetServiceParam (list, "PATH=", path, sizeof (path) - 1)) {
2789           if (GetServiceParam (list, "PROGRAM=", program, sizeof (program) - 1)) {
2790             paramlist = GetServiceParamAndPromptLists (list);
2791             prefix [0] = '\0';
2792             GetServiceParam (list, "PREFIX=", prefix, sizeof (prefix) - 1);
2793             suffix [0] = '\0';
2794             GetServiceParam (list, "SUFFIX=", suffix, sizeof (suffix) - 1);
2795             AddAnalysisItem (m, bfp, bspviewOK, docsumOK,
2796                              nucOK, protOK, onlyBspTarget,
2797                              host, port, path, program, timeoutsec, format, demomode,
2798                              SequinHandleURLResults, paramlist, prefix, suffix,
2799                              title, submenu, DoURLProc, head);
2800           }
2801         }
2802 
2803       }
2804     }
2805 
2806     seenBracket = FALSE;
2807     keepGoing = TRUE;
2808     for (vnp = list; vnp != NULL && keepGoing; vnp = vnp->next) {
2809       ptr = (CharPtr) vnp->data.ptrvalue;
2810       if (ptr != NULL) {
2811         if (ptr [0] == '[') {
2812           if (seenBracket) {
2813             keepGoing = FALSE;
2814           } else {
2815             seenBracket = TRUE;
2816           }
2817         }
2818         if (keepGoing) {
2819           vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
2820         }
2821       }
2822     }
2823 
2824   }
2825 
2826   ValNodeFreeData (list);
2827 }
2828 
CreateAnalysisMenu(WindoW w,BaseFormPtr bfp,Boolean bspviewOK,Boolean docsumOK)2829 extern MenU CreateAnalysisMenu (WindoW w, BaseFormPtr bfp, Boolean bspviewOK, Boolean docsumOK)
2830 
2831 {
2832   NewObjectPtr  first;
2833   ValNodePtr    head1 = NULL, head2 = NULL;
2834   Int2          i;
2835   size_t        len;
2836   MenU          m;
2837   Char          path1 [PATH_MAX];
2838   Char          path2 [PATH_MAX];
2839   CharPtr       ptr;
2840   SbstrucPtr    sbp;
2841   Char          sect [256];
2842   Char          temp [32];
2843   ValNodePtr    vnp;
2844 
2845   ProgramPath (path1, sizeof (path1));
2846   ptr = StringRChr (path1, DIRDELIMCHR);
2847   if (ptr != NULL) {
2848     ptr++;
2849     *ptr = '\0';
2850   }
2851   FileBuildPath (path1, "services", NULL);
2852   head1 = DirCatalog (path1);
2853 
2854   if (GetAppParam ("SEQNCGIS", "SERVICES", "PATH", NULL, path2, sizeof (path2) - 1)) {
2855     len = StringLen (path2);
2856     if (path2 [len - 1] != DIRDELIMCHR) {
2857       StringCat (path2, DIRDELIMSTR);
2858     }
2859     if (StringCmp (path1, path2) != 0) {
2860       head2 = DirCatalog (path2);
2861     }
2862   }
2863 
2864   if ((! extraServices) && (! indexerVersion) && (! genomeCenter) &&
2865       head1 == NULL && head2 == NULL) {
2866     if (! GetAppParam ("SEQNCGIS", "ORDER", NULL, NULL, sect, sizeof (sect) - 1)) {
2867       return NULL;
2868     }
2869   }
2870   m = PulldownMenu (w, "Analysis");
2871   if (m == NULL) return NULL;
2872   analysissubmenulist = NULL;
2873   first = NULL;
2874   if (bspviewOK) {
2875     AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
2876                      NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
2877                      "Restriction Search", "Search",
2878                      SimpleRsiteProc, &first);
2879     if (indexerVersion) {
2880       AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
2881                        NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
2882                        "QBlast Test", "Search",
2883                        SimpleQBlastProc, &first);
2884     }
2885   }
2886   if (bspviewOK || docsumOK) {
2887     if (useEntrez) {
2888       i = 1;
2889       sprintf (temp, "ORDER_%d", (int) i);
2890       while (GetAppParam ("SEQNCGIS", "ORDER", temp, NULL, sect, sizeof (sect) - 1)) {
2891         ReadAnalysisConfigFile (sect, m, bfp, bspviewOK, docsumOK, &first);
2892         i++;
2893         sprintf (temp, "ORDER_%d", (int) i);
2894       }
2895       for (vnp = head1; vnp != NULL; vnp = vnp->next) {
2896         if (vnp->choice == 0) {
2897           ReadServiceConfigFile (path1, vnp, m, bfp, bspviewOK, docsumOK, &first);
2898         }
2899       }
2900       for (vnp = head2; vnp != NULL; vnp = vnp->next) {
2901         if (vnp->choice == 0) {
2902           ReadServiceConfigFile (path2, vnp, m, bfp, bspviewOK, docsumOK, &first);
2903         }
2904       }
2905     }
2906   }
2907   if (bspviewOK) {
2908   }
2909   if (docsumOK) {
2910   }
2911 #ifdef WIN_MAC
2912   macUserDataPtr = LinkNewObjectLists (macUserDataPtr, first);
2913 #else
2914   bfp->userDataPtr = LinkNewObjectLists (bfp->userDataPtr, first);
2915 #endif
2916   for (vnp = analysissubmenulist; vnp != NULL; vnp = vnp->next) {
2917     sbp = (SbstrucPtr) vnp->data.ptrvalue;
2918     if (sbp != NULL) {
2919       sbp->name = MemFree (sbp->name);
2920     }
2921   }
2922   analysissubmenulist = ValNodeFreeData (analysissubmenulist);
2923   ValNodeFreeData (head1);
2924   ValNodeFreeData (head2);
2925   return m;
2926 }
2927 
2928 /* NEW UPDATE SEQUENCE SECTION */
2929 
2930 
2931 #define SQN_LEFT    1
2932 #define SQN_RIGHT   2
2933 #define SQN_MIDDLE  3
2934 
ListPhrapGraphsCallback(SeqGraphPtr sgp,Pointer userdata)2935 static void ListPhrapGraphsCallback (SeqGraphPtr sgp, Pointer userdata)
2936 {
2937   ValNodePtr PNTR vnpp;
2938 
2939   if (sgp == NULL || userdata == NULL) return;
2940   if (StringICmp (sgp->title, "Phrap Quality") == 0)
2941   {
2942     vnpp = (ValNodePtr PNTR) userdata;
2943     ValNodeAddPointer (vnpp, 0, sgp);
2944   }
2945 }
2946 
2947 /* THOUGHTS:
2948  * Can we/must we update quality scores before/after the old Bioseq has been replaced?
2949  * If we replace quality scores after the bioseq has been replaced, the oldbsp->length
2950  * is the length of the buffer we need to hold the quality scores,
2951  * otherwise use the newbsp->length.
2952  * Useful functions:
2953   aln_len = AlnMgr2GetAlnLength(salp, FALSE);
2954 
2955 NLM_EXTERN Int4 AlnMgr2GetNumAlnBlocks(SeqAlignPtr sap)
2956 NLM_EXTERN Boolean AlnMgr2GetNthBlockRange(SeqAlignPtr sap, Int4 n, Int4Ptr start, Int4Ptr stop)
2957 
2958 
2959  * Assumptions: data replacement has already taken place, oldbsp is in row 1 of salp,
2960  *              newbsp is in row 2 of salp.
2961 
2962  */
2963 static Boolean
ReplaceQualityScores(BioseqPtr oldbsp,BioseqPtr newbsp,FILE * log_fp,BoolPtr data_in_log)2964 ReplaceQualityScores
2965 (BioseqPtr   oldbsp,
2966  BioseqPtr   newbsp,
2967  FILE        *log_fp,
2968  BoolPtr     data_in_log)
2969 {
2970   ValNodePtr    oldhead = NULL, newhead = NULL, vnp;
2971   SeqGraphPtr   sgp, last_sgp = NULL, new_sgp;
2972   SeqAnnotPtr   sap, last_sap;
2973   Char          acc_str [256];
2974 
2975   if (oldbsp == NULL || newbsp == NULL
2976       || !ISA_na (oldbsp->mol) || !ISA_na (newbsp->mol))
2977   {
2978     return FALSE;
2979   }
2980 
2981   /* first, remove old scores */
2982   VisitGraphsOnBsp (oldbsp, &oldhead, ListPhrapGraphsCallback);
2983   for (vnp = oldhead; vnp != NULL; vnp = vnp->next)
2984   {
2985     sgp = vnp->data.ptrvalue;
2986     if (sgp != NULL)
2987     {
2988       sgp->idx.deleteme = TRUE;
2989     }
2990   }
2991   oldhead = ValNodeFree (oldhead);
2992   DeleteMarkedObjects (0, OBJ_BIOSEQ, (Pointer) oldbsp);
2993 
2994   /* now copy new quality scores to old sequence */
2995   VisitGraphsOnBsp (newbsp, &newhead, ListPhrapGraphsCallback);
2996 
2997   if (newhead == NULL)
2998   {
2999     if (log_fp != NULL && data_in_log != NULL)
3000     {
3001       SeqIdWrite (oldbsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
3002       fprintf (log_fp, "Quality scores cleared for %s\n", acc_str);
3003       *data_in_log = TRUE;
3004     }
3005   }
3006   else
3007   {
3008     /* now add in new phrap annotations */
3009     last_sap = NULL;
3010     last_sgp = NULL;
3011     for (sap = oldbsp->annot; sap != NULL && sap->type !=3; sap = sap->next)
3012     {
3013       last_sap = sap;
3014     }
3015 
3016     if (sap == NULL)
3017     {
3018       sap = SeqAnnotNew ();
3019       sap->type = 3;
3020       sap->data = NULL;
3021       if (last_sap == NULL)
3022       {
3023         oldbsp->annot = sap;
3024       }
3025       else
3026       {
3027         last_sap->next = sap;
3028       }
3029     }
3030 
3031 
3032     for (sgp = (SeqGraphPtr) sap->data; sgp != NULL; sgp = sgp->next)
3033     {
3034       last_sgp = sgp;
3035     }
3036     for (vnp = newhead; vnp != NULL; vnp = vnp->next)
3037     {
3038       sgp = (SeqGraphPtr) vnp->data.ptrvalue;
3039       if (sgp != NULL)
3040       {
3041         new_sgp = (SeqGraphPtr) AsnIoMemCopy (sgp, (AsnReadFunc) SeqGraphAsnRead, (AsnWriteFunc) SeqGraphAsnWrite);
3042         if (new_sgp != NULL)
3043         {
3044           new_sgp->next = NULL;
3045           if (last_sgp == NULL)
3046           {
3047             sap->data = new_sgp;
3048           }
3049           else
3050           {
3051             last_sgp->next = new_sgp;
3052           }
3053           last_sgp = new_sgp;
3054         }
3055       }
3056     }
3057     SeqIdWrite (oldbsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
3058     fprintf (log_fp, "Replaced quality scores for %s\n", acc_str);
3059     *data_in_log = TRUE;
3060   }
3061 
3062 
3063   return TRUE;
3064 }
3065 
3066 
3067 #define SEQGRAPH_FloatHi    1
3068 #define SEQGRAPH_Int4       2
3069 #define SEQGRAPH_BS         3
3070 
3071 /* remove compression from SeqGraph */
ExpandSeqGraph(SeqGraphPtr sgp)3072 static Boolean ExpandSeqGraph (SeqGraphPtr sgp)
3073 {
3074   Int4    oldpos = 0, newpos = 0, i;
3075   Pointer new_values = NULL;
3076   Int4    new_numval;
3077   Int2    cur_byte;
3078 
3079   if (sgp == NULL || sgp->compr == 0 || sgp->compr == 1) {
3080     return TRUE;
3081   } else if (sgp->compr < 0) {
3082     return FALSE;
3083   }
3084 
3085   new_numval = sgp->numval * sgp->compr;
3086 
3087   /* allocate space for new values */
3088   switch (sgp->flags[2]) {
3089     case SEQGRAPH_FloatHi:
3090       new_values = MemNew (sizeof (FloatHi) * new_numval);
3091       break;
3092     case SEQGRAPH_Int4:
3093       new_values = MemNew (sizeof (Int4) * new_numval);
3094       break;
3095     case SEQGRAPH_BS:
3096       new_values = (Pointer) BSNew (new_numval);
3097       BSSeek ((ByteStorePtr)new_values, 0, SEEK_SET);
3098       BSSeek ((ByteStorePtr) sgp->values, 0, SEEK_SET);
3099       break;
3100   }
3101 
3102   /* copy and expand */
3103   while (oldpos < sgp->numval) {
3104     cur_byte = 0;
3105     if (sgp->flags[2] == SEQGRAPH_BS) {
3106       cur_byte = BSGetByte ((ByteStorePtr) sgp->values);
3107     }
3108     for (i = 0; i < sgp->compr; i++) {
3109       switch (sgp->flags[2]) {
3110         case SEQGRAPH_FloatHi:
3111           ((FloatHiPtr)new_values)[newpos++] = ((FloatHiPtr)sgp->values)[oldpos];
3112           break;
3113         case SEQGRAPH_Int4:
3114           ((Int4Ptr)new_values)[newpos++] = ((Int4Ptr)sgp->values)[oldpos];
3115           break;
3116         case SEQGRAPH_BS:
3117           BSPutByte ((ByteStorePtr) new_values, cur_byte);
3118           break;
3119       }
3120     }
3121     oldpos++;
3122   }
3123 
3124   /* free old values and replace with new */
3125   if (sgp->flags[2] == SEQGRAPH_BS) {
3126     sgp->values = BSFree ((ByteStorePtr) sgp->values);
3127   } else {
3128     sgp->values = MemFree (sgp->values);
3129   }
3130   sgp->values = new_values;
3131   sgp->numval = new_numval;
3132   sgp->compr = 0;
3133 
3134   return TRUE;
3135 }
3136 
TruncateSeqGraphValues(SeqGraphPtr sgp,Int4 len,Boolean onleft)3137 static Boolean TruncateSeqGraphValues (SeqGraphPtr sgp, Int4 len, Boolean onleft)
3138 {
3139   Int4    oldpos, newpos = 0;
3140   Pointer new_values = NULL;
3141   Int4    new_numval;
3142   Int2    cur_byte;
3143   Int4    imin = 0, imax = 0;
3144   FloatHi fmin, fmax;
3145 
3146   if (sgp == NULL) return TRUE;
3147   if (!ExpandSeqGraph (sgp)) return FALSE;
3148 
3149   new_numval = sgp->numval - len;
3150 
3151   /* allocate space for new values */
3152   switch (sgp->flags[2]) {
3153     case SEQGRAPH_FloatHi:
3154       new_values = MemNew (sizeof (FloatHi) * new_numval);
3155       fmin = ((FloatHiPtr)sgp->values)[0];
3156       fmax = fmin;
3157       break;
3158     case SEQGRAPH_Int4:
3159       new_values = MemNew (sizeof (Int4) * new_numval);
3160       imin = ((Int4Ptr)sgp->values)[0];
3161       imax = imin;
3162       break;
3163     case SEQGRAPH_BS:
3164       new_values = (Pointer) BSNew (new_numval);
3165       BSSeek ((ByteStorePtr)new_values, 0, SEEK_SET);
3166       if (onleft) {
3167         BSSeek ((ByteStorePtr) sgp->values, len, SEEK_SET);
3168       } else {
3169         BSSeek ((ByteStorePtr) sgp->values, 0, SEEK_SET);
3170       }
3171       imin = BSGetByte ((ByteStorePtr) sgp->values);
3172       imax = imin;
3173       /* put pointer back */
3174       if (onleft) {
3175         BSSeek ((ByteStorePtr) sgp->values, len, SEEK_SET);
3176       } else {
3177         BSSeek ((ByteStorePtr) sgp->values, 0, SEEK_SET);
3178       }
3179       break;
3180   }
3181 
3182   /* copy */
3183   if (onleft) {
3184     oldpos = len;
3185   } else {
3186     oldpos = 0;
3187   }
3188   while (oldpos < sgp->numval && newpos < new_numval) {
3189       switch (sgp->flags[2]) {
3190         case SEQGRAPH_FloatHi:
3191           ((FloatHiPtr)new_values)[newpos] = ((FloatHiPtr)sgp->values)[oldpos];
3192           if (((FloatHiPtr)new_values)[newpos] > fmax) {
3193             fmax = ((FloatHiPtr)new_values)[newpos];
3194           }
3195           if (((FloatHiPtr)new_values)[newpos] < fmin) {
3196             fmin = ((FloatHiPtr)new_values)[newpos];
3197           }
3198           break;
3199         case SEQGRAPH_Int4:
3200           ((Int4Ptr)new_values)[newpos] = ((Int4Ptr)sgp->values)[oldpos];
3201           if (((Int4Ptr)new_values)[newpos] > imax) {
3202             imax = ((Int4Ptr)new_values)[newpos];
3203           }
3204           if (((Int4Ptr)new_values)[newpos] < imin) {
3205             imin = ((Int4Ptr)new_values)[newpos];
3206           }
3207           break;
3208         case SEQGRAPH_BS:
3209           cur_byte = BSGetByte ((ByteStorePtr) sgp->values);
3210           BSPutByte ((ByteStorePtr) new_values, cur_byte);
3211           if (cur_byte > imax) {
3212             imax = cur_byte;
3213           }
3214           if (cur_byte < imin) {
3215             imin = cur_byte;
3216           }
3217           break;
3218     }
3219     oldpos++;
3220     newpos++;
3221   }
3222 
3223   /* free old values and replace with new */
3224   if (sgp->flags[2] == SEQGRAPH_BS) {
3225     sgp->values = BSFree ((ByteStorePtr) sgp->values);
3226   } else {
3227     sgp->values = MemFree (sgp->values);
3228   }
3229   sgp->values = new_values;
3230   sgp->numval = new_numval;
3231 
3232   /* replace mins and maxes */
3233   if (sgp->flags[2] == SEQGRAPH_FloatHi) {
3234     sgp->max.realvalue = fmax;
3235     sgp->min.realvalue = fmin;
3236   } else {
3237     sgp->max.intvalue = imax;
3238     sgp->min.intvalue = imin;
3239   }
3240   return TRUE;
3241 }
3242 
3243 
3244 
3245 /* assume Bioseq has already been trimmed - length of old Bioseq was trim5 + bsp->length + trim3 */
3246 static Boolean
TrimQualityScoresForSequenceUpdate(BioseqPtr bsp,Int4 trim5,Int4 trim3,FILE * log_fp,BoolPtr data_in_log)3247 TrimQualityScoresForSequenceUpdate
3248 (BioseqPtr bsp,
3249  Int4      trim5,
3250  Int4      trim3,
3251  FILE      *log_fp,
3252  BoolPtr   data_in_log)
3253 {
3254   ValNodePtr    score_list = NULL, vnp;
3255   SeqGraphPtr   sgp;
3256   SeqIntPtr     sip;
3257   Int4          left, right;
3258   Boolean       rval = FALSE;
3259   Char          acc_str [256];
3260 
3261   if (bsp == NULL) return FALSE;
3262 
3263   VisitGraphsOnBsp (bsp, &score_list, ListPhrapGraphsCallback);
3264   if (score_list == NULL) return FALSE;
3265 
3266   for (vnp = score_list; vnp != NULL; vnp = vnp->next) {
3267     sgp = vnp->data.ptrvalue;
3268     if (sgp != NULL && sgp->loc != NULL && sgp->loc->choice == SEQLOC_INT) {
3269       sip = (SeqIntPtr) sgp->loc->data.ptrvalue;
3270       /* trim on right */
3271       if (sip->from > trim5 + bsp->length) {
3272         sgp->idx.deleteme = TRUE;
3273         rval = TRUE;
3274       } else if (sip->to > trim5 + bsp->length - 1) {
3275         right = sip->to - trim5 - bsp->length + 1;
3276         sip->to = trim5 + bsp->length - 1;
3277         TruncateSeqGraphValues (sgp, right, FALSE);
3278         rval = TRUE;
3279       }
3280 
3281       sip->from -= trim5;
3282       sip->to -= trim5;
3283       if (sip->to < 0) {
3284         sgp->idx.deleteme = TRUE;
3285         rval = TRUE;
3286       } else if (sip->from < 0) {
3287         left = 0 - sip->from;
3288         sip->from = 0;
3289         TruncateSeqGraphValues (sgp, left, TRUE);
3290         rval = TRUE;
3291       }
3292     }
3293   }
3294 
3295   if (rval && log_fp != NULL && data_in_log != NULL) {
3296     SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
3297     fprintf (log_fp, "Quality scores trimmed for %s\n", acc_str);
3298     *data_in_log = TRUE;
3299   }
3300   return rval;
3301 }
3302 
3303 
AdjustAlignment(UpsDataPtr udp,Int2 choice)3304 static Boolean AdjustAlignment (
3305   UpsDataPtr udp,
3306   Int2 choice
3307 )
3308 
3309 {
3310   DenseSegPtr  dsp;
3311   Int2         j;
3312   SeqAlignPtr  sap;
3313 
3314   if (udp == NULL) return FALSE;
3315 
3316   sap = udp->salp;
3317   if (sap == NULL) return FALSE;
3318   AMFreeAllIndexes (sap);
3319 
3320   if (sap->segtype == SAS_DENSEG) {
3321     dsp = (DenseSegPtr) sap->segs;
3322 
3323     switch (choice) {
3324       case 2 :
3325         /* adjust alignment 5' */
3326         if (dsp != NULL && dsp->lens != NULL && dsp->numseg > 0) {
3327           dsp->lens [dsp->numseg - 1] += udp->old3;
3328         }
3329         break;
3330       case 3 :
3331         /* adjust alignment 3' */
3332         if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
3333           dsp->lens [0] += udp->old5;
3334           dsp->starts [0] = 0;
3335           dsp->starts [1] = 0;
3336           for (j = 1; j < dsp->numseg; j++) {
3337             if (dsp->starts [1 + j * 2] != -1) {
3338               dsp->starts [1 + j * 2] += udp->old5 - udp->new5;
3339             }
3340           }
3341         }
3342         break;
3343       case 4 :
3344         /* adjust alignment patch */
3345         if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
3346           dsp->lens [dsp->numseg - 1] += udp->old3;
3347           dsp->lens [0] += udp->old5;
3348           dsp->starts [0] = 0;
3349           dsp->starts [1] = 0;
3350           for (j = 1; j < dsp->numseg; j++) {
3351             if (dsp->starts [1 + j * 2] != -1) {
3352               dsp->starts [1 + j * 2] += udp->old5 - udp->new5;
3353             }
3354           }
3355         }
3356         break;
3357       default :
3358         break;
3359     }
3360   }
3361 
3362   AlnMgr2IndexSingleChildSeqAlign (sap);
3363 
3364   return TRUE;
3365 }
3366 
OffsetLoc(SeqLocPtr slp,Int4 offset,SeqIdPtr sip)3367 static void OffsetLoc (SeqLocPtr slp, Int4 offset, SeqIdPtr sip)
3368 
3369 {
3370   PackSeqPntPtr  psp;
3371   SeqIntPtr      sinp;
3372   SeqPntPtr      spp;
3373   Uint1          used;
3374 
3375   if (slp == NULL) return;
3376   switch (slp->choice) {
3377     case SEQLOC_INT :
3378       sinp = (SeqIntPtr) slp->data.ptrvalue;
3379       if (sinp != NULL) {
3380         sinp->from += offset;
3381         sinp->to += offset;
3382         if (sip != NULL) {
3383           sinp->id = SeqIdFree (sinp->id);
3384           sinp->id = SeqIdDup (sip);
3385         }
3386       }
3387       break;
3388     case SEQLOC_PNT :
3389       spp = (SeqPntPtr) slp->data.ptrvalue;
3390       if (spp != NULL) {
3391         spp->point += offset;
3392         if (sip != NULL) {
3393           spp->id = SeqIdFree (spp->id);
3394           spp->id = SeqIdDup (sip);
3395         }
3396       }
3397       break;
3398     case SEQLOC_PACKED_PNT :
3399       psp = (PackSeqPntPtr) slp->data.ptrvalue;
3400       if (psp != NULL) {
3401         for (used = 0; used < psp->used; used++) {
3402           psp->pnts [used] += offset;
3403         }
3404         if (sip != NULL) {
3405           psp->id = SeqIdFree (psp->id);
3406           psp->id = SeqIdDup (sip);
3407         }
3408       }
3409       break;
3410     default :
3411       break;
3412   }
3413 }
3414 
OffsetLocation(SeqLocPtr loc,Int4 offset,SeqIdPtr sip)3415 extern void OffsetLocation (SeqLocPtr loc, Int4 offset, SeqIdPtr sip)
3416 
3417 {
3418   SeqLocPtr  slp;
3419 
3420   slp = SeqLocFindNext (loc, NULL);
3421   while (slp != NULL) {
3422     OffsetLoc (slp, offset, sip);
3423     slp = SeqLocFindNext (loc, slp);
3424   }
3425 }
3426 
PromoteSeqId(SeqIdPtr sip,Pointer userdata)3427 static void PromoteSeqId (SeqIdPtr sip, Pointer userdata)
3428 
3429 {
3430   SeqIdPtr  bestid, newid, oldid;
3431 
3432   bestid = (SeqIdPtr) userdata;
3433 
3434   newid = SeqIdDup (bestid);
3435   if (newid == NULL) return;
3436 
3437   oldid = ValNodeNew (NULL);
3438   if (oldid == NULL) return;
3439 
3440   MemCopy (oldid, sip, sizeof (ValNode));
3441   oldid->next = NULL;
3442 
3443   sip->choice = newid->choice;
3444   sip->data.ptrvalue = newid->data.ptrvalue;
3445 
3446   SeqIdFree (oldid);
3447   ValNodeFree (newid);
3448 
3449   SeqIdStripLocus (sip);
3450 }
3451 
CorrectFeatureSeqIds(SeqFeatPtr sfp,Pointer userdata)3452 static void CorrectFeatureSeqIds (
3453   SeqFeatPtr sfp,
3454   Pointer userdata
3455 )
3456 
3457 {
3458   VisitSeqIdsInSeqLoc (sfp->location, userdata, PromoteSeqId);
3459 }
3460 
DoFeaturePropWithOffset(UpsDataPtr udp,Int4 offset,SeqAnnotPtr PNTR sapp,Boolean patch)3461 static Boolean DoFeaturePropWithOffset (
3462   UpsDataPtr udp,
3463   Int4 offset,
3464   SeqAnnotPtr PNTR sapp,
3465   Boolean patch
3466 )
3467 
3468 {
3469   BioseqPtr          bsp, newbsp, oldbsp;
3470   CodeBreakPtr       cbp;
3471   SeqMgrFeatContext  context;
3472   CdRegionPtr        crp;
3473   SeqFeatPtr         dup, sfp, last = NULL;
3474   Uint2              entityID;
3475   Boolean            keepProteinIDs;
3476   SeqEntryPtr        newsep, prdsep, top;
3477   RnaRefPtr          rrp;
3478   SeqAnnotPtr        sap = NULL, saptmp;
3479   SeqDescrPtr        sdp;
3480   SeqIdPtr           sip;
3481   tRNAPtr            trp;
3482 
3483   if (udp == NULL) return FALSE;
3484 
3485   SeqEntrySetScope (NULL);
3486 
3487   sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &context);
3488   if (sfp == NULL) return FALSE;
3489 
3490   if (udp->diffOrgs) {
3491     keepProteinIDs = FALSE;
3492   } else {
3493     keepProteinIDs = GetStatus (udp->keepProteinIDs);
3494   }
3495 
3496   oldbsp = udp->oldbsp;
3497 
3498   entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
3499   top = GetBestTopParentForData (entityID, udp->oldbsp);
3500 
3501   sdp = ExtractBioSourceAndPubs (top);
3502 
3503   sip = SeqIdFindBest (oldbsp->id, 0);
3504 
3505   while (sfp != NULL) {
3506 
3507     if ((! patch) || (context.right >= udp->new5 && context.left <= udp->new5 + udp->newa)) {
3508 
3509     dup = AsnIoMemCopy ((Pointer) sfp,
3510                         (AsnReadFunc) SeqFeatAsnRead,
3511                         (AsnWriteFunc) SeqFeatAsnWrite);
3512 
3513     if (last == NULL) {
3514       sap = SeqAnnotNew ();
3515       if (oldbsp->annot == NULL) {
3516         oldbsp->annot = sap;
3517       } else {
3518         for (saptmp = oldbsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
3519         saptmp->next = sap;
3520       }
3521       sap->type = 1;
3522       sap->data = (Pointer) dup;
3523     } else {
3524       last->next = dup;
3525     }
3526     last = dup;
3527 
3528     /*
3529     sep = SeqMgrGetSeqEntryForData (oldbsp);
3530     CreateNewFeature (sep, NULL, dup->data.choice, dup);
3531     */
3532 
3533     OffsetLocation (dup->location, offset, sip);
3534     switch (dup->data.choice) {
3535       case SEQFEAT_CDREGION :
3536         crp = (CdRegionPtr) dup->data.value.ptrvalue;
3537         if (crp != NULL) {
3538           for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
3539             OffsetLocation (cbp->loc, offset, sip);
3540           }
3541         }
3542         break;
3543       case SEQFEAT_RNA :
3544         rrp = (RnaRefPtr) dup->data.value.ptrvalue;
3545         if (rrp != NULL && rrp->ext.choice == 2) {
3546           trp = (tRNAPtr) rrp->ext.value.ptrvalue;
3547           if (trp != NULL && trp->anticodon != NULL) {
3548             OffsetLocation (trp->anticodon, offset, sip);
3549           }
3550         }
3551         break;
3552       default :
3553         break;
3554     }
3555     if (dup->product != NULL) {
3556       SeqEntrySetScope (NULL);
3557       bsp = BioseqFindFromSeqLoc (dup->product);
3558       if (bsp != NULL) {
3559         prdsep = SeqMgrGetSeqEntryForData (bsp);
3560         if (prdsep != NULL) {
3561           newsep = AsnIoMemCopy ((Pointer) prdsep,
3562                                  (AsnReadFunc) SeqEntryAsnRead,
3563                                  (AsnWriteFunc) SeqEntryAsnWrite);
3564           if (newsep != NULL) {
3565             if (IS_Bioseq (newsep)) {
3566               newbsp = (BioseqPtr) newsep->data.ptrvalue;
3567               if (newbsp != NULL) {
3568                 if (! keepProteinIDs) {
3569                   newbsp->id = SeqIdSetFree (newbsp->id);
3570                   newbsp->id = MakeNewProteinSeqId (NULL, sip);
3571                   newbsp->hist = SeqHistFree (newbsp->hist);
3572                   VisitFeaturesOnBsp (newbsp, (Pointer) newbsp->id, CorrectFeatureSeqIds);
3573                   SetSeqFeatProduct (dup, newbsp);
3574                   /*
3575                   dup->product = SeqLocFree (dup->product);
3576                   dup->product = CreateWholeInterval (newsep);
3577                   */
3578                 }
3579                 SeqMgrReplaceInBioseqIndex (newbsp);
3580               }
3581             }
3582             AddSeqEntryToSeqEntry (top, newsep, TRUE);
3583           }
3584         }
3585       }
3586     }
3587     }
3588 
3589     sfp = SeqMgrGetNextFeature (udp->newbsp, sfp, 0, 0, &context);
3590   }
3591 
3592   ReplaceBioSourceAndPubs (top, sdp);
3593 
3594   if (sapp != NULL) {
3595     *sapp = sap;
3596   }
3597 
3598   return TRUE;
3599 }
3600 
LengthForNewSequence(UpsDataPtr udp)3601 static Int4 LengthForNewSequence (UpsDataPtr udp)
3602 {
3603   Int4 new_len = 0;
3604 
3605   if (udp == NULL)
3606   {
3607     return 0;
3608   }
3609   else if (GetValue (udp->sfb) == UPDATE_FEATURES_ONLY)
3610   {
3611     new_len = udp->oldbsp->length;
3612   }
3613   else if (udp->rmcval == UPDATE_PATCH)
3614   {
3615     new_len = udp->old5 + udp->newa + udp->old3;
3616   }
3617   else if (udp->rmcval == UPDATE_REPLACE)
3618   {
3619     new_len = udp->new5 + udp->newa + udp->new3;
3620   }
3621   else if (udp->rmcval == UPDATE_EXTEND5)
3622   {
3623     new_len = udp->new5 + udp->olda + udp->old3;
3624   }
3625   else if (udp->rmcval == UPDATE_EXTEND3)
3626   {
3627     new_len = udp->old5 + udp->olda + udp->new3;
3628   }
3629   return new_len;
3630 }
3631 
3632 static SeqLocPtr
GetPropagatedLocation(SeqLocPtr orig_loc,BioseqPtr newbsp,BioseqPtr oldbsp,Int4 new_len,SeqAlignPtr salp)3633 GetPropagatedLocation
3634 (SeqLocPtr   orig_loc,
3635  BioseqPtr   newbsp,
3636  BioseqPtr   oldbsp,
3637  Int4        new_len,
3638  SeqAlignPtr salp)
3639 {
3640   SeqLocPtr tmp_loc, new_loc;
3641   Boolean   split;
3642 
3643   tmp_loc = SeqLocCopy (orig_loc);
3644   ReplaceComplexLocation (tmp_loc, salp, new_len, 2, 1);
3645 
3646   new_loc = SeqLocCopyRegion (oldbsp->id, tmp_loc, newbsp, 0, oldbsp->length - 1, Seq_strand_plus, &split);
3647 
3648   tmp_loc = SeqLocFree (tmp_loc);
3649 
3650   return new_loc;
3651 }
3652 
3653 
DoFeaturePropThruAlign(UpsDataPtr udp,SeqAnnotPtr PNTR sapp)3654 static Boolean DoFeaturePropThruAlign (
3655   UpsDataPtr udp,
3656   SeqAnnotPtr PNTR sapp
3657 )
3658 
3659 {
3660   BioseqPtr          bsp, newbsp, oldbsp;
3661   CodeBreakPtr       cbp, prevcbp, nextcbp;
3662   SeqMgrFeatContext  context;
3663   CdRegionPtr        crp;
3664   SeqFeatPtr         dup, sfp, last = NULL;
3665   Uint2              entityID;
3666   Int4               from, to;
3667   Boolean            keepProteinIDs;
3668   SeqLocPtr          newloc;
3669   SeqEntryPtr        newsep, prdsep, top;
3670   RnaRefPtr          rrp;
3671   SeqAnnotPtr        sap = NULL, saptmp;
3672   SeqDescrPtr        sdp;
3673   SeqIdPtr           sip;
3674   Boolean            split;
3675   tRNAPtr            trp;
3676   Boolean            partial5, partial3;
3677 
3678   if (udp == NULL) return FALSE;
3679 
3680   SeqEntrySetScope (NULL);
3681 
3682   sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &context);
3683   if (sfp == NULL) return FALSE;
3684 
3685   keepProteinIDs = GetStatus (udp->keepProteinIDs);
3686 
3687   oldbsp = udp->oldbsp;
3688 
3689   entityID = ObjMgrGetEntityIDForPointer (oldbsp);
3690   top = GetBestTopParentForData (entityID, oldbsp);
3691 
3692   sdp = ExtractBioSourceAndPubs (top);
3693 
3694   sip = SeqIdFindBest (oldbsp->id, 0);
3695 
3696   from = udp->new5;
3697   to = udp->new5 + udp->newa;
3698 
3699   while (sfp != NULL) {
3700 
3701     if (context.right >= from && context.left <= to) {
3702       split = FALSE;
3703       newloc = GetPropagatedLocation (sfp->location, udp->newbsp, udp->oldbsp,
3704                                       LengthForNewSequence (udp), udp->salp);
3705       if (newloc != NULL) {
3706         CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
3707         SetSeqLocPartial (newloc, partial5, partial3);
3708         dup = AsnIoMemCopy ((Pointer) sfp,
3709                             (AsnReadFunc) SeqFeatAsnRead,
3710                             (AsnWriteFunc) SeqFeatAsnWrite);
3711 
3712         SeqLocFree (dup->location);
3713         dup->location = newloc;
3714         if (split) {
3715           dup->partial = TRUE;
3716         }
3717         dup->partial |= partial5;
3718         dup->partial |= partial3;
3719 
3720         if (last == NULL) {
3721           sap = SeqAnnotNew ();
3722           if (oldbsp->annot == NULL) {
3723             oldbsp->annot = sap;
3724           } else {
3725             for (saptmp = oldbsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
3726             saptmp->next = sap;
3727           }
3728           sap->type = 1;
3729           sap->data = (Pointer) dup;
3730         } else {
3731           last->next = dup;
3732         }
3733         last = dup;
3734 
3735         switch (dup->data.choice) {
3736           case SEQFEAT_CDREGION :
3737             crp = (CdRegionPtr) dup->data.value.ptrvalue;
3738             if (crp != NULL) {
3739               prevcbp = NULL;
3740               for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp) {
3741                 nextcbp = cbp->next;
3742                 newloc = GetPropagatedLocation (cbp->loc, udp->newbsp, udp->oldbsp,
3743                                                 LengthForNewSequence (udp), udp->salp);
3744                 SeqLocFree (cbp->loc);
3745                 cbp->loc = newloc;
3746                 if (cbp->loc == NULL) {
3747                   if (prevcbp != NULL) {
3748                     prevcbp->next = nextcbp;
3749                   } else {
3750                     crp->code_break = nextcbp;
3751                   }
3752                   cbp->next = NULL;
3753                   CodeBreakFree (cbp);
3754                 } else {
3755                   prevcbp = cbp;
3756                 }
3757               }
3758             }
3759             break;
3760           case SEQFEAT_RNA :
3761             rrp = (RnaRefPtr) dup->data.value.ptrvalue;
3762             if (rrp != NULL && rrp->ext.choice == 2) {
3763               trp = (tRNAPtr) rrp->ext.value.ptrvalue;
3764               if (trp != NULL && trp->anticodon != NULL) {
3765                 newloc = GetPropagatedLocation (trp->anticodon, udp->newbsp, udp->oldbsp,
3766                                                 LengthForNewSequence (udp), udp->salp);
3767                 SeqLocFree (trp->anticodon);
3768                 trp->anticodon = newloc;
3769               }
3770             }
3771             break;
3772           default :
3773             break;
3774         }
3775         if (dup->product != NULL) {
3776           SeqEntrySetScope (NULL);
3777           bsp = BioseqFindFromSeqLoc (dup->product);
3778           if (bsp != NULL) {
3779             prdsep = SeqMgrGetSeqEntryForData (bsp);
3780             if (prdsep != NULL) {
3781               newsep = AsnIoMemCopy ((Pointer) prdsep,
3782                                      (AsnReadFunc) SeqEntryAsnRead,
3783                                      (AsnWriteFunc) SeqEntryAsnWrite);
3784               if (newsep != NULL) {
3785                 if (IS_Bioseq (newsep)) {
3786                   newbsp = (BioseqPtr) newsep->data.ptrvalue;
3787                   if (newbsp != NULL) {
3788                     if (! keepProteinIDs) {
3789                       newbsp->id = SeqIdSetFree (newbsp->id);
3790                       newbsp->id = MakeNewProteinSeqId (NULL, sip);
3791                       VisitFeaturesOnBsp (newbsp, (Pointer) newbsp->id, CorrectFeatureSeqIds);
3792                       SetSeqFeatProduct (dup, newbsp);
3793                       /*
3794                       dup->product = SeqLocFree (dup->product);
3795                       dup->product = CreateWholeInterval (newsep);
3796                       */
3797                     }
3798                     SeqMgrReplaceInBioseqIndex (newbsp);
3799                   }
3800                 }
3801                 AddSeqEntryToSeqEntry (top, newsep, TRUE);
3802               }
3803             }
3804           }
3805         }
3806       }
3807     }
3808 
3809     sfp = SeqMgrGetNextFeature (udp->newbsp, sfp, 0, 0, &context);
3810   }
3811 
3812   ReplaceBioSourceAndPubs (top, sdp);
3813 
3814   if (sapp != NULL) {
3815     *sapp = sap;
3816   }
3817 
3818   return TRUE;
3819 }
3820 
ReplaceSequence(UpsDataPtr udp)3821 static Boolean ReplaceSequence (UpsDataPtr udp)
3822 
3823 {
3824   MsgAnswer          ans;
3825 
3826   if (udp == NULL)
3827   {
3828     return TRUE;
3829   }
3830 
3831   if (FALSE == udp->isSet)
3832   {
3833     if ((udp->seq1 != NULL || udp->seq2 != NULL)
3834         && StringICmp (udp->seq1, udp->seq2) == 0
3835         && ! udp->revcomp)
3836     {
3837 	    ans = Message (MSG_OKC, "Replacement sequence is identical to"
3838 	                           " original - possible error");
3839 	    if (ans == ANS_CANCEL) return FALSE;
3840     }
3841   }
3842 
3843   ReplaceOneSequence (udp->salp, udp->oldbsp, udp->newbsp);
3844   return TRUE;
3845 }
3846 
Merge5Prime(UpsDataPtr udp)3847 static Boolean Merge5Prime (UpsDataPtr udp)
3848 
3849 {
3850   ByteStorePtr  bs;
3851   Char          ch;
3852   Int4          i, newlen;
3853   BioseqPtr     newbsp;
3854   CharPtr       ptr, str, tmp;
3855 
3856   /* construct replacement sequence by recombining between old and overlap */
3857 
3858   tmp = udp->seq2;
3859 
3860   newlen = udp->new5 + udp->newa + udp->old3;
3861   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
3862   if (str == NULL)
3863     return FALSE;
3864   ptr = str;
3865 
3866   for (i = 0; i < udp->new5 + udp->newa; i++) {
3867     ch = *tmp;
3868     *ptr = ch;
3869     tmp++;
3870     ptr++;
3871   }
3872 
3873   tmp = udp->seq1 + udp->old5 + udp->olda;
3874   for (i = 0; i < udp->old3; i++) {
3875     ch = *tmp;
3876     *ptr = ch;
3877     tmp++;
3878     ptr++;
3879   }
3880 
3881   *ptr = '\0';
3882   bs = BSNew (newlen);
3883   BSWrite (bs, (VoidPtr) str, newlen);
3884 
3885   udp->seq2 = MemFree (udp->seq2);
3886   udp->seq2 = str;
3887 
3888   if (bs != NULL && BSLen (bs) < 1) {
3889     bs = BSFree (bs);
3890   }
3891   if (bs == NULL) return FALSE;
3892 
3893   /* overlap turned into replacement sequence */
3894 
3895   newbsp = udp->newbsp;
3896   newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
3897   newbsp->seq_data = (SeqDataPtr) bs;
3898   newbsp->seq_data_type = Seq_code_iupacna;
3899   newbsp->length = newlen;
3900 
3901   /* adjust alignment and reindex */
3902 
3903   if (! AdjustAlignment (udp, 2)) return FALSE;
3904 
3905   /* then finish by replacing with new sequence */
3906 
3907   return ReplaceSequence (udp);
3908 }
3909 
Merge3Prime(UpsDataPtr udp)3910 static Boolean Merge3Prime (UpsDataPtr udp)
3911 
3912 {
3913   ByteStorePtr  bs;
3914   Char          ch;
3915   Int4          i, newlen;
3916   BioseqPtr     newbsp;
3917   CharPtr       ptr, str, tmp;
3918 
3919   /* construct replacement sequence by recombining between old and overlap */
3920 
3921   newlen = udp->old5 + udp->newa + udp->new3;
3922   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
3923   if (str == NULL)
3924     return FALSE;
3925   ptr = str;
3926 
3927   tmp = udp->seq1;
3928   for (i = 0; i < udp->old5; i++) {
3929     ch = *tmp;
3930     *ptr = ch;
3931     tmp++;
3932     ptr++;
3933   }
3934 
3935   tmp = udp->seq2 + udp->new5;
3936   for (i = 0; i < udp->newa + udp->new3; i++) {
3937     ch = *tmp;
3938     *ptr = ch;
3939     tmp++;
3940     ptr++;
3941   }
3942 
3943   *ptr = '\0';
3944   bs = BSNew (newlen);
3945   BSWrite (bs, (VoidPtr) str, newlen);
3946 
3947   udp->seq2 = MemFree (udp->seq2);
3948   udp->seq2 = str;
3949 
3950   if (bs != NULL && BSLen (bs) < 1) {
3951     bs = BSFree (bs);
3952   }
3953   if (bs == NULL) return FALSE;
3954 
3955   /* overlap turned into replacement sequence */
3956 
3957   newbsp = udp->newbsp;
3958   newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
3959   newbsp->seq_data = (SeqDataPtr) bs;
3960   newbsp->seq_data_type = Seq_code_iupacna;
3961   newbsp->length = newlen;
3962 
3963   /* adjust alignment and reindex */
3964 
3965   if (! AdjustAlignment (udp, 3)) return FALSE;
3966 
3967   /* then finish by replacing with new sequence */
3968 
3969   return ReplaceSequence (udp);
3970 }
3971 
3972 static Boolean ExtendFeatures (UpsDataPtr udp, Int4 offset);
3973 
3974 /*------------------------------------------------------------------*/
3975 /*                                                                  */
3976 /*  Merge5PrimeNoOverlap () -- Merge a new sequence onto the 5' end */
3977 /*                             of an existing sequence.             */
3978 /*                                                                  */
3979 /*                             Performs a similar function to       */
3980 /*                             Merge5Prime() except works when      */
3981 /*                             there is no alignment between the    */
3982 /*                             two sequences.                       */
3983 /*                                                                  */
3984 /*------------------------------------------------------------------*/
3985 
Merge5PrimeNoOverlap(UpsDataPtr udp)3986 static Boolean Merge5PrimeNoOverlap (UpsDataPtr udp)
3987 
3988 {
3989   CharPtr       origSeqStr;
3990   CharPtr       newSeqStr;
3991   CharPtr       mergedSeqStr;
3992   Int4          mergedLen;
3993   ByteStorePtr  mergedBS;
3994 
3995   /* Get original and new sequences */
3996 
3997   origSeqStr = GetSequenceByBsp (udp->oldbsp);
3998   newSeqStr = GetSequenceByBsp (udp->newbsp);
3999 
4000   /* Concatenate the new sequence onto the beginning */
4001   /* (i.e. the 5' end) of the original sequence.     */
4002 
4003   mergedLen =  StringLen (newSeqStr) + StringLen (origSeqStr);
4004   mergedSeqStr = (CharPtr) MemNew (mergedLen + 1);
4005   sprintf (mergedSeqStr, "%s%s", newSeqStr, origSeqStr);
4006 
4007   /* Convert the new sequence into a ByteStore */
4008 
4009   mergedBS = BSNew (mergedLen);
4010   BSWrite (mergedBS, (VoidPtr) mergedSeqStr, mergedLen);
4011 
4012   /* Replace the original sequence with the */
4013   /* new concatenated sequence.             */
4014 
4015   udp->newbsp->seq_data      = SeqDataFree (udp->newbsp->seq_data, udp->newbsp->seq_data_type);
4016   udp->newbsp->seq_data      = (SeqDataPtr) mergedBS;
4017   udp->newbsp->seq_data_type = Seq_code_iupacna;
4018   udp->newbsp->length        = mergedLen;
4019 
4020   /* Replace the merged sequence and return */
4021 
4022   return ExtendFeatures (udp, StringLen (newSeqStr));
4023 }
4024 
4025 /*------------------------------------------------------------------*/
4026 /*                                                                  */
4027 /*  Merge3PrimeNoOverlap () -- Merge a new sequence onto the 3' end */
4028 /*                             of an existing sequence.             */
4029 /*                                                                  */
4030 /*                             Performs a similar function to       */
4031 /*                             Merge3Prime() except works when      */
4032 /*                             there is no alignment between the    */
4033 /*                             two sequences.                       */
4034 /*                                                                  */
4035 /*------------------------------------------------------------------*/
4036 
Merge3PrimeNoOverlap(UpsDataPtr udp)4037 static Boolean Merge3PrimeNoOverlap (UpsDataPtr udp)
4038 
4039 {
4040   CharPtr       origSeqStr;
4041   CharPtr       newSeqStr;
4042   CharPtr       mergedSeqStr;
4043   Int4          mergedLen;
4044   ByteStorePtr  mergedBS;
4045 
4046   /* Get original and new sequences */
4047 
4048   origSeqStr = GetSequenceByBsp (udp->oldbsp);
4049   newSeqStr = GetSequenceByBsp (udp->newbsp);
4050 
4051   /* Concatenate the new sequence onto the end   */
4052   /* (i.e. the 3' end) of the original sequence. */
4053 
4054   mergedLen =  StringLen (newSeqStr) + StringLen (origSeqStr);
4055   mergedSeqStr = (CharPtr) MemNew (mergedLen + 1);
4056   sprintf (mergedSeqStr, "%s%s", origSeqStr, newSeqStr);
4057 
4058   /* Convert the new sequence into a ByteStore */
4059 
4060   mergedBS = BSNew (mergedLen);
4061   BSWrite (mergedBS, (VoidPtr) mergedSeqStr, mergedLen);
4062 
4063   /* Replace the original sequence with the */
4064   /* new concatenated sequence.             */
4065 
4066   udp->newbsp->seq_data      = SeqDataFree (udp->newbsp->seq_data, udp->newbsp->seq_data_type);
4067   udp->newbsp->seq_data      = (SeqDataPtr) mergedBS;
4068   udp->newbsp->seq_data_type = Seq_code_iupacna;
4069   udp->newbsp->length        = mergedLen;
4070 
4071   /* Replace the merged sequence and return */
4072 
4073   return ExtendFeatures (udp, 0);
4074 }
4075 
OkToPatchDelta(UpsDataPtr udp)4076 static Boolean OkToPatchDelta (UpsDataPtr udp)
4077 {
4078   Boolean rval = TRUE;
4079 
4080   if (udp == NULL || udp->oldbsp == NULL || udp->newbsp == NULL
4081       || udp->oldbsp->repr != Seq_repr_delta || udp->newbsp->repr != Seq_repr_delta
4082       || udp->oldbsp->seq_ext_type != 4 || udp->newbsp->seq_ext_type != 4)
4083   {
4084     rval = FALSE;
4085   }
4086 
4087   return rval;
4088 }
4089 
SplitDeltaSeq(DeltaSeqPtr dsp,Int4 offset)4090 static void SplitDeltaSeq (DeltaSeqPtr dsp, Int4 offset)
4091 {
4092   SeqLocPtr   slp1, slp2;
4093   SeqLitPtr   slip1, slip2;
4094   Int4        len;
4095   Boolean     changed;
4096   DeltaSeqPtr dsp_new;
4097   ByteStorePtr bs_1, bs_2;
4098   Int2         residue;
4099   Int4         pos;
4100 
4101   if (dsp == NULL || dsp->data.ptrvalue == NULL || offset == 0)
4102   {
4103     return;
4104   }
4105 
4106   if (dsp->choice == 1)
4107   {
4108     slp1 = (SeqLocPtr)(dsp->data.ptrvalue);
4109     len = SeqLocLen (slp1);
4110     if (offset > len)
4111     {
4112       return;
4113     }
4114     slp2 = (SeqLocPtr) AsnIoMemCopy (slp1, (AsnReadFunc) SeqLocAsnRead,
4115                                      (AsnWriteFunc) SeqLocAsnWrite);
4116     slp1 = SeqLocDelete (slp1, SeqLocId (slp1),
4117                           offset, len - 1, FALSE, &changed);
4118     slp2 = SeqLocDelete (slp2, SeqLocId (slp2),
4119                          0, offset, FALSE, &changed);
4120     dsp_new = ValNodeNew (NULL);
4121     dsp_new->choice = 1;
4122     dsp_new->data.ptrvalue = slp2;
4123     dsp_new->next = dsp->next;
4124     dsp->next = dsp_new;
4125   }
4126   else if (dsp->choice == 2)
4127   {
4128     slip1 = (SeqLitPtr) dsp->data.ptrvalue;
4129     if (offset > slip1->length)
4130     {
4131       return;
4132     }
4133     if (IsDeltaSeqGap (dsp))
4134     {
4135       /* use AsnIoMemCopy, to automatically copy gap data if present */
4136       slip2 = (SeqLitPtr) AsnIoMemCopy (slip1, (AsnReadFunc) SeqLitAsnRead, (AsnWriteFunc) SeqLitAsnWrite);
4137       slip2->length = slip1->length - offset;
4138       slip1->length = offset;
4139     }
4140     else
4141     {
4142       slip2 = SeqLitNew ();
4143       if (slip1->seq_data_type == Seq_code_iupacna)
4144       {
4145         bs_1 = (ByteStorePtr) slip1->seq_data;
4146       }
4147       else
4148       {
4149         bs_1 = BSConvertSeq((ByteStorePtr) slip1->seq_data, Seq_code_iupacna,
4150                               slip1->seq_data_type,
4151                               slip1->length);
4152         slip1->seq_data_type = Seq_code_iupacna;
4153         slip1->seq_data = (SeqDataPtr) bs_1;
4154       }
4155       bs_2 = BSNew (slip1->length - offset);
4156       pos = offset;
4157       BSSeek(bs_1, pos, SEEK_SET);
4158       BSSeek (bs_2, 0L, SEEK_SET);
4159       while (pos < slip1->length)
4160       {
4161         residue = BSGetByte (bs_1);
4162         BSPutByte (bs_2, residue);
4163         pos++;
4164       }
4165       BSSeek(bs_1, offset, SEEK_SET);
4166       BSDelete(bs_1, slip1->length - offset);
4167 
4168       slip2->seq_data = (SeqDataPtr) bs_2;
4169       slip2->seq_data_type = slip1->seq_data_type;
4170       slip2->length = slip1->length - offset;
4171       slip1->length = offset;
4172     }
4173     dsp_new = ValNodeNew (NULL);
4174     dsp_new->choice = 2;
4175     dsp_new->data.ptrvalue = slip2;
4176     dsp_new->next = dsp->next;
4177     dsp->next = dsp_new;
4178   }
4179 }
4180 
4181 /* This function will patch a delta sequence with another delta sequence.
4182  * The pieces in the overlap from the old sequence will be replaced by pieces
4183  * in the overlap from the new sequence.
4184  */
PatchDeltaSequence(UpsDataPtr udp)4185 static Boolean PatchDeltaSequence (UpsDataPtr udp)
4186 
4187 {
4188   Int4        currnew_pos = 0, currold_pos;
4189   SeqLitPtr   slip, slip_new;
4190   DeltaSeqPtr dspold, dspnew;
4191   Int4        seqstart;
4192   DeltaSeqPtr new_list = NULL;
4193 
4194   if (! OkToPatchDelta (udp))
4195   {
4196     return FALSE;
4197   }
4198 
4199   /* keep old 5' end intact */
4200   currold_pos = 0;
4201   seqstart = 0;
4202   dspold = (DeltaSeqPtr) udp->oldbsp->seq_ext;
4203   while (dspold != NULL && currold_pos < udp->old5)
4204   {
4205     seqstart = currold_pos;
4206     if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
4207     {
4208       return FALSE;
4209     }
4210     slip = (SeqLitPtr) (dspold->data.ptrvalue);
4211 	  currold_pos += slip->length;
4212 		if (currold_pos > udp->old5)
4213 		{
4214       SplitDeltaSeq (dspold, udp->old5 - seqstart);
4215       slip = (SeqLitPtr) (dspold->data.ptrvalue);
4216       currold_pos = udp->old5;
4217 		}
4218 		slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
4219 		                                     (AsnWriteFunc) SeqLitAsnWrite);
4220 		ValNodeAddPointer (&new_list, 2, slip_new);
4221 	  dspold = dspold->next;
4222   }
4223 
4224   /* skip over new 5' end */
4225   currnew_pos = 0;
4226   seqstart = 0;
4227   dspnew = (DeltaSeqPtr) udp->newbsp->seq_ext;
4228   while (dspnew != NULL && currnew_pos < udp->new5)
4229   {
4230     seqstart = currold_pos;
4231     if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
4232     {
4233       return FALSE;
4234     }
4235 	  slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4236 	  currnew_pos += slip->length;
4237 	  if (currnew_pos > udp->new5)
4238 	  {
4239       SplitDeltaSeq (dspnew, udp->new5 - seqstart);
4240       currnew_pos = udp->new5;
4241 	  }
4242 	  dspnew = dspnew->next;
4243   }
4244 
4245   /* copy in new overlap */
4246   while (dspnew != NULL && currnew_pos < udp->new5 + udp->newa)
4247   {
4248     seqstart = currold_pos;
4249     if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
4250     {
4251       return FALSE;
4252     }
4253 	  slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4254 	  currnew_pos += slip->length;
4255 		if (currnew_pos > udp->new5 + udp->newa)
4256 		{
4257       SplitDeltaSeq (dspnew, udp->new5 + udp->newa - seqstart);
4258       slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4259       currnew_pos = udp->new5 + udp->newa;
4260 		}
4261 		slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
4262 		                                     (AsnWriteFunc) SeqLitAsnWrite);
4263 		ValNodeAddPointer (&new_list, 2, slip_new);
4264 		dspnew = dspnew->next;
4265   }
4266 
4267   /* skip over old overlap */
4268 
4269   while (dspold != NULL && currold_pos < udp->old5 + udp->olda)
4270   {
4271     seqstart = currold_pos;
4272     if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
4273     {
4274       return FALSE;
4275     }
4276     slip = (SeqLitPtr) (dspold->data.ptrvalue);
4277     currold_pos += slip->length;
4278     if (currold_pos > udp->old5 + udp->olda)
4279     {
4280       SplitDeltaSeq (dspold, udp->new5 + udp->newa - seqstart);
4281       currold_pos = udp->old5 + udp->olda;
4282     }
4283     dspold = dspold->next;
4284   }
4285 
4286   /* copy in old 3' */
4287 
4288   while (dspold != NULL)
4289   {
4290     if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
4291     {
4292       return FALSE;
4293     }
4294     slip = (SeqLitPtr) (dspold->data.ptrvalue);
4295 		slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
4296 		                                     (AsnWriteFunc) SeqLitAsnWrite);
4297 		ValNodeAddPointer (&new_list, 2, slip_new);
4298 		dspold = dspold->next;
4299   }
4300 
4301   /* free newbsp's old SeqLit List */
4302   for (dspnew = (DeltaSeqPtr) udp->newbsp->seq_ext;
4303        dspnew != NULL;
4304        dspnew = dspnew->next)
4305   {
4306     slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4307     SeqLitFree (slip);
4308   }
4309   udp->newbsp->seq_ext = ValNodeFree (udp->newbsp->seq_ext);
4310   udp->newbsp->seq_ext = new_list;
4311   udp->newbsp->length = udp->old5 + udp->newa + udp->old3;
4312   return TRUE;
4313 }
4314 
OkToPatchRaw(UpsDataPtr udp)4315 static Boolean OkToPatchRaw (UpsDataPtr udp)
4316 {
4317   Boolean rval = TRUE;
4318 
4319   if (udp == NULL || udp->oldbsp == NULL || udp->newbsp == NULL
4320       || udp->oldbsp->repr != Seq_repr_raw || udp->newbsp->repr != Seq_repr_raw)
4321   {
4322     rval = FALSE;
4323   }
4324 
4325   return rval;
4326 }
4327 
PatchRawSequence(UpsDataPtr udp)4328 static Boolean PatchRawSequence (UpsDataPtr udp)
4329 
4330 {
4331   ByteStorePtr  bs;
4332   Char          ch;
4333   Int4          i, newlen;
4334   BioseqPtr     newbsp;
4335   CharPtr       ptr, str, tmp;
4336 
4337   newlen = udp->old5 + udp->newa + udp->old3;
4338   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
4339   if (str == NULL) return FALSE;
4340 
4341   /* construct replacement sequence by double recombination */
4342   ptr = str;
4343 
4344   tmp = udp->seq1;
4345   for (i = 0; i < udp->old5; i++) {
4346     ch = *tmp;
4347     *ptr = ch;
4348     tmp++;
4349     ptr++;
4350   }
4351 
4352   tmp = udp->seq2 + udp->new5;
4353   for (i = 0; i < udp->newa; i++) {
4354     ch = *tmp;
4355     *ptr = ch;
4356     tmp++;
4357     ptr++;
4358   }
4359 
4360   tmp = udp->seq1 + udp->old5 + udp->olda;
4361   for (i = 0; i < udp->old3; i++) {
4362     ch = *tmp;
4363     *ptr = ch;
4364     tmp++;
4365     ptr++;
4366   }
4367 
4368   *ptr = '\0';
4369   bs = BSNew (newlen);
4370   BSWrite (bs, (VoidPtr) str, newlen);
4371 
4372   udp->seq2 = MemFree (udp->seq2);
4373   udp->seq2 = str;
4374 
4375   if (bs != NULL && BSLen (bs) < 1) {
4376     bs = BSFree (bs);
4377   }
4378   if (bs == NULL) return FALSE;
4379 
4380   /* overlap turned into replacement sequence */
4381 
4382   newbsp = udp->newbsp;
4383   newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
4384   newbsp->seq_data = (SeqDataPtr) bs;
4385   newbsp->seq_data_type = Seq_code_iupacna;
4386   newbsp->length = newlen;
4387   return TRUE;
4388 }
4389 
PatchSequence(UpsDataPtr udp)4390 static Boolean PatchSequence (UpsDataPtr udp)
4391 
4392 {
4393   Boolean rval = FALSE;
4394 
4395   if (OkToPatchRaw (udp))
4396   {
4397     rval = PatchRawSequence (udp);
4398   }
4399   else if (OkToPatchDelta (udp))
4400   {
4401     rval = PatchDeltaSequence (udp);
4402   }
4403 
4404   if (!rval)
4405   {
4406     return rval;
4407   }
4408 
4409   /* adjust alignment and reindex */
4410 
4411   if (! AdjustAlignment (udp, 4)) return FALSE;
4412 
4413   /* then finish by replacing with new sequence */
4414 
4415   return ReplaceSequence (udp);
4416 }
4417 
MarkProductForDeletion(SeqLocPtr product)4418 static void MarkProductForDeletion (
4419   SeqLocPtr product
4420 )
4421 
4422 {
4423   BioseqPtr  bsp;
4424   SeqIdPtr   sip;
4425 
4426   if (product == NULL) return;
4427   sip = SeqLocId (product);
4428   if (sip == NULL) return;
4429   bsp = BioseqFind (sip);
4430   if (bsp == NULL) return;
4431   bsp->idx.deleteme = TRUE;
4432 }
4433 
CombineTexts(CharPtr PNTR txtptr,CharPtr PNTR oldtxtptr)4434 static void CombineTexts (
4435   CharPtr PNTR txtptr,
4436   CharPtr PNTR oldtxtptr
4437 )
4438 
4439 {
4440   size_t     len;
4441   CharPtr    str;
4442 
4443   if (txtptr == NULL || oldtxtptr == NULL) return;
4444 
4445   if (*txtptr == NULL) {
4446 
4447     *txtptr = *oldtxtptr;
4448     *oldtxtptr = NULL;
4449 
4450   } else if (*oldtxtptr != NULL && StringICmp (*txtptr, *oldtxtptr) != 0) {
4451 
4452     len = StringLen (*txtptr) + StringLen (*oldtxtptr) + 5;
4453     str = MemNew (sizeof (Char) * len);
4454     StringCpy (str, *txtptr);
4455     StringCat (str, "; ");
4456     StringCat (str, *oldtxtptr);
4457     *txtptr = MemFree (*txtptr);
4458     *txtptr = str;
4459   }
4460 }
4461 
FuseCommonFeatureFields(SeqFeatPtr sfp,SeqFeatPtr oldsfp)4462 static void FuseCommonFeatureFields (
4463   SeqFeatPtr sfp,
4464   SeqFeatPtr oldsfp
4465 )
4466 
4467 {
4468   GBQualPtr       lastgbq;
4469   SeqFeatXrefPtr  lastxref;
4470 
4471   if (sfp == NULL || oldsfp == NULL) return;
4472 
4473   CombineTexts (&(sfp->comment), &(oldsfp->comment));
4474   CombineTexts (&(sfp->title), &(oldsfp->title));
4475   CombineTexts (&(sfp->except_text), &(oldsfp->except_text));
4476 
4477   if (sfp->qual == NULL) {
4478     sfp->qual = oldsfp->qual;
4479     oldsfp->qual = NULL;
4480   } else if (oldsfp->qual != NULL) {
4481     for (lastgbq = sfp->qual; lastgbq->next != NULL; lastgbq = lastgbq->next) continue;
4482     lastgbq->next = oldsfp->qual;
4483     oldsfp->qual = NULL;
4484   }
4485 
4486   ValNodeLink (&(sfp->dbxref), oldsfp->dbxref);
4487   oldsfp->dbxref = NULL;
4488 
4489   ValNodeLink (&(sfp->cit), oldsfp->cit);
4490   oldsfp->cit = NULL;
4491 
4492   if (sfp->xref == NULL) {
4493     sfp->xref = oldsfp->xref;
4494     oldsfp->xref = NULL;
4495   } else if (oldsfp->xref != NULL) {
4496     for (lastxref = sfp->xref; lastxref->next != NULL; lastxref = lastxref->next) continue;
4497     lastxref->next = oldsfp->xref;
4498     oldsfp->xref = NULL;
4499   }
4500 
4501   if (sfp->ext == NULL) {
4502     sfp->ext = oldsfp->ext;
4503     oldsfp->ext = NULL;
4504   } else if (oldsfp->ext != NULL) {
4505     sfp->ext = CombineUserObjects (sfp->ext, oldsfp->ext);
4506     oldsfp->ext = NULL;
4507   }
4508 
4509   sfp->partial |= oldsfp->partial;
4510   sfp->excpt |= oldsfp->excpt;
4511   sfp->pseudo |= oldsfp->pseudo;
4512 }
4513 
FuseFeatures(SeqFeatPtr sfp,SeqFeatPtr oldsfp)4514 static void FuseFeatures (
4515   SeqFeatPtr sfp,
4516   SeqFeatPtr oldsfp
4517 )
4518 
4519 {
4520   GeneRefPtr      grp, oldgrp;
4521   BioseqPtr       prod, oldprod;
4522   SeqFeatPtr      prot, oldprot;
4523   ProtRefPtr      prp, oldprp;
4524   RnaRefPtr       rrp, oldrrp;
4525   SeqIdPtr        sip;
4526 
4527   if (sfp == NULL || oldsfp == NULL) return;
4528 
4529   /* merge common fields */
4530 
4531   FuseCommonFeatureFields (sfp, oldsfp);
4532 
4533   /* now deal with type-specific data */
4534 
4535   switch (sfp->data.choice) {
4536     case SEQFEAT_GENE :
4537       grp = (GeneRefPtr) sfp->data.value.ptrvalue;
4538       oldgrp = (GeneRefPtr) oldsfp->data.value.ptrvalue;
4539       if (grp == NULL || oldgrp == NULL) return;
4540       CombineTexts (&(grp->locus), &(oldgrp->locus));
4541       CombineTexts (&(grp->allele), &(oldgrp->allele));
4542       CombineTexts (&(grp->desc), &(oldgrp->desc));
4543       CombineTexts (&(grp->maploc), &(oldgrp->maploc));
4544       CombineTexts (&(grp->locus_tag), &(oldgrp->locus_tag));
4545       grp->pseudo |= oldgrp->pseudo;
4546       ValNodeLink (&(grp->db), oldgrp->db);
4547       oldgrp->db = NULL;
4548       ValNodeLink (&(grp->syn), oldgrp->syn);
4549       oldgrp->syn = NULL;
4550       break;
4551     case SEQFEAT_CDREGION :
4552       sip = SeqLocId (sfp->product);
4553       prod = BioseqFind (sip);
4554       sip = SeqLocId (oldsfp->product);
4555       oldprod = BioseqFind (sip);
4556       if (prod == NULL || oldprod == NULL) return;
4557       prot = SeqMgrGetBestProteinFeature (prod, NULL);
4558       oldprot = SeqMgrGetBestProteinFeature (oldprod, NULL);
4559       if (prot == NULL || oldprot == NULL) return;
4560       FuseCommonFeatureFields (prot, oldprot);
4561       prp = (ProtRefPtr) prot->data.value.ptrvalue;
4562       oldprp = (ProtRefPtr) oldprot->data.value.ptrvalue;
4563       if (prp == NULL || oldprp == NULL) return;
4564       ValNodeLink (&(prp->name), oldprp->name);
4565       oldprp->name = NULL;
4566       ValNodeLink (&(prp->ec), oldprp->ec);
4567       oldprp->ec = NULL;
4568       ValNodeLink (&(prp->activity), oldprp->activity);
4569       oldprp->activity = NULL;
4570       ValNodeLink (&(prp->db), oldprp->db);
4571       oldprp->db = NULL;
4572       CombineTexts (&(prp->desc), &(oldprp->desc));
4573       break;
4574     case SEQFEAT_RNA :
4575       rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
4576       oldrrp = (RnaRefPtr) oldsfp->data.value.ptrvalue;
4577       if (rrp == NULL || oldrrp == NULL) return;
4578       if (rrp->ext.choice == 1 && oldrrp->ext.choice == 1) {
4579         CombineTexts ((CharPtr PNTR) &(rrp->ext.value.ptrvalue), (CharPtr PNTR) &(oldrrp->ext.value.ptrvalue));
4580       }
4581       break;
4582     case SEQFEAT_REGION :
4583     case SEQFEAT_COMMENT :
4584       if (sfp->data.value.ptrvalue == NULL || oldsfp->data.value.ptrvalue == NULL) return;
4585       CombineTexts ((CharPtr PNTR) &(sfp->data.value.ptrvalue), (CharPtr PNTR) &(oldsfp->data.value.ptrvalue));
4586       break;
4587     default :
4588       break;
4589   }
4590 }
4591 
RemoveOldFeatsInRegion(UpsDataPtr udp,BioseqPtr bsp,SeqAnnotPtr sap)4592 static void RemoveOldFeatsInRegion (
4593   UpsDataPtr udp,
4594   BioseqPtr bsp,
4595   SeqAnnotPtr sap
4596 )
4597 
4598 {
4599   SeqMgrFeatContext  context;
4600   Int4               left, right;
4601   SeqFeatPtr         sfp;
4602 
4603   if (udp == NULL || bsp == NULL || sap == NULL) return;
4604   if (sap->type != 1) return;
4605 
4606   left = INT4_MAX;
4607   right = INT4_MIN;
4608 
4609   for (sfp = (SeqFeatPtr) sap->data; sfp != NULL; sfp = sfp->next) {
4610     if (sfp != SeqMgrGetDesiredFeature (0, bsp, 0, 0, sfp, &context)) continue;
4611     left = MIN (left, context.left);
4612     right = MAX (right, context.right);
4613   }
4614 
4615   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
4616 
4617   while (sfp != NULL) {
4618 
4619     if (context.sap != sap && context.right >= left && context.left <= right) {
4620       sfp->idx.deleteme = TRUE;
4621       MarkProductForDeletion (sfp->product);
4622     }
4623 
4624     sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
4625   }
4626 }
4627 
RemoveOldFeats(BioseqPtr bsp)4628 static Boolean RemoveOldFeats (BioseqPtr bsp)
4629 
4630 {
4631   SeqMgrFeatContext  context;
4632   SeqFeatPtr         sfp;
4633   Boolean            rval = FALSE;
4634 
4635   if (bsp == NULL) return FALSE;
4636 
4637   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
4638 
4639   while (sfp != NULL)
4640   {
4641     sfp->idx.deleteme = TRUE;
4642     rval = TRUE;
4643     MarkProductForDeletion (sfp->product);
4644     sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
4645   }
4646   return rval;
4647 }
4648 
4649 
ResolveDuplicateFeats(UpsDataPtr udp,BioseqPtr bsp,SeqAnnotPtr sap)4650 static void ResolveDuplicateFeats (
4651   UpsDataPtr udp,
4652   BioseqPtr bsp,
4653   SeqAnnotPtr sap
4654 )
4655 
4656 {
4657   SeqMgrFeatContext  context, lastcontext;
4658   Int2               i, j;
4659   Boolean            ivalssame;
4660   SeqFeatPtr         lastsfp = NULL, sfp;
4661   Int2               nobmval;
4662 
4663   if (udp == NULL || bsp == NULL || sap == NULL) return;
4664 
4665   nobmval = GetValue (udp->nobm);
4666   if (nobmval == UPDATE_FEAT_DUP_USE_BOTH) return; /* keep both */
4667 
4668   SeqMgrIndexFeatures (0, (Pointer) bsp);
4669 
4670   if (nobmval == UPDATE_FEAT_DUP_REPLACE) {
4671     RemoveOldFeatsInRegion (udp, bsp, sap);
4672     return;
4673   }
4674 
4675   lastsfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
4676   if (lastsfp == NULL) return;
4677 
4678   MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
4679 
4680   sfp = SeqMgrGetNextFeature (bsp, lastsfp, 0, 0, &context);
4681   if (sfp == NULL) return;
4682 
4683   while (sfp != NULL) {
4684 
4685     if (context.left == lastcontext.left &&
4686         context.right == lastcontext.right &&
4687         context.featdeftype == lastcontext.featdeftype) {
4688 
4689       if (context.strand == lastcontext.strand ||
4690           lastcontext.strand == Seq_strand_unknown ||
4691           context.strand == Seq_strand_unknown) {
4692 
4693         ivalssame = TRUE;
4694         if (context.numivals != lastcontext.numivals ||
4695             context.ivals == NULL ||
4696             lastcontext.ivals == NULL) {
4697 
4698           ivalssame = FALSE;
4699 
4700         } else {
4701 
4702           for (i = 0, j = 0; i < lastcontext.numivals; i++, j += 2) {
4703             if (context.ivals [j] != lastcontext.ivals [j]) {
4704               ivalssame = FALSE;
4705             }
4706             if (context.ivals [j + 1] != lastcontext.ivals [j + 1]) {
4707               ivalssame = FALSE;
4708             }
4709           }
4710         }
4711 
4712         if (ivalssame &&
4713             context.sap != lastcontext.sap &&
4714             (context.sap == sap || lastcontext.sap == sap)) {
4715 
4716           if (nobmval == UPDATE_FEAT_DUP_USE_NEW) { /* keep new */
4717             if (context.sap == sap) {
4718               lastsfp->idx.deleteme = TRUE;
4719               MarkProductForDeletion (lastsfp->product);
4720             } else if (lastcontext.sap == sap) {
4721               sfp->idx.deleteme = TRUE;
4722               MarkProductForDeletion (sfp->product);
4723             }
4724 
4725           } else if (nobmval == UPDATE_FEAT_DUP_USE_OLD) { /* keep old */
4726             if (context.sap == sap) {
4727               sfp->idx.deleteme = TRUE;
4728               MarkProductForDeletion (sfp->product);
4729             } else if (lastcontext.sap == sap) {
4730               lastsfp->idx.deleteme = TRUE;
4731               MarkProductForDeletion (lastsfp->product);
4732             }
4733 
4734           } else if (nobmval == UPDATE_FEAT_DUP_MERGE) { /* merge */
4735             if (context.sap == sap) {
4736               FuseFeatures (sfp, lastsfp);
4737               lastsfp->idx.deleteme = TRUE;
4738               MarkProductForDeletion (lastsfp->product);
4739             } else if (lastcontext.sap == sap) {
4740               FuseFeatures (lastsfp, sfp);
4741               sfp->idx.deleteme = TRUE;
4742               MarkProductForDeletion (sfp->product);
4743             }
4744           }
4745         }
4746       }
4747     }
4748 
4749     lastsfp = sfp;
4750     MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
4751 
4752     sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
4753   }
4754 }
4755 
ExtendFeatures(UpsDataPtr udp,Int4 offset)4756 static Boolean ExtendFeatures (UpsDataPtr udp, Int4 offset)
4757 
4758 {
4759   MsgAnswer          ans;
4760   CodeBreakPtr       cbp;
4761   SeqMgrFeatContext  context;
4762   CdRegionPtr        crp;
4763   Int4               len;
4764   BioseqPtr          newbsp;
4765   BioseqPtr          oldbsp;
4766   RnaRefPtr          rrp;
4767   Uint1              seq_data_type;
4768   SeqFeatPtr         sfp;
4769   SeqIdPtr           sip;
4770   tRNAPtr            trp;
4771   SeqDataPtr         sdp;
4772 
4773   if (udp->salp != NULL)
4774     if (FALSE == udp->isSet)
4775       if (StringICmp (udp->seq1, udp->seq2) == 0) {
4776 	ans = Message (MSG_OKC, "Replacement sequence is identical to"
4777 		       " original - possible error");
4778 	if (ans == ANS_CANCEL) return FALSE;
4779       }
4780 
4781   oldbsp = udp->oldbsp;
4782   newbsp = udp->newbsp;
4783 
4784   sip = SeqIdFindBest (oldbsp->id, 0);
4785   if (sip == NULL) return FALSE;
4786 
4787   if (offset > 0) {
4788     sfp = SeqMgrGetNextFeature (oldbsp, NULL, 0, 0, &context);
4789     while (sfp != NULL) {
4790       OffsetLocation (sfp->location, offset, sip);
4791       switch (sfp->data.choice) {
4792         case SEQFEAT_CDREGION :
4793           crp = (CdRegionPtr) sfp->data.value.ptrvalue;
4794           if (crp != NULL) {
4795             for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
4796               OffsetLocation (cbp->loc, offset, sip);
4797             }
4798           }
4799           break;
4800         case SEQFEAT_RNA :
4801           rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
4802           if (rrp != NULL && rrp->ext.choice == 2) {
4803             trp = (tRNAPtr) rrp->ext.value.ptrvalue;
4804             if (trp != NULL && trp->anticodon != NULL) {
4805               OffsetLocation (trp->anticodon, offset, sip);
4806             }
4807           }
4808           break;
4809         default :
4810           break;
4811       }
4812       sfp = SeqMgrGetNextFeature (oldbsp, sfp, 0, 0, &context);
4813     }
4814   }
4815 
4816   /* switch bioseqs to finish extension */
4817 
4818   sdp = oldbsp->seq_data;
4819   oldbsp->seq_data = newbsp->seq_data;
4820   newbsp->seq_data = sdp;
4821   len = oldbsp->length;
4822   oldbsp->length = newbsp->length;
4823   newbsp->length = len;
4824   seq_data_type = oldbsp->seq_data_type;
4825   oldbsp->seq_data_type = newbsp->seq_data_type;
4826   newbsp->seq_data_type = seq_data_type;
4827 
4828   return TRUE;
4829 }
4830 
ExtendBothEnds(UpsDataPtr udp)4831 static Boolean ExtendBothEnds (UpsDataPtr udp)
4832 
4833 {
4834   ByteStorePtr  bs;
4835   Char          ch;
4836   Int4          i, newlen;
4837   BioseqPtr     newbsp;
4838   BioseqPtr     oldbsp;
4839   CharPtr       ptr, str, tmp;
4840 
4841   /* construct replacement sequence by extending old sequence */
4842 
4843   newlen = udp->new5 + udp->olda + udp->new3;
4844   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
4845   if (str == NULL)
4846     return FALSE;
4847   ptr = str;
4848 
4849   tmp = udp->seq2;
4850   for (i = 0; i < udp->new5; i++) {
4851     ch = *tmp;
4852     *ptr = ch;
4853     tmp++;
4854     ptr++;
4855   }
4856 
4857   tmp = udp->seq1 + udp->old5;
4858   for (i = 0; i < udp->olda; i++) {
4859     ch = *tmp;
4860     *ptr = ch;
4861     tmp++;
4862     ptr++;
4863   }
4864 
4865   tmp = udp->seq2 + udp->new5 + udp->newa;
4866   for (i = 0; i < udp->new3; i++) {
4867     ch = *tmp;
4868     *ptr = ch;
4869     tmp++;
4870     ptr++;
4871   }
4872 
4873   *ptr = '\0';
4874   bs = BSNew (newlen);
4875   BSWrite (bs, (VoidPtr) str, newlen);
4876 
4877   udp->seq2 = MemFree (udp->seq2);
4878   udp->seq2 = str;
4879 
4880   if (bs != NULL && BSLen (bs) < 1) {
4881     bs = BSFree (bs);
4882   }
4883   if (bs == NULL) return FALSE;
4884 
4885   /* overlap turned into replacement sequence */
4886 
4887   oldbsp = udp->oldbsp;
4888   newbsp = udp->newbsp;
4889   newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
4890   newbsp->seq_data = (SeqDataPtr) bs;
4891   newbsp->seq_data_type = Seq_code_iupacna;
4892   newbsp->length = newlen;
4893 
4894   /* then finish by offsetting features */
4895 
4896   return ExtendFeatures (udp, udp->new5);
4897 }
4898 
Extend5Prime(UpsDataPtr udp)4899 static Boolean Extend5Prime (UpsDataPtr udp)
4900 
4901 {
4902   ByteStorePtr  bs;
4903   Char          ch;
4904   Int4          i, newlen;
4905   BioseqPtr     newbsp;
4906   BioseqPtr     oldbsp;
4907   CharPtr       ptr, str, tmp;
4908 
4909   /* construct replacement sequence by extending old sequence */
4910 
4911   newlen = udp->new5 + udp->olda + udp->old3;
4912   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
4913   if (str == NULL)
4914     return FALSE;
4915   ptr = str;
4916 
4917   tmp = udp->seq2;
4918   for (i = 0; i < udp->new5; i++) {
4919     ch = *tmp;
4920     *ptr = ch;
4921     tmp++;
4922     ptr++;
4923   }
4924 
4925   tmp = udp->seq1 + udp->old5;
4926   for (i = 0; i < udp->olda + udp->old3; i++) {
4927     ch = *tmp;
4928     *ptr = ch;
4929     tmp++;
4930     ptr++;
4931   }
4932 
4933   *ptr = '\0';
4934   bs = BSNew (newlen);
4935   BSWrite (bs, (VoidPtr) str, newlen);
4936 
4937   udp->seq2 = MemFree (udp->seq2);
4938   udp->seq2 = str;
4939 
4940   if (bs != NULL && BSLen (bs) < 1) {
4941     bs = BSFree (bs);
4942   }
4943   if (bs == NULL) return FALSE;
4944 
4945   /* overlap turned into replacement sequence */
4946 
4947   oldbsp = udp->oldbsp;
4948   newbsp = udp->newbsp;
4949   newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
4950   newbsp->seq_data = (SeqDataPtr) bs;
4951   newbsp->seq_data_type = Seq_code_iupacna;
4952   newbsp->length = newlen;
4953 
4954   /* then finish by offsetting features */
4955 
4956   return ExtendFeatures (udp, udp->new5);
4957 }
4958 
Extend3Prime(UpsDataPtr udp)4959 static Boolean Extend3Prime (UpsDataPtr udp)
4960 
4961 {
4962   ByteStorePtr  bs;
4963   Char          ch;
4964   Int4          i, newlen;
4965   BioseqPtr     newbsp;
4966   BioseqPtr     oldbsp;
4967   CharPtr       ptr, str, tmp;
4968 
4969   /* construct replacement sequence by extending old sequence */
4970 
4971   newlen = udp->old5 + udp->olda + udp->new3;
4972   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
4973   if (str == NULL)
4974     return FALSE;
4975   ptr = str;
4976 
4977   tmp = udp->seq1;
4978   for (i = 0; i < udp->old5 + udp->olda; i++) {
4979     ch = *tmp;
4980     *ptr = ch;
4981     tmp++;
4982     ptr++;
4983   }
4984 
4985   tmp = udp->seq2 + udp->new5 + udp->newa;
4986   for (i = 0; i < udp->new3; i++) {
4987     ch = *tmp;
4988     *ptr = ch;
4989     tmp++;
4990     ptr++;
4991   }
4992 
4993   *ptr = '\0';
4994   bs = BSNew (newlen);
4995   BSWrite (bs, (VoidPtr) str, newlen);
4996 
4997   udp->seq2 = MemFree (udp->seq2);
4998   udp->seq2 = str;
4999 
5000   if (bs != NULL && BSLen (bs) < 1) {
5001     bs = BSFree (bs);
5002   }
5003   if (bs == NULL) return FALSE;
5004 
5005   /* overlap turned into replacement sequence */
5006 
5007   oldbsp = udp->oldbsp;
5008   newbsp = udp->newbsp;
5009   newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
5010   newbsp->seq_data = (SeqDataPtr) bs;
5011   newbsp->seq_data_type = Seq_code_iupacna;
5012   newbsp->length = newlen;
5013 
5014   /* no offset, but ExtendFeatures finishes switch */
5015 
5016   return ExtendFeatures (udp, 0);
5017 }
5018 
ExtendOneSequence(UpsDataPtr udp)5019 static Boolean ExtendOneSequence (UpsDataPtr udp)
5020 {
5021   Boolean      update = FALSE;
5022   MsgAnswer    ans;
5023   Uint2        entityID;
5024   CharPtr      errmsg = NULL;
5025 
5026 
5027   if (udp == NULL) return FALSE;
5028 
5029   switch (udp->rmcval) {
5030     case UPDATE_REPLACE :
5031       if (udp->old5 > 0 && udp->old3 > 0) {
5032         errmsg = "Unaligned sequence at 5' and 3' ends.  Do you wish to proceed?";
5033       } else if (udp->old5 > 0) {
5034         errmsg = "Unaligned sequence at 5' end.  Do you wish to proceed?";
5035       } else if (udp->old3 > 0) {
5036         errmsg = "Unaligned sequence at 3' end.  Do you wish to proceed?";
5037       }
5038       break;
5039     case UPDATE_EXTEND5 :
5040       if (udp->old5 > 0) {
5041         errmsg = "Unaligned sequence at 5' end.  Do you wish to proceed?";
5042       }
5043       break;
5044     case UPDATE_EXTEND3 :
5045       if (udp->old3 > 0) {
5046         errmsg = "Unaligned sequence at 3' end.  Do you wish to proceed?";
5047       }
5048       break;
5049     default :
5050       break;
5051   }
5052   if (errmsg != NULL) {
5053     ans = Message (MSG_YN, "%s", errmsg);
5054     if (ans == ANS_NO) {
5055       return FALSE;
5056     }
5057   }
5058 
5059   switch (udp->rmcval) {
5060     case UPDATE_REPLACE :
5061       if (ExtendBothEnds (udp)) {
5062         update = TRUE;
5063       }
5064       break;
5065     case UPDATE_EXTEND5:
5066       if (udp->salp == NULL) {
5067         if (Merge5PrimeNoOverlap (udp)) {
5068           update = TRUE;
5069         }
5070       } else if (Extend5Prime (udp)) {
5071         update = TRUE;
5072       }
5073       break;
5074     case UPDATE_EXTEND3 :
5075       if (udp->salp == NULL) {
5076         if (Merge3PrimeNoOverlap (udp)) {
5077           update = TRUE;
5078         }
5079       } else if (Extend3Prime (udp)) {
5080         update = TRUE;
5081       }
5082       break;
5083     default :
5084       break;
5085   }
5086 
5087   if (update) {
5088 
5089     entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
5090     if (GetStatus (udp->add_cit_subs))
5091     {
5092       AddCitSubToUpdatedSequence ( udp->oldbsp, entityID, kSubmitterUpdateText);
5093     }
5094   }
5095   return update;
5096 }
5097 
OpenSequenceUpdateLog(UpsDataPtr udp)5098 static void OpenSequenceUpdateLog (UpsDataPtr udp)
5099 {
5100   if (udp == NULL || udp->log_fp != NULL)
5101   {
5102   	return;
5103   }
5104   TmpNam (udp->log_path);
5105   udp->log_fp = FileOpen (udp->log_path, "wb");
5106 }
5107 
CloseOutSequenceUpdateLog(UpsDataPtr udp)5108 static void CloseOutSequenceUpdateLog (UpsDataPtr udp)
5109 {
5110   if (udp == NULL || udp->log_fp == NULL)
5111   {
5112     return;
5113   }
5114   FileClose (udp->log_fp);
5115   udp->log_fp = NULL;
5116   if (udp->data_in_log) {
5117     LaunchGeneralTextViewer (udp->log_path, "Protein changes");
5118     udp->data_in_log = FALSE;
5119   }
5120   FileRemove (udp->log_path);
5121 }
5122 
5123 
5124 static Boolean PrepareToUpdateSequences (UpsDataPtr udp);
5125 static Boolean PrepareUpdatePtr (UpsDataPtr    udp);
5126 static ForM UpdateSequenceForm (UpsDataPtr udp);
5127 static void UpdateOneSequence (
5128   UpsDataPtr   udp,
5129   Int2         sfbval,
5130   Boolean      add_cit_subs,
5131   Boolean      update_proteins);
5132 
5133 
FindNewCDSStop(SeqLocPtr slp,BioseqPtr bsp,Int4 prot_len)5134 static Int4 FindNewCDSStop (SeqLocPtr slp, BioseqPtr bsp, Int4 prot_len)
5135 {
5136   Int4      loc_len, tot_len = 0;
5137   SeqLocPtr this_slp;
5138   Int4      curr_start;
5139 
5140   for (this_slp = SeqLocFindNext (slp, NULL);
5141        this_slp != NULL;
5142        this_slp = SeqLocFindNext (slp, this_slp))
5143   {
5144     loc_len = SeqLocLen (this_slp);
5145     curr_start = GetOffsetInBioseq (this_slp, bsp, SEQLOC_START);
5146     if (loc_len + tot_len > prot_len)
5147     {
5148       curr_start = GetOffsetInBioseq (this_slp, bsp, SEQLOC_START);
5149       if (SeqLocStrand (this_slp) == Seq_strand_minus)
5150       {
5151         return curr_start - (prot_len - tot_len) + 1;
5152       }
5153       else
5154       {
5155         return curr_start + prot_len - tot_len - 1;
5156       }
5157     }
5158     tot_len += loc_len;
5159   }
5160   return tot_len;
5161 }
5162 
5163 
FixProteinString(SeqFeatPtr sfp,Uint1 strand,Boolean truncate_proteins,Boolean PNTR truncated,Boolean PNTR contains_start,Boolean PNTR contains_stop)5164 static CharPtr FixProteinString
5165 (SeqFeatPtr    sfp,
5166  Uint1         strand,
5167  Boolean       truncate_proteins,
5168  Boolean PNTR  truncated,
5169  Boolean PNTR  contains_start,
5170  Boolean PNTR  contains_stop)
5171 {
5172   ByteStorePtr bs;
5173   BioseqPtr    nucBsp;
5174   CharPtr      newprot;
5175   CharPtr      ptr;
5176   Char         ch;
5177   Int4         start, stop, new_stop, prot_len;
5178   Boolean      changed;
5179   CdRegionPtr  crp;
5180 
5181   if (sfp == NULL || truncated == NULL
5182       || contains_start == NULL
5183       || contains_stop == NULL) {
5184     return NULL;
5185   }
5186 
5187   bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
5188   if (bs == NULL) return NULL;
5189   newprot = BSMerge (bs, NULL);
5190   bs = BSFree (bs);
5191   if (newprot == NULL) return NULL;
5192 
5193   ptr = newprot;
5194   ch = *ptr;
5195   if (ch == 'M') {
5196     *contains_start = TRUE;
5197   } else {
5198     *contains_start = FALSE;
5199   }
5200   *contains_stop = FALSE;
5201   *truncated = FALSE;
5202   while (ch != '\0')
5203   {
5204     *ptr = TO_UPPER (ch);
5205     if (ch == '*') {
5206       *contains_stop = TRUE;
5207       if (*(ptr + 1) == 0 || truncate_proteins) {
5208         *ptr = 0;
5209         if (truncate_proteins && *(ptr + 1) != 0) {
5210           *truncated = TRUE;
5211           nucBsp = BioseqFindFromSeqLoc (sfp->location);
5212           if (nucBsp == NULL) return newprot;
5213           start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5214           stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5215           prot_len = (1 + ptr - newprot) * 3;
5216           if (sfp->data.choice == SEQFEAT_CDREGION) {
5217             crp = (CdRegionPtr) sfp->data.value.ptrvalue;
5218             if (crp != NULL) {
5219               if (crp->frame == 2) {
5220                 prot_len += 1;
5221               } else if (crp->frame == 3) {
5222                 prot_len += 2;
5223               }
5224             }
5225           }
5226           new_stop = FindNewCDSStop (sfp->location, nucBsp, prot_len);
5227           if (strand == Seq_strand_minus) {
5228             sfp->location = SeqLocDelete (sfp->location, SeqLocId (sfp->location),
5229                           stop, new_stop - 1, FALSE, &changed);
5230           } else {
5231             sfp->location = SeqLocDelete (sfp->location, SeqLocId (sfp->location),
5232                           new_stop + 1, stop, FALSE, &changed);
5233           }
5234         }
5235         return newprot;
5236       }
5237     }
5238     ptr++;
5239     ch = *ptr;
5240   }
5241   return newprot;
5242 }
5243 
5244 /* This function will truncate base pairs to make the length of the CDS
5245  * a multiple of three.  If truncation occurs, the function returns TRUE,
5246  * otherwise the function returns FALSE.
5247  */
ShiftStopForLengthChange(SeqLocPtr slp,BioseqPtr nucBsp,Int4 transl_except_len,Boolean PNTR changed)5248 static SeqLocPtr ShiftStopForLengthChange
5249 (SeqLocPtr slp,
5250  BioseqPtr nucBsp,
5251  Int4      transl_except_len,
5252  Boolean PNTR changed)
5253 {
5254   Int4      start, stop, new_stop;
5255   Uint1     strand;
5256   SeqIdPtr  sip;
5257   Int4      len;
5258 
5259   if (slp == NULL || nucBsp == NULL || changed == NULL) {
5260     return NULL;
5261   }
5262 
5263   *changed = FALSE;
5264 
5265   start = GetOffsetInBioseq (slp, nucBsp, SEQLOC_START);
5266   stop = GetOffsetInBioseq (slp, nucBsp, SEQLOC_STOP);
5267   new_stop = stop;
5268   strand = SeqLocStrand (slp);
5269   len = SeqLocLen (slp);
5270 
5271   if (strand == Seq_strand_minus) {
5272     if (len % 3 != transl_except_len) {
5273       new_stop += len % 3 + transl_except_len;
5274       sip = SeqLocId (slp);
5275       slp = SeqLocDelete (slp, sip, stop, new_stop - 1, FALSE, changed);
5276       if (slp == NULL) {
5277         return NULL;
5278       }
5279     }
5280   } else {
5281     if (len % 3 != transl_except_len) {
5282       new_stop -= len % 3 - transl_except_len;
5283       sip = SeqLocId (slp);
5284       slp = SeqLocDelete (slp, sip, new_stop + 1, stop, FALSE, changed);
5285       if (slp == NULL) {
5286         return NULL;
5287       }
5288     }
5289   }
5290   return slp;
5291 }
5292 
5293 extern SeqLocPtr
ExpandSeqLoc(Int4 start,Int4 stop,Uint1 strand,BioseqPtr bsp,SeqLocPtr slp)5294 ExpandSeqLoc
5295 (Int4 start,
5296  Int4 stop,
5297  Uint1 strand,
5298  BioseqPtr bsp,
5299  SeqLocPtr slp)
5300 {
5301   Int4      curr_start, curr_stop, tmp_start, tmp_stop;
5302   SeqLocPtr this_slp;
5303 
5304   if (slp == NULL) return NULL;
5305 
5306   if (slp->choice == SEQLOC_INT || slp->choice == SEQLOC_PNT) {
5307     slp = expand_seq_loc (start, stop, strand, slp);
5308   } else {
5309     curr_start = GetOffsetInBioseq (slp, bsp, SEQLOC_START);
5310     curr_stop = GetOffsetInBioseq (slp, bsp, SEQLOC_STOP);
5311     for (this_slp = SeqLocFindNext (slp, NULL);
5312          this_slp != NULL;
5313          this_slp = SeqLocFindNext (slp, this_slp))
5314     {
5315       tmp_start = GetOffsetInBioseq (this_slp, bsp, SEQLOC_START);
5316       tmp_stop = GetOffsetInBioseq (this_slp, bsp, SEQLOC_STOP);
5317       if (strand == Seq_strand_minus) {
5318         if (tmp_start == curr_start && tmp_start < stop) {
5319           this_slp = expand_seq_loc (tmp_stop, stop, strand, this_slp);
5320           tmp_start = stop;
5321         }
5322         if (tmp_stop == curr_stop && tmp_stop > start) {
5323           this_slp = expand_seq_loc (start, tmp_start, strand, this_slp);
5324         }
5325       } else {
5326         if (tmp_start == curr_start && tmp_start > start) {
5327           this_slp = expand_seq_loc (start, tmp_stop, strand, this_slp);
5328           tmp_start = start;
5329         }
5330         if (tmp_stop == curr_stop && tmp_stop < stop) {
5331           this_slp = expand_seq_loc (tmp_start, stop, strand, this_slp);
5332         }
5333       }
5334     }
5335   }
5336   return slp;
5337 }
5338 
ShiftLocationForFrame(SeqLocPtr slp,Uint1 frame,BioseqPtr nucBsp)5339 static SeqLocPtr ShiftLocationForFrame
5340 (SeqLocPtr slp,
5341  Uint1 frame,
5342  BioseqPtr nucBsp)
5343 {
5344   Int4      max_stop, start, stop;
5345   Uint1     strand;
5346   SeqIdPtr  sip;
5347   Int4      offset, new_start;
5348   Boolean   changed;
5349 
5350 
5351   if (slp == NULL || nucBsp == NULL) return NULL;
5352   if (frame == 0 || frame == 1) return slp;
5353 
5354   start = GetOffsetInBioseq (slp, nucBsp, SEQLOC_START);
5355   stop = GetOffsetInBioseq (slp, nucBsp, SEQLOC_STOP);
5356   strand = SeqLocStrand (slp);
5357   max_stop = nucBsp->length - 1;
5358   new_start = start;
5359 
5360   offset = frame - 1;
5361   sip = SeqLocId (slp);
5362   if (strand == Seq_strand_minus) {
5363     stop -= offset;
5364     new_start = start - offset;
5365     if ((1 + new_start - stop ) % 3 != 0) {
5366       new_start -= (1 + new_start - stop) % 3;
5367     }
5368     if (stop < 0) stop = 0;
5369     slp = ExpandSeqLoc (stop, start, strand, nucBsp, slp);
5370     if (new_start < 0) new_start = 0;
5371     if (new_start < start) {
5372       slp = SeqLocDelete (slp, sip, new_start + 1, start, FALSE, &changed);
5373     }
5374   } else {
5375     stop += offset;
5376     new_start = start + offset;
5377     if ((1 + stop - new_start) % 3 != 0) {
5378       new_start += (1 + stop - new_start) % 3;
5379     }
5380     if (stop > max_stop) stop = max_stop;
5381     slp = ExpandSeqLoc (start, stop, strand, nucBsp, slp);
5382     if (start > max_stop) start = max_stop;
5383     if (new_start > start) {
5384       slp = SeqLocDelete (slp, sip, start, new_start - 1, FALSE, &changed);
5385     }
5386   }
5387   return slp;
5388 }
5389 
GetTranslationTable(CdRegionPtr crp,Boolean PNTR table_is_local)5390 static TransTablePtr GetTranslationTable (CdRegionPtr crp, Boolean PNTR table_is_local)
5391 {
5392   TransTablePtr tbl = NULL;
5393   ValNodePtr    vnp;
5394   Int2          genCode = 0;
5395   Char          str [32];
5396 
5397   if (crp == NULL || table_is_local == NULL) return NULL;
5398 
5399   *table_is_local = FALSE;
5400   /* find genetic code */
5401 
5402   if (crp->genetic_code != NULL) {
5403     vnp = (ValNodePtr) crp->genetic_code->data.ptrvalue;
5404     while (vnp != NULL) {
5405       if (vnp->choice == 2) {
5406         genCode = (Int2) vnp->data.intvalue;
5407       }
5408       vnp = vnp->next;
5409     }
5410   }
5411 
5412   if (genCode == 7) {
5413     genCode = 4;
5414   } else if (genCode == 8) {
5415     genCode = 1;
5416   } else if (genCode == 0) {
5417     genCode = 1;
5418   }
5419 
5420   /* set up translation table */
5421   /* set app property name for storing desired FSA */
5422 
5423   sprintf (str, "TransTableFSAforGenCode%d", (int) genCode);
5424 
5425   /* get FSA for desired genetic code if it already exists */
5426 
5427   tbl = (TransTablePtr) GetAppProperty (str);
5428   if (tbl == NULL) {
5429     tbl = TransTableNew (genCode);
5430     *table_is_local = TRUE;
5431   }
5432   return tbl;
5433 }
5434 
ExtendProtein5(SeqFeatPtr sfp,Uint2 input_entityID,Boolean force_partial)5435 static CharPtr ExtendProtein5
5436 (SeqFeatPtr sfp,
5437  Uint2      input_entityID,
5438  Boolean    force_partial)
5439 {
5440   CdRegionPtr   crp;
5441   TransTablePtr tbl = NULL;
5442   Boolean       table_is_local = FALSE;
5443   SeqLocPtr     test_slp;
5444   SeqIdPtr      sip;
5445   BioseqPtr     nucBsp;
5446   Int4          start, new_start;
5447   Int4          stop, new_stop;
5448   Int4          increment = 3000;
5449   Int4          offset;
5450   Uint1         strand;
5451   Boolean       found_start = FALSE;
5452   Boolean       found_stop = FALSE;
5453   Boolean       stop_looking = FALSE;
5454   Int4          dna_len;
5455   CharPtr       bases;
5456   Int4          total;
5457   Int2          state;
5458   CharPtr       codon_start;
5459   Boolean       partial3, partial5;
5460   Boolean       contains_start, contains_stop;
5461   Boolean       changed;
5462   CharPtr       newprot;
5463   Boolean       truncated;
5464 
5465   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION
5466       || (crp = (CdRegionPtr)sfp->data.value.ptrvalue) == NULL) {
5467     return NULL;
5468   }
5469   nucBsp = GetBioseqGivenSeqLoc (sfp->location, input_entityID);
5470   if (nucBsp == NULL) return NULL;
5471 
5472   tbl = GetTranslationTable (crp, &table_is_local);
5473   if (tbl == NULL) return NULL;
5474 
5475   test_slp = SeqLocMerge (nucBsp, sfp->location, NULL, FALSE, FALSE, FALSE);
5476   strand = SeqLocStrand (sfp->location);
5477   sip = SeqLocId (sfp->location);
5478   offset = -1;
5479 
5480   start = GetOffsetInBioseq (test_slp, nucBsp, SEQLOC_START);
5481   if (start == 0)
5482   {
5483   	stop_looking = TRUE;
5484   }
5485 
5486   while (((! found_start && ! found_stop) || force_partial) && ! stop_looking) {
5487     start = GetOffsetInBioseq (test_slp, nucBsp, SEQLOC_START);
5488     stop = GetOffsetInBioseq (test_slp, nucBsp, SEQLOC_STOP);
5489     if (strand == Seq_strand_minus) {
5490       new_start = start + increment;
5491       new_stop = start + 1;
5492       if (new_start > nucBsp->length - 1) {
5493         new_start = start + ((Int4)((nucBsp->length - 1 - start) / 3)) * 3;
5494         stop_looking = TRUE;
5495       }
5496       test_slp = ExpandSeqLoc (stop, new_start, strand, nucBsp, test_slp);
5497       test_slp = SeqLocDelete (test_slp, sip, stop, start, FALSE, &changed);
5498     } else {
5499       new_start = start - increment;
5500       new_stop = start - 1;
5501       if (new_start < 0) {
5502         new_start = start % 3;
5503         stop_looking = TRUE;
5504       }
5505       test_slp = ExpandSeqLoc (new_start, stop, strand, nucBsp, test_slp);
5506       test_slp = SeqLocDelete (test_slp, sip, start, stop, FALSE, &changed);
5507     }
5508     dna_len = SeqLocLen (test_slp);
5509     bases = ReadCodingRegionBases (test_slp, dna_len, crp->frame, &total);
5510     if (bases == NULL) {
5511       stop_looking = TRUE;
5512     } else {
5513       state = 0;
5514       codon_start = bases + StringLen (bases) - 3;
5515       while (codon_start >= bases && ! found_start && ! found_stop) {
5516         state = 0;
5517         state = NextCodonState (tbl, state, (Uint1)*codon_start);
5518         state = NextCodonState (tbl, state, (Uint1)*(codon_start + 1));
5519         state = NextCodonState (tbl, state, (Uint1)*(codon_start + 2));
5520         if (IsOrfStart (tbl, state, TTBL_TOP_STRAND)) {
5521           found_start = TRUE;
5522           if (strand == Seq_strand_minus) {
5523             offset = new_start - (codon_start - bases);
5524           } else {
5525             offset = new_start + codon_start - bases;
5526           }
5527         } else if (IsOrfStop (tbl, state, TTBL_TOP_STRAND)) {
5528           found_stop = TRUE;
5529         } else {
5530           codon_start -= 3;
5531         }
5532       }
5533       MemFree (bases);
5534     }
5535   }
5536 
5537   SeqLocFree (test_slp);
5538   if (! found_stop) {
5539     start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5540     stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5541     if (found_start) {
5542       if (strand == Seq_strand_minus) {
5543         sfp->location = ExpandSeqLoc (stop, offset, strand, nucBsp, sfp->location);
5544       } else {
5545         sfp->location = ExpandSeqLoc (offset, stop, strand, nucBsp, sfp->location);
5546       }
5547     } else {
5548       CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5549       SetSeqLocPartial (sfp->location, TRUE, partial3);
5550       sfp->partial = TRUE;
5551       if (crp->frame == 0)
5552       {
5553         crp->frame = 1;
5554       }
5555       if (strand == Seq_strand_minus) {
5556         sfp->location = ExpandSeqLoc (stop, nucBsp->length - 1, strand, nucBsp, sfp->location);
5557         crp->frame = (nucBsp->length - 1 - start + crp->frame - 1) % 3 + 1;
5558       } else {
5559         sfp->location = ExpandSeqLoc (0, stop, strand, nucBsp, sfp->location);
5560         crp->frame = (start + crp->frame - 1) % 3 + 1;
5561       }
5562     }
5563   }
5564   newprot = FixProteinString (sfp, strand, FALSE, &truncated,
5565                               &contains_start, &contains_stop);
5566   if (table_is_local) {
5567     TransTableFree (tbl);
5568   }
5569 
5570   return newprot;
5571 }
5572 
5573 
ExtendProtein3(SeqFeatPtr sfp,Uint2 input_entityID,Boolean force_partial)5574 extern CharPtr ExtendProtein3
5575 (SeqFeatPtr sfp,
5576  Uint2      input_entityID,
5577  Boolean    force_partial)
5578 {
5579   BioseqPtr nucBsp;
5580   Int4      max_stop, min_start, start, stop;
5581   Uint1     strand;
5582   Boolean   contains_start, contains_stop;
5583   Int4      increment = 3000;
5584   CharPtr   newprot;
5585   Boolean   partial5, partial3;
5586   Boolean   truncated;
5587 
5588   if (sfp == NULL) return NULL;
5589 
5590   nucBsp = GetBioseqGivenSeqLoc (sfp->location, input_entityID);
5591   if (nucBsp == NULL) return NULL;
5592 
5593   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5594   start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5595   stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5596   strand = SeqLocStrand (sfp->location);
5597   max_stop = nucBsp->length - 1;
5598   if (stop > start) {
5599     while (max_stop % 3 != stop % 3) {
5600       max_stop --;
5601     }
5602     min_start = start %3;
5603   } else {
5604     while (max_stop % 3 != start % 3) {
5605       max_stop --;
5606     }
5607     min_start = stop % 3;
5608   }
5609 
5610   contains_stop = FALSE;
5611   contains_start = FALSE;
5612   newprot = NULL;
5613   /* need to initialize newprot in case we're already at the edge */
5614   if ((strand != Seq_strand_minus && stop == max_stop)
5615       || (strand == Seq_strand_minus && stop == min_start))
5616   {
5617   	newprot = FixProteinString (sfp, strand, FALSE, &truncated,
5618                               &contains_start, &contains_stop);
5619   }
5620   while ((! contains_stop || force_partial) &&
5621          (   (strand == Seq_strand_minus && stop > min_start)
5622           || (strand != Seq_strand_minus && stop < max_stop)))
5623   {
5624     if (newprot != NULL) {
5625       MemFree (newprot);
5626       newprot = NULL;
5627     }
5628     if (strand == Seq_strand_minus) {
5629       stop -= increment;
5630       if (stop < min_start) {
5631         stop = min_start;
5632       }
5633       sfp->location = ExpandSeqLoc (stop, start, strand, nucBsp, sfp->location);
5634     } else {
5635       stop += increment;
5636       if (stop > max_stop) {
5637         stop = max_stop;
5638       }
5639       sfp->location = ExpandSeqLoc (start, stop, strand, nucBsp, sfp->location);
5640     }
5641     newprot = FixProteinString (sfp, strand, TRUE, &truncated,
5642                               &contains_start, &contains_stop);
5643   }
5644 
5645   if (! contains_stop || force_partial) {
5646     start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5647     stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5648     if (strand == Seq_strand_minus) {
5649       sfp->location = ExpandSeqLoc (0, start, strand, nucBsp, sfp->location);
5650     } else {
5651       sfp->location = ExpandSeqLoc (start, nucBsp->length - 1, strand, nucBsp, sfp->location);
5652     }
5653     partial3 = TRUE;
5654     SetSeqLocPartial (sfp->location, partial5, TRUE);
5655   }
5656   return newprot;
5657 }
5658 
MergeOverlapsForThisFeature(SeqFeatPtr sfp)5659 static Boolean MergeOverlapsForThisFeature (SeqFeatPtr sfp)
5660 {
5661   if (sfp == NULL) return FALSE;
5662   return ! sfp->excpt;
5663 }
5664 
5665 static Boolean
AdjustCDSForUpdate(SeqFeatPtr sfp,Uint2 input_entityID,Uint1 frame,Int4 transl_except_len,Boolean truncate_proteins,Boolean extend_proteins5,Boolean extend_proteins3,Boolean PNTR truncated,Boolean PNTR stop_shifted,Boolean PNTR extended5,Boolean PNTR extended3,BioseqPtr protBsp,BioseqPtr PNTR newbsp)5666 AdjustCDSForUpdate
5667 (SeqFeatPtr   sfp,
5668  Uint2        input_entityID,
5669  Uint1        frame,
5670  Int4         transl_except_len,
5671  Boolean      truncate_proteins,
5672  Boolean      extend_proteins5,
5673  Boolean      extend_proteins3,
5674  Boolean PNTR truncated,
5675  Boolean PNTR stop_shifted,
5676  Boolean PNTR extended5,
5677  Boolean PNTR extended3,
5678  BioseqPtr    protBsp,
5679  BioseqPtr PNTR newbsp)
5680 {
5681   ByteStorePtr  bs;
5682   CharPtr       newprot, ptr;
5683   SeqEntryPtr   nwsep;
5684   BioseqPtr     newBsp;
5685   Boolean       contains_start, contains_stop;
5686   Uint1         strand;
5687   SeqLocPtr     newloc;
5688   BioseqPtr     nucBsp;
5689   Boolean       partial5, partial3;
5690   CharPtr       seqnew = NULL, seqold = NULL;
5691   Boolean       rval = FALSE;
5692 
5693   if (sfp == NULL
5694     || sfp->idx.subtype != FEATDEF_CDS
5695     || sfp->product == NULL
5696     || protBsp == NULL
5697     || truncated == NULL || stop_shifted == NULL
5698     || extended5 == NULL || extended3 == NULL
5699     || newbsp == NULL)
5700   {
5701     return FALSE;
5702   }
5703 
5704   CheckSeqLocForPartial (sfp->location, &partial3, &partial5);
5705 
5706   nucBsp = GetBioseqGivenSeqLoc (sfp->location, input_entityID);
5707   if (nucBsp == NULL) return FALSE;
5708 
5709   newloc = SeqLocMergeExEx (nucBsp, sfp->location, NULL, FALSE, FALSE,
5710                             MergeOverlapsForThisFeature (sfp),
5711                             FALSE, FALSE, FALSE, FALSE);
5712 
5713   if (newloc == NULL) return FALSE;
5714   sfp->location = newloc;
5715   strand = SeqLocStrand (sfp->location);
5716   sfp->location = ShiftStopForLengthChange (sfp->location, nucBsp, transl_except_len, stop_shifted);
5717   if (sfp->location == NULL) {
5718     return FALSE;
5719   }
5720 
5721   sfp->location = ShiftLocationForFrame (sfp->location, frame, nucBsp);
5722 
5723   newprot = FixProteinString (sfp, strand, truncate_proteins, truncated,
5724                               &contains_start, &contains_stop);
5725 
5726   /* Must do 3' end first, otherwise may truncate at stops introduced by expanding 5' end for partiality */
5727   if ((! contains_stop && extend_proteins3 && transl_except_len == 0)
5728       || ((extend_proteins3 || partial3) && !truncate_proteins)) {
5729     MemFree (newprot);
5730     newprot = ExtendProtein3 (sfp, input_entityID, partial3 && !truncate_proteins);
5731     if (newprot == NULL) return FALSE;
5732     *extended3 = TRUE;
5733   } else {
5734     *extended3 = FALSE;
5735   }
5736   if (! contains_start && (extend_proteins5 || partial5)) {
5737     MemFree (newprot);
5738     newprot = ExtendProtein5 (sfp, input_entityID, partial5);
5739     if (newprot == NULL) return FALSE;
5740     *extended5 = TRUE;
5741   } else {
5742     *extended5 = FALSE;
5743   }
5744 
5745   sfp->partial = CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5746 
5747   bs = BSNew (1000);
5748   if (bs != NULL)
5749   {
5750     ptr = newprot;
5751     BSWrite (bs, (VoidPtr) ptr, (Int4) StringLen (ptr));
5752   }
5753   MemFree (newprot);
5754 
5755   newBsp = BioseqNew ();
5756   if (newBsp == NULL) {
5757     return FALSE;
5758   }
5759 
5760   newBsp->id = SeqIdParse ("lcl|ProtAlign");
5761   newBsp->repr = Seq_repr_raw;
5762   newBsp->mol = Seq_mol_aa;
5763   newBsp->seq_data_type = Seq_code_ncbieaa;
5764   newBsp->seq_data = (SeqDataPtr) bs;
5765   newBsp->length = BSLen (bs);
5766 
5767   /* create SeqEntry for temporary protein bioseq to live in */
5768   nwsep = SeqEntryNew ();
5769   nwsep->choice = 1;
5770   nwsep->data.ptrvalue = newBsp;
5771   SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) newBsp, nwsep);
5772 
5773   seqold = GetSequenceByBsp (protBsp);
5774   seqnew = GetSequenceByBsp (newBsp);
5775 
5776   if (StringCmp (seqold, seqnew) == 0
5777     || (contains_stop && ! *truncated
5778       && StringNCmp (seqold,
5779                      seqnew,
5780                      StringLen (seqold)) == 0))
5781   {
5782     SeqEntryFree (nwsep);
5783     rval = FALSE;
5784   }
5785   else
5786   {
5787     *newbsp = newBsp;
5788     rval = TRUE;
5789   }
5790 
5791   return rval;
5792 }
5793 
5794 
WarnNoProteinUpdate(BioseqPtr bsp)5795 static void WarnNoProteinUpdate (BioseqPtr bsp)
5796 {
5797   Char     acc_str [256];
5798   CharPtr  warn_format = "Protein %s has not been updated - you must manually re-translate the coding regions and move any protein features";
5799   CharPtr  warn_msg;
5800 
5801   if (bsp == NULL || bsp->id == NULL) return;
5802   SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
5803   warn_msg = (CharPtr) MemNew (StringLen (warn_format) + StringLen (acc_str));
5804   if (warn_msg == NULL) return;
5805   sprintf (warn_msg, warn_format, acc_str);
5806   ErrPostEx (SEV_ERROR, 0, 0, warn_msg);
5807   MemFree (warn_msg);
5808 }
5809 
5810 
LogFrameChange(FILE * fp,BioseqPtr bsp,Uint1 frame)5811 static void LogFrameChange (FILE *fp, BioseqPtr bsp, Uint1 frame)
5812 {
5813   Char     acc_str [256];
5814 
5815   if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
5816   SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
5817   fprintf (fp, "Changed frame for %s to %d\n", acc_str, frame);
5818 }
5819 
5820 
LogProteinTruncate(FILE * fp,BioseqPtr bsp)5821 static void LogProteinTruncate (FILE *fp, BioseqPtr bsp)
5822 {
5823   Char     acc_str [256];
5824 
5825   if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
5826   SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
5827   fprintf (fp, "Truncated protein %s at stop\n", acc_str);
5828 }
5829 
5830 
LogProteinStopShift(FILE * fp,BioseqPtr bsp)5831 static void LogProteinStopShift (FILE *fp, BioseqPtr bsp)
5832 {
5833   Char     acc_str [256];
5834 
5835   if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
5836   SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
5837   fprintf (fp, "Adjusted length of CDS for protein %s to be multiple of 3\n", acc_str);
5838 }
5839 
5840 
LogProteinExtend5(FILE * fp,BioseqPtr bsp)5841 static void LogProteinExtend5 (FILE *fp, BioseqPtr bsp)
5842 {
5843   Char     acc_str [256];
5844 
5845   if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
5846   SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
5847   fprintf (fp, "Extended protein %s on 5' end\n", acc_str);
5848 }
5849 
5850 
LogProteinExtend3(FILE * fp,BioseqPtr bsp)5851 static void LogProteinExtend3 (FILE *fp, BioseqPtr bsp)
5852 {
5853   Char     acc_str [256];
5854 
5855   if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
5856   SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
5857   fprintf (fp, "Extended protein %s on 3' end\n", acc_str);
5858 }
5859 
LogGeneCorrection(FILE * fp,SeqFeatPtr gene,SeqLocPtr oldloc)5860 static void LogGeneCorrection (FILE *fp, SeqFeatPtr gene, SeqLocPtr oldloc)
5861 {
5862   CharPtr           loc1, loc2;
5863   SeqMgrFeatContext gcontext;
5864   SeqFeatPtr        found_gene;
5865 
5866   if (fp == NULL || gene == NULL || gene->location == NULL || oldloc == NULL) return;
5867   found_gene = SeqMgrGetDesiredFeature (gene->idx.entityID, NULL, 0, 0, gene, &gcontext);
5868   if (found_gene == NULL) return;
5869   loc1 = SeqLocPrint (gene->location);
5870   loc2 = SeqLocPrint (oldloc);
5871   if (loc1 != NULL && loc2 != NULL && StringCmp (loc1, loc2) != 0) {
5872     fprintf (fp, "Moved gene %s from %s to %s\n", gcontext.label, loc2, loc1);
5873   }
5874   MemFree (loc1);
5875   MemFree (loc2);
5876 }
5877 
5878 
LogGeneBadCorrection(FILE * fp,SeqFeatPtr gene)5879 static void LogGeneBadCorrection (FILE *fp, SeqFeatPtr gene)
5880 {
5881   SeqMgrFeatContext gcontext;
5882   SeqFeatPtr        found_gene;
5883 
5884   if (fp == NULL || gene == NULL || gene->location == NULL) return;
5885   found_gene = SeqMgrGetDesiredFeature (gene->idx.entityID, NULL, 0, 0, gene, &gcontext);
5886   if (found_gene == NULL) return;
5887   fprintf (fp, "Please examine gene %s, new gene may be too large\n", gcontext.label);
5888 }
5889 
5890 
CorrectCDSGene(SeqFeatPtr sfp,SeqFeatPtr gene_sfp,FILE * fp,Boolean PNTR data_in_log)5891 static void CorrectCDSGene
5892 (SeqFeatPtr sfp,
5893  SeqFeatPtr gene_sfp,
5894  FILE *fp,
5895  Boolean PNTR data_in_log)
5896 {
5897   BioseqPtr bsp;
5898   Boolean   partial5, partial3;
5899   SeqLocPtr log_slp, new_slp;
5900   Int2      res;
5901 
5902   if (sfp == NULL || gene_sfp == NULL || fp == NULL
5903       || data_in_log == NULL){
5904     return;
5905   }
5906   bsp = BioseqFindFromSeqLoc (sfp->location);
5907   if (bsp == NULL) return;
5908   new_slp = SeqLocMerge (bsp, sfp->location, NULL, TRUE, FALSE, FALSE);
5909   res = SeqLocCompare (gene_sfp->location, new_slp);
5910   if (res == SLC_A_EQ_B) {
5911     SeqLocFree (new_slp);
5912     return;
5913   }
5914   if (SeqLocLen (gene_sfp->location) > SeqLocLen (new_slp)) {
5915     SeqLocFree (new_slp);
5916     new_slp = SeqLocMerge (bsp, sfp->location, gene_sfp->location, TRUE, FALSE, FALSE);
5917     LogGeneBadCorrection (fp, gene_sfp);
5918   }
5919   log_slp = SeqLocMerge (bsp, sfp->location, NULL, FALSE, FALSE, FALSE);
5920 
5921   *data_in_log = TRUE;
5922   SeqLocFree (gene_sfp->location);
5923   gene_sfp->location = new_slp;
5924   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5925   SetSeqLocPartial (gene_sfp->location, partial5, partial3);
5926   gene_sfp->partial = sfp->partial;
5927   LogGeneCorrection (fp, gene_sfp, log_slp);
5928   SeqLocFree (log_slp);
5929 }
5930 
FixProtRefPtrs(ValNodePtr feat_list)5931 static void FixProtRefPtrs (ValNodePtr feat_list)
5932 {
5933   ValNodePtr vnp;
5934   SeqFeatPtr sfp;
5935   Uint1      strand;
5936   BioseqPtr  bsp;
5937 
5938   if (feat_list == NULL) return;
5939   for (vnp = feat_list; vnp != NULL; vnp = vnp->next) {
5940     sfp = (SeqFeatPtr)vnp->data.ptrvalue;
5941     if (sfp == NULL) continue;
5942     bsp = BioseqFindFromSeqLoc (sfp->location);
5943     if (bsp == NULL) continue;
5944     strand = SeqLocStrand (sfp->location);
5945     if (strand == Seq_strand_minus) {
5946       sfp->location = ExpandSeqLoc (bsp->length - 1, 0, strand, bsp, sfp->location);
5947     } else {
5948       sfp->location = ExpandSeqLoc (0, bsp->length - 1, strand, bsp, sfp->location);
5949     }
5950   }
5951 }
5952 
5953 
Sqn_AlignForSequenceUpdate(BioseqPtr bsp1,BioseqPtr bsp2,BoolPtr revcomp)5954 static SeqAlignPtr Sqn_AlignForSequenceUpdate (BioseqPtr bsp1, BioseqPtr bsp2, BoolPtr revcomp)
5955 {
5956   return AlignForSequenceUpdate (bsp1, bsp2, revcomp, Sequin_GlobalAlign2Seq);
5957 }
5958 
5959 
PrepareUpdateAlignmentForProtein(SeqFeatPtr sfp,BioseqPtr protBsp,Uint2 input_entityID,FILE * fp,Boolean truncate_proteins,Boolean extend_proteins5,Boolean extend_proteins3,Boolean correct_cds_genes,Int4 transl_except_len,Boolean * data_in_log,SeqAlignPtr PNTR salpptr,BioseqPtr PNTR newbspptr)5960 static Boolean PrepareUpdateAlignmentForProtein
5961 (SeqFeatPtr sfp,
5962  BioseqPtr  protBsp,
5963  Uint2      input_entityID,
5964  FILE *     fp,
5965  Boolean    truncate_proteins,
5966  Boolean    extend_proteins5,
5967  Boolean    extend_proteins3,
5968  Boolean    correct_cds_genes,
5969  Int4       transl_except_len,
5970  Boolean    *data_in_log,
5971  SeqAlignPtr PNTR salpptr,
5972  BioseqPtr PNTR newbspptr)
5973 {
5974   Boolean       align_succeeded;
5975   Boolean       changed_frame;
5976   Uint1         frame_attempts;
5977   ErrSev        level;
5978   CdRegionPtr   crp;
5979   SeqLocPtr     orig_slp;
5980   Boolean       orig_partial;
5981   SeqFeatPtr    gene_sfp;
5982   SeqMgrFeatContext gcontext;
5983   Boolean       truncated, stop_shifted;
5984   Boolean       extended5, extended3;
5985   Uint1         old_frame;
5986   BioseqPtr     newBsp = NULL;
5987   Boolean       adjust_succeeded;
5988   SeqAlignPtr   salp = NULL;
5989   Boolean       revcomp;
5990 
5991   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION
5992       || (crp = (CdRegionPtr)sfp->data.value.ptrvalue) == NULL
5993       || protBsp == NULL
5994       || data_in_log == NULL) {
5995     return FALSE;
5996   }
5997 
5998   old_frame = crp->frame;
5999 
6000   orig_slp = sfp->location;
6001   orig_partial = sfp->partial;
6002   if (correct_cds_genes) {
6003     gene_sfp = SeqMgrGetOverlappingGene (sfp->location, &gcontext);
6004   }
6005   align_succeeded = FALSE;
6006   changed_frame = FALSE;
6007 
6008   level = ErrSetMessageLevel (SEV_MAX);
6009   for (frame_attempts = 1;
6010        frame_attempts < 4 && ! align_succeeded;
6011        frame_attempts ++) {
6012     if (sfp->location != orig_slp) {
6013       if (sfp->location->choice == 0) {
6014         SeqLocFree (sfp->location);
6015       }
6016       sfp->location = orig_slp;
6017     }
6018     sfp->partial = orig_partial;
6019     crp->frame = old_frame;
6020     if (newBsp != NULL) {
6021       newBsp = BioseqFree (newBsp);
6022     }
6023     truncated= FALSE;
6024     stop_shifted = FALSE;
6025     extended5 = FALSE;
6026     extended3 = FALSE;
6027     adjust_succeeded = AdjustCDSForUpdate (sfp,
6028                                            input_entityID,
6029                                            frame_attempts,
6030                                            transl_except_len,
6031                                            truncate_proteins,
6032                                            extend_proteins5,
6033                                            extend_proteins3,
6034                                            &truncated, &stop_shifted,
6035                                            &extended5, &extended3,
6036                                            protBsp, &newBsp);
6037     if (sfp->location == NULL || sfp->location->choice == 0)
6038     {
6039       sfp->location = orig_slp;
6040     }
6041     if (adjust_succeeded)
6042     {
6043       salp = Sqn_AlignForSequenceUpdate (protBsp, newBsp, &revcomp);
6044     }
6045     if (!adjust_succeeded || salp != NULL)
6046     {
6047       if (frame_attempts > 1) {
6048         changed_frame = TRUE;
6049         LogFrameChange (fp, protBsp, frame_attempts);
6050         *data_in_log = TRUE;
6051       }
6052       break;
6053     }
6054   }
6055   ErrSetMessageLevel (level);
6056   if (adjust_succeeded && salp == NULL)
6057   {
6058     /* put CD Region back to original state */
6059     crp->frame = old_frame;
6060     if (sfp->location != orig_slp) {
6061       SeqLocFree (sfp->location);
6062       sfp->location = orig_slp;
6063     }
6064     sfp->partial = orig_partial;
6065     WarnNoProteinUpdate (protBsp);
6066     newBsp = BioseqFree (newBsp);
6067     return FALSE;
6068   }
6069 
6070   if (truncated) {
6071     LogProteinTruncate (fp, protBsp);
6072     *data_in_log = TRUE;
6073   }
6074   if (stop_shifted) {
6075     LogProteinStopShift (fp, protBsp);
6076     *data_in_log = TRUE;
6077   }
6078   if (extended5) {
6079     LogProteinExtend5 (fp, protBsp);
6080     *data_in_log = TRUE;
6081   }
6082   if (extended3) {
6083     LogProteinExtend3 (fp, protBsp);
6084     *data_in_log = TRUE;
6085   }
6086 
6087   if (correct_cds_genes && gene_sfp != NULL) {
6088     CorrectCDSGene (sfp, gene_sfp, fp, data_in_log);
6089   }
6090   if (sfp->location != orig_slp) {
6091     SeqLocFree (orig_slp);
6092   }
6093 
6094   *salpptr = salp;
6095   *newbspptr = newBsp;
6096   return TRUE;
6097 }
6098 
6099 
CheckForIDCollision(BioseqPtr oldbsp,BioseqPtr newbsp,BoolPtr islocal)6100 static Boolean CheckForIDCollision (
6101   BioseqPtr oldbsp,
6102   BioseqPtr newbsp,
6103   BoolPtr islocal
6104 )
6105 
6106 {
6107   SeqIdPtr  sip;
6108 
6109   if (oldbsp == NULL || newbsp == NULL) return FALSE;
6110   for (sip = newbsp->id; sip != NULL; sip = sip->next) {
6111     if (SeqIdIn (sip, oldbsp->id)) {
6112       if (sip->choice == SEQID_LOCAL) {
6113         *islocal = TRUE;
6114       }
6115       return TRUE;
6116     }
6117   }
6118   return FALSE;
6119 }
6120 
6121 static CharPtr convPubDescMssg =
6122 "Do you wish to convert publications to apply only to the appropriate ranges?";
6123 
6124 #define UPDATE_SKIP_THIS    1
6125 #define UPDATE_SKIP_ALL     2
6126 #define UPDATE_REPLACE_THIS 3
6127 #define UPDATE_REPLACE_ALL  4
6128 #define UPDATE_CANCEL       5
6129 
6130 typedef struct noalignmentchoice
6131 {
6132   Boolean done;
6133   Boolean cancelled;
6134   GrouP   action_choice;
6135   Boolean skip_this;
6136   Boolean skip_all;
6137   Boolean replace_this;
6138   Boolean replace_all;
6139 } NoAlignmentChoiceData, PNTR NoAlignmentChoicePtr;
6140 
NoAlignmentChoiceOk(ButtoN b)6141 static void NoAlignmentChoiceOk (ButtoN b)
6142 {
6143   NoAlignmentChoicePtr nacp;
6144 
6145   nacp = (NoAlignmentChoicePtr) GetObjectExtra (b);
6146   if (nacp == NULL) return;
6147   nacp->cancelled = FALSE;
6148   nacp->done = TRUE;
6149 }
6150 
NoAlignmentChoiceCancel(ButtoN b)6151 static void NoAlignmentChoiceCancel (ButtoN b)
6152 {
6153   NoAlignmentChoicePtr nacp;
6154 
6155   nacp = (NoAlignmentChoicePtr) GetObjectExtra (b);
6156   if (nacp == NULL) return;
6157   nacp->cancelled = TRUE;
6158   nacp->done = TRUE;
6159 }
6160 
GetNoAlignmentChoice(SeqIdPtr id,Int2 previous_choice)6161 static Int2 GetNoAlignmentChoice (SeqIdPtr id, Int2 previous_choice)
6162 {
6163   Char                  buf [64];
6164   WindoW                w;
6165   GrouP                 h, g, c;
6166   ButtoN                b;
6167   NoAlignmentChoiceData nacd;
6168   Char                  promptstr[115];
6169   Int2                  no_aln_choice;
6170   SeqIdPtr              sip, sip_next;
6171 
6172   sip = SeqIdFindBest (id, 0);
6173   if (sip == NULL) return UPDATE_CANCEL;
6174   w = ModalWindow(-20, -13, -10, -10, NULL);
6175   if (w == NULL) return 0;
6176 
6177   h = HiddenGroup (w, -1, 0, NULL);
6178   g = HiddenGroup(h, 0, 4, NULL);
6179   sip_next = sip->next;
6180   sip->next = NULL;
6181   SeqIdWrite (sip, buf, PRINTID_REPORT, sizeof (buf) - 1);
6182   sip->next = sip_next;
6183   sprintf (promptstr, "There is no alignment between the sequences for %s.", buf);
6184   StaticPrompt (g, promptstr, 0, popupMenuHeight, programFont, 'l');
6185   StaticPrompt (g, "You may choose to :", 0, popupMenuHeight, programFont, 'l');
6186   nacd.action_choice = HiddenGroup (g, 0, 4, NULL);
6187   RadioButton (nacd.action_choice, "Skip This Sequence");
6188   RadioButton (nacd.action_choice, "Skip All Sequences without Alignments");
6189   RadioButton (nacd.action_choice, "Replace This Sequence");
6190   RadioButton (nacd.action_choice, "Replace All Sequences without Alignments");
6191   if (previous_choice > 0 && previous_choice < UPDATE_CANCEL)
6192   {
6193     SetValue (nacd.action_choice, previous_choice);
6194   }
6195   else
6196   {
6197     SetValue (nacd.action_choice, 1);
6198   }
6199   c = HiddenGroup (h, 2, 0, NULL);
6200   b = PushButton (c, "Ok", NoAlignmentChoiceOk);
6201   SetObjectExtra (b, &nacd, NULL);
6202   b = PushButton (c, "Cancel", NoAlignmentChoiceCancel);
6203   SetObjectExtra (b, &nacd, NULL);
6204 
6205   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
6206 
6207   nacd.cancelled = FALSE;
6208   nacd.done = FALSE;
6209   Show(w);
6210   Select (w);
6211   while (!nacd.done)
6212   {
6213     ProcessExternalEvent ();
6214     Update ();
6215   }
6216   ProcessAnEvent ();
6217   no_aln_choice = GetValue (nacd.action_choice);
6218   Remove (w);
6219   if (nacd.cancelled)
6220   {
6221     return UPDATE_CANCEL;
6222   }
6223   else
6224   {
6225     return no_aln_choice;
6226   }
6227 }
6228 
PrepareUpdatePtr(UpsDataPtr udp)6229 static Boolean PrepareUpdatePtr (UpsDataPtr    udp)
6230 {
6231   Uint2        entityID;
6232   SeqEntryPtr  oldsep, newsep;
6233   SeqIdPtr     sip;
6234   Boolean      islocal = FALSE;
6235   Char         buf [64];
6236   SeqAlignPtr  salp = NULL;
6237   Boolean      revcomp = FALSE;
6238   Boolean      asked_about_desc_prop = FALSE;
6239   Boolean      propagate_descriptors = FALSE;
6240   SeqIdPtr     id, id_next;
6241   MsgAnswer    ans;
6242   Char         collision_id [100];
6243 
6244   if (udp->oldbsp == NULL || udp->newbsp == NULL) return FALSE;
6245   if (ISA_na (udp->oldbsp->mol) != ISA_na (udp->newbsp->mol)) {
6246     Message (MSG_OK, "Both sequences must be either nucleotides or proteins");
6247     return FALSE;
6248   }
6249 
6250   entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
6251   oldsep = GetBestTopParentForData (entityID, udp->oldbsp);
6252   entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
6253   newsep = GetBestTopParentForData (entityID, udp->newbsp);
6254   if (oldsep == NULL || newsep == NULL)
6255     return FALSE;
6256 
6257   if (CONVERTPUBS_NOT_SET == udp->convertPubs)
6258   {
6259     if (Message (MSG_YN, convPubDescMssg) == ANS_YES) {
6260       ConvertPubSrcComDescsToFeats (oldsep, TRUE, FALSE, FALSE, FALSE, &asked_about_desc_prop, &propagate_descriptors, NULL);
6261       ConvertPubSrcComDescsToFeats (newsep, TRUE, FALSE, FALSE, FALSE, &asked_about_desc_prop, &propagate_descriptors, NULL);
6262       udp->convertPubs = CONVERTPUBS_YES;
6263     }
6264     else
6265       udp->convertPubs = CONVERTPUBS_NO;
6266   }
6267 
6268   if (CheckForIDCollision (udp->oldbsp, udp->newbsp, &islocal)) {
6269     sprintf (collision_id, "lcl|SequinUpdateSequence%d", udp->seqsubpos);
6270     sip = SeqIdParse (collision_id);
6271     if (sip != NULL) {
6272       BioseqReplaceID (udp->newbsp, sip);
6273       sip = SeqIdFree (sip);
6274     }
6275   }
6276 
6277   salp = Sqn_AlignForSequenceUpdate (udp->oldbsp, udp->newbsp, &revcomp);
6278 
6279   if (salp == NULL) {
6280     if (udp->log_fp != NULL) {
6281       id = SeqIdFindBest (udp->oldbsp->id, 0);
6282       if (id != NULL)
6283       {
6284         id_next = id->next;
6285         id->next = NULL;
6286         SeqIdWrite (id, buf, PRINTID_REPORT, sizeof (buf) - 1);
6287         id->next = id_next;
6288         fprintf (udp->log_fp, "No sequence similarity for %s\n", buf);
6289         udp->data_in_log = TRUE;
6290       }
6291     }
6292     if (udp->suppress_continue_msg) {
6293       return FALSE;
6294     } else {
6295       if (udp->isSet && udp->do_update)
6296       {
6297         if (udp->no_aln_choice != UPDATE_SKIP_ALL && udp->no_aln_choice != UPDATE_REPLACE_ALL)
6298         {
6299           udp->no_aln_choice = GetNoAlignmentChoice (udp->oldbsp->id, udp->no_aln_choice);
6300         }
6301         if (udp->no_aln_choice == UPDATE_CANCEL)
6302         {
6303           return FALSE;
6304         }
6305       }
6306       else if (udp->do_update)
6307       {
6308         ans = Message (MSG_YN, "There is no alignment between the sequences.  Do you wish to continue?");
6309         if (ans == ANS_YES)
6310         {
6311           udp->useGUI = TRUE;
6312         }
6313         else
6314         {
6315           return FALSE;
6316         }
6317       }
6318     }
6319   }
6320   udp->salp     = salp;
6321   udp->revcomp  = revcomp;
6322   udp->diffOrgs = FALSE;
6323   udp->recomb1  = -1;
6324   udp->recomb2  = -1;
6325 
6326   return TRUE;
6327 }
6328 
6329 static void UpdateProteinsOnNewBsp (SeqFeatPtr sfp, Pointer userdata);
6330 
6331 static void
FindProtRefPtrsOnBsp(BioseqPtr bsp,ValNodePtr PNTR feat_list)6332 FindProtRefPtrsOnBsp
6333 (BioseqPtr bsp,
6334  ValNodePtr PNTR feat_list)
6335 {
6336   SeqMgrFeatContext context;
6337   SeqFeatPtr        sfp;
6338   ValNodePtr        vnp;
6339 
6340   if (bsp == NULL || feat_list == NULL) return;
6341   sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_PROT, 0, &context);
6342   while (sfp != NULL) {
6343     if (context.left == 0 && context.right == bsp->length - 1) {
6344       vnp = ValNodeNew (*feat_list);
6345       if (vnp != NULL) {
6346         vnp->data.ptrvalue = sfp;
6347       }
6348       if (*feat_list == NULL) {
6349         *feat_list = vnp;
6350       }
6351     }
6352     sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_PROT, 0, &context);
6353   }
6354 }
6355 
FindProductProtRefs(BioseqPtr bsp)6356 static ValNodePtr FindProductProtRefs (BioseqPtr bsp)
6357 {
6358   SeqFeatPtr        sfp;
6359   SeqMgrFeatContext context;
6360   ValNodePtr        feat_list = NULL;
6361 
6362   if (bsp == NULL) return NULL;
6363   sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &context);
6364   while (sfp != NULL) {
6365     FindProtRefPtrsOnBsp (BioseqFindFromSeqLoc (sfp->product), &feat_list);
6366     sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &context);
6367   }
6368   return feat_list;
6369 }
6370 
FindTranslExceptCDSs(BioseqPtr bsp)6371 static ValNodePtr FindTranslExceptCDSs (BioseqPtr bsp)
6372 {
6373   SeqFeatPtr        sfp;
6374   SeqMgrFeatContext context;
6375   ValNodePtr        feat_list = NULL;
6376   ValNodePtr        vnp;
6377   Int4              cd_len;
6378 
6379   if (bsp == NULL) return NULL;
6380   sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &context);
6381   while (sfp != NULL) {
6382     if (CodingRegionHasTranslExcept (sfp))
6383     {
6384       vnp = ValNodeNew(feat_list);
6385       if (feat_list == NULL)
6386       {
6387       	feat_list = vnp;
6388       }
6389       if (vnp != NULL)
6390       {
6391       	cd_len = SeqLocLen (sfp->location);
6392       	vnp->choice = cd_len % 3;
6393       	vnp->data.ptrvalue = sfp;
6394       }
6395     }
6396     sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &context);
6397   }
6398   return feat_list;
6399 }
6400 
GetOriginalTranslExceptLen(SeqFeatPtr sfp,ValNodePtr list)6401 static Int4 GetOriginalTranslExceptLen (SeqFeatPtr sfp, ValNodePtr list)
6402 {
6403   ValNodePtr vnp;
6404 
6405   if (sfp == NULL || list == NULL) return 0;
6406   for (vnp = list; vnp != NULL; vnp = vnp->next)
6407   {
6408   	if (vnp->data.ptrvalue == sfp)
6409   	{
6410   		return vnp->choice;
6411   	}
6412   }
6413   if (CodingRegionHasTranslExcept (sfp))
6414   {
6415   	return SeqLocLen (sfp->location) % 3;
6416   }
6417   return 0;
6418 }
6419 
UpdateOneSequence(UpsDataPtr udp,Int2 sfbval,Boolean add_cit_subs,Boolean update_proteins)6420 static void UpdateOneSequence (
6421   UpsDataPtr   udp,
6422   Int2         sfbval,
6423   Boolean      add_cit_subs,
6424   Boolean      update_proteins
6425 )
6426 {
6427   SeqAnnotPtr  sap = NULL;
6428   Uint2        entityID;
6429   SeqEntryPtr  sep;
6430   Boolean      update = FALSE;
6431   Boolean      feature_update = FALSE;
6432   ValNodePtr   prot_feat_list = NULL;
6433 
6434   if (udp != NULL)
6435   {
6436     if (GetStatus (udp->replace_all))
6437     {
6438   	  RemoveOldFeats (udp->oldbsp);
6439     }
6440   }
6441 
6442   if (update_proteins && udp != NULL) {
6443     prot_feat_list = FindProductProtRefs (udp->oldbsp);
6444     if (udp->transl_except_list != NULL)
6445     {
6446       ValNodeFree (udp->transl_except_list);
6447       udp->transl_except_list = NULL;
6448     }
6449     udp->transl_except_list = FindTranslExceptCDSs (udp->oldbsp);
6450   }
6451 
6452   if (udp != NULL && (sfbval == UPDATE_SEQUENCE_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES)) {
6453     switch (udp->rmcval) {
6454       case UPDATE_REPLACE :
6455         if (ReplaceSequence (udp)) {
6456           update = TRUE;
6457         }
6458         break;
6459       case UPDATE_EXTEND5 :
6460 	      if (NULL == udp->salp) {
6461 	        if (Merge5PrimeNoOverlap (udp))
6462 	          update = TRUE;
6463 	      }
6464 	      else
6465 	      {
6466 	        if (Merge5Prime (udp))
6467 	          update = TRUE;
6468         }
6469         break;
6470       case UPDATE_EXTEND3 :
6471 	      if (NULL == udp->salp) {
6472 	        if (Merge3PrimeNoOverlap (udp))
6473 	          update = TRUE;
6474 	      }
6475 	      else
6476 	      {
6477 	        if (Merge3Prime (udp))
6478 	          update = TRUE;
6479         }
6480         break;
6481       case UPDATE_PATCH :
6482         if (PatchSequence (udp)) {
6483           update = TRUE;
6484         }
6485         break;
6486       default :
6487         break;
6488     }
6489     if ( sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
6490       switch (udp->rmcval) {
6491         case UPDATE_REPLACE :
6492           if (DoFeaturePropWithOffset (udp, 0, &sap, FALSE)) {
6493             update = TRUE;
6494             feature_update = TRUE;
6495           }
6496           break;
6497         case UPDATE_EXTEND5 :
6498           if (DoFeaturePropWithOffset (udp, 0, &sap, FALSE)) {
6499             update = TRUE;
6500             feature_update = TRUE;
6501           }
6502           break;
6503         case UPDATE_EXTEND3 :
6504           if (DoFeaturePropWithOffset (udp, udp->old5 - udp->new5, &sap, FALSE)) {
6505             update = TRUE;
6506             feature_update = TRUE;
6507           }
6508           break;
6509         case UPDATE_PATCH :
6510           if (DoFeaturePropWithOffset (udp, udp->old5 - udp->new5, &sap, TRUE)) {
6511             update = TRUE;
6512             feature_update = TRUE;
6513           }
6514           break;
6515         default :
6516           break;
6517       }
6518     }
6519     if (udp->rmcval == UPDATE_REPLACE && udp->revcomp && update)
6520     {
6521       ReverseComplementBioseqAndFeats (udp->oldbsp, udp->input_entityID);
6522     }
6523 
6524   } else if (sfbval == UPDATE_FEATURES_ONLY && udp != NULL) {
6525     switch (udp->rmcval) {
6526       case UPDATE_REPLACE :
6527         if (DoFeaturePropThruAlign (udp, &sap)) {
6528           update = TRUE;
6529           feature_update = TRUE;
6530         }
6531         break;
6532       case UPDATE_EXTEND5 :
6533         if (DoFeaturePropThruAlign (udp, &sap)) {
6534           update = TRUE;
6535           feature_update = TRUE;
6536         }
6537         break;
6538       case UPDATE_EXTEND3 :
6539         if (DoFeaturePropThruAlign (udp, &sap)) {
6540           update = TRUE;
6541           feature_update = TRUE;
6542         }
6543         break;
6544       case UPDATE_PATCH :
6545         if (DoFeaturePropThruAlign (udp, &sap)) {
6546           update = TRUE;
6547           feature_update = TRUE;
6548         }
6549         break;
6550       default :
6551         break;
6552     }
6553   }
6554   if (update) {
6555     entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
6556     if (add_cit_subs
6557       && (feature_update || StringCmp (udp->seq1, udp->seq2) != 0))
6558     {
6559       AddCitSubToUpdatedSequence ( udp->oldbsp, entityID, kSubmitterUpdateText);
6560     }
6561     if (update_proteins)
6562     {
6563       SeqMgrClearFeatureIndexes (entityID, udp->oldbsp);
6564       SeqMgrIndexFeatures (entityID, NULL);
6565       sep = GetBestTopParentForData (entityID, udp->oldbsp);
6566       udp->truncate_proteins = GetStatus (udp->truncate_proteins_btn);
6567       udp->extend_proteins5 = GetStatus (udp->extend_proteins5_btn);
6568       udp->extend_proteins3 = GetStatus (udp->extend_proteins3_btn);
6569       udp->correct_cds_genes = GetStatus (udp->correct_cds_genes_btn);
6570       VisitFeaturesInSep (sep, udp, UpdateProteinsOnNewBsp);
6571       FixProtRefPtrs (prot_feat_list);
6572     }
6573     if (! udp->suppress_instant_refresh) {
6574       ObjMgrSetDirtyFlag (entityID, TRUE);
6575       ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
6576     }
6577   }
6578 
6579   if (udp == NULL) return;
6580   if (GetStatus (udp->update_quality_scores_btn) && udp->rmcval == UPDATE_REPLACE
6581       && (sfbval == UPDATE_SEQUENCE_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES))
6582   {
6583     ReplaceQualityScores (udp->oldbsp, udp->newbsp, udp->log_fp, &(udp->data_in_log));
6584   }
6585   else if (sfbval != UPDATE_FEATURES_ONLY)
6586   {
6587     RemoveQualityScores (udp->oldbsp, udp->log_fp, &(udp->data_in_log));
6588   }
6589 
6590   ValNodeFree (prot_feat_list);
6591   ValNodeFree (udp->transl_except_list);
6592   udp->transl_except_list = NULL;
6593   if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
6594     if (update) {
6595       entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
6596       sep = GetTopSeqEntryForEntityID (entityID);
6597       /* need to set scope to make sure we mark the right bioseq for deletion */
6598       SeqEntrySetScope (sep);
6599       /* resolve features unless the policy was to remove all the old ones */
6600       if (!GetStatus (udp->replace_all))
6601       {
6602         ResolveDuplicateFeats (udp, udp->oldbsp, sap);
6603       }
6604       SeqEntrySetScope (NULL);
6605       DeleteMarkedObjects (entityID, 0, NULL);
6606       SeqMgrClearFeatureIndexes (entityID, NULL);
6607       ObjMgrSetDirtyFlag (entityID, TRUE);
6608       ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
6609     }
6610   }
6611 }
6612 
UpdateProteinsOnNewBsp(SeqFeatPtr sfp,Pointer userdata)6613 static void UpdateProteinsOnNewBsp (SeqFeatPtr sfp, Pointer userdata)
6614 {
6615   UpsDataPtr    udp_orig;
6616   SeqLocPtr     new_product;
6617   Boolean       data_in_log;
6618   Int4          transl_except_len = 0;
6619   Boolean       fix_products = TRUE;
6620   BioseqPtr     protBsp = NULL;
6621   SeqAlignPtr   salp = NULL;
6622   BioseqPtr     newbsp = NULL;
6623   Boolean       rval;
6624 
6625   if (sfp == NULL || sfp->idx.subtype != FEATDEF_CDS || userdata == NULL)
6626   {
6627     return;
6628   }
6629 
6630   if (sfp->idx.deleteme)
6631   {
6632     return;
6633   }
6634 
6635   protBsp = BioseqFindFromSeqLoc (sfp->product);
6636   if (protBsp == NULL)
6637   {
6638     return;
6639   }
6640   udp_orig = (UpsDataPtr) userdata;
6641 
6642   data_in_log = FALSE;
6643   transl_except_len = GetOriginalTranslExceptLen (sfp, udp_orig->transl_except_list);
6644   rval = PrepareUpdateAlignmentForProtein (sfp,
6645                                            protBsp,
6646                                            udp_orig->input_entityID,
6647                                            udp_orig->log_fp,
6648                                            udp_orig->truncate_proteins,
6649                                            udp_orig->extend_proteins5,
6650                                            udp_orig->extend_proteins3,
6651                                            udp_orig->correct_cds_genes,
6652                                            transl_except_len,
6653                                            &data_in_log,
6654                                            &salp,
6655                                            &newbsp);
6656   if (data_in_log) {
6657     udp_orig->data_in_log = TRUE;
6658   }
6659   if (!rval) return;
6660 
6661   if (protBsp->idx.deleteme)
6662   {
6663     fix_products = FALSE;
6664   }
6665 
6666   ReplaceOneSequence (salp, protBsp, newbsp);
6667 
6668   if (fix_products)
6669   {
6670     if (sfp->product->choice != SEQLOC_WHOLE) {
6671       new_product = SeqLocWholeNew (protBsp);
6672       if (new_product == NULL) return;
6673       SeqLocFree (sfp->product);
6674       sfp->product = new_product;
6675     }
6676     newbsp = BioseqFree (newbsp);
6677   }
6678 }
6679 
6680 
6681 /* This section of code is used to warn the user when an alignment update
6682  * will affect the area inside a variation or the area immediately to the
6683  * left or right of a variation.
6684  */
VariationAlignmentCallback(SeqFeatPtr sfp,Pointer userdata)6685 static void VariationAlignmentCallback (SeqFeatPtr sfp, Pointer userdata)
6686 {
6687   CharPtr    buf, cp;
6688   UpsDataPtr udp;
6689   Boolean    change_found = FALSE;
6690 
6691   if (sfp == NULL || userdata == NULL || sfp->idx.subtype != FEATDEF_variation)
6692   {
6693     return;
6694   }
6695   udp = (UpsDataPtr) userdata;
6696   if (udp->salp == NULL)
6697   {
6698     return;
6699   }
6700 
6701   buf = FeatureLocationAlignment (sfp, udp->salp, 1, 2);
6702   if (buf == NULL)
6703   {
6704     return;
6705   }
6706   cp = buf;
6707   /* skip over "Old    :" */
6708   if (StringLen (cp) > 8)
6709   {
6710     cp += 8;
6711   }
6712   while (*cp != 0 && *cp != '\n' && !change_found)
6713   {
6714     if (*cp == '-')
6715     {
6716       change_found = TRUE;
6717     }
6718     cp++;
6719   }
6720   if (*cp == '\n')
6721   {
6722     cp++;
6723   }
6724   /* skip over "New    :" */
6725   if (StringLen (cp) > 8)
6726   {
6727     cp += 8;
6728   }
6729   while (*cp != 0 && *cp != '\n' && !change_found)
6730   {
6731     if (*cp != '.')
6732     {
6733       change_found = TRUE;
6734     }
6735     cp++;
6736   }
6737   if (change_found)
6738   {
6739     ValNodeAddPointer (&udp->affected_variation_features, 0, sfp);
6740   }
6741   buf = MemFree (buf);
6742 }
6743 
PrepareVariationFeatureLogEntry(SeqFeatPtr sfp,SeqAlignPtr salp)6744 static CharPtr PrepareVariationFeatureLogEntry (SeqFeatPtr sfp, SeqAlignPtr salp)
6745 {
6746   CharPtr loc_buf, feat_buf, total_buf;
6747   Int4    buf_len;
6748 
6749   if (sfp == NULL || salp == NULL)
6750   {
6751     return NULL;
6752   }
6753 
6754   loc_buf = SeqLocPrint (sfp->location);
6755   feat_buf = FeatureLocationAlignment (sfp, salp, 1, 2);
6756 
6757   buf_len = StringLen (sfp->comment) + StringLen (loc_buf) + StringLen (feat_buf) + 3;
6758   total_buf = (CharPtr) MemNew (buf_len * sizeof (Char));
6759   if (total_buf != NULL)
6760   {
6761     total_buf [0] = 0;
6762     /* add feature name */
6763     if (!StringHasNoText (sfp->comment))
6764     {
6765       StringCpy (total_buf, sfp->comment);
6766       StringCat (total_buf, "\n");
6767     }
6768     /* add feature location */
6769     if (!StringHasNoText (loc_buf))
6770     {
6771       StringCat (total_buf, loc_buf);
6772       StringCat (total_buf, "\n");
6773     }
6774     /* add alignment picture */
6775     if (!StringHasNoText (feat_buf))
6776     {
6777       StringCat (total_buf, feat_buf);
6778     }
6779     loc_buf = MemFree (loc_buf);
6780     feat_buf = MemFree (feat_buf);
6781   }
6782   return total_buf;
6783 }
6784 
6785 static Int4
VariationFeatureChangesOk(ValNodePtr variation_feature_list,SeqAlignPtr salp,Boolean allow_skip)6786 VariationFeatureChangesOk
6787 (ValNodePtr  variation_feature_list,
6788  SeqAlignPtr salp,
6789  Boolean     allow_skip)
6790 {
6791   WindoW w;
6792   GrouP  h, c;
6793   ButtoN b;
6794   DoC    doc;
6795   ValNodePtr vnp;
6796   SeqFeatPtr sfp;
6797   CharPtr               total_buf;
6798   ModalAcceptCancelData acd;
6799   CharPtr               str_format = "%d variation features are affected by this update.";
6800 
6801   if (variation_feature_list == NULL || salp == NULL)
6802   {
6803     return TRUE;
6804   }
6805 
6806   w = MovableModalWindow (-20, -13, -10, -10, "Affected Variation Sequences", NULL);
6807   h = HiddenGroup(w, -1, 0, NULL);
6808   SetGroupSpacing (h, 10, 10);
6809 
6810   doc = DocumentPanel (h, stdCharWidth * 40, stdLineHeight * 12);
6811   SetDocAutoAdjust (doc, TRUE);
6812 
6813   total_buf = MemNew (StringLen (str_format) + 15);
6814   if (total_buf != NULL)
6815   {
6816     sprintf (total_buf, str_format, ValNodeLen (variation_feature_list));
6817     AppendText (doc, total_buf, NULL, NULL, programFont);
6818     total_buf = MemFree (total_buf);
6819   }
6820 
6821   for (vnp = variation_feature_list; vnp != NULL; vnp = vnp->next)
6822   {
6823     sfp = (SeqFeatPtr) vnp->data.ptrvalue;
6824     total_buf = PrepareVariationFeatureLogEntry (sfp, salp);
6825     if (!StringHasNoText (total_buf))
6826     {
6827       AppendText (doc, total_buf, NULL, NULL, programFont);
6828     }
6829     MemFree (total_buf);
6830   }
6831   UpdateDocument (doc, 0, 0);
6832 
6833   c = HiddenGroup (h, 3, 0, NULL);
6834   b = PushButton (c, "Proceed", ModalAcceptButton);
6835   SetObjectExtra (b, &acd, NULL);
6836   if (allow_skip)
6837   {
6838     b = PushButton (c, "Skip Update", ModalThirdOptionButton);
6839     SetObjectExtra (b, &acd, NULL);
6840   }
6841 
6842   b = PushButton (c, "Cancel Update", ModalCancelButton);
6843   SetObjectExtra (b, &acd, NULL);
6844 
6845 
6846   AlignObjects (ALIGN_CENTER, (HANDLE) doc,
6847                               (HANDLE) c,
6848                               NULL);
6849 
6850   Show (w);
6851   Select (w);
6852 
6853   acd.cancelled = FALSE;
6854   acd.third_option = FALSE;
6855   acd.accepted = FALSE;
6856   while (!acd.accepted && ! acd.cancelled && !acd.third_option)
6857   {
6858     ProcessExternalEvent ();
6859     Update ();
6860   }
6861   ProcessAnEvent ();
6862   Remove (w);
6863 
6864   if (acd.accepted)
6865   {
6866     return 1;
6867   }
6868   else if (acd.cancelled)
6869   {
6870     return 2;
6871   }
6872   else
6873   {
6874     return 3;
6875   }
6876 }
6877 
6878 static void
AddVariationFeaturesToLog(FILE * fp,BoolPtr data_in_log,ValNodePtr variation_feature_list,SeqAlignPtr salp)6879 AddVariationFeaturesToLog
6880 (FILE       *fp,
6881  BoolPtr    data_in_log,
6882  ValNodePtr variation_feature_list,
6883  SeqAlignPtr salp)
6884 {
6885   ValNodePtr vnp;
6886   CharPtr    total_buf;
6887   SeqFeatPtr sfp;
6888 
6889   if (fp == NULL || variation_feature_list == NULL)
6890   {
6891     return;
6892   }
6893 
6894   for (vnp = variation_feature_list; vnp != NULL; vnp = vnp->next)
6895   {
6896     sfp = (SeqFeatPtr) vnp->data.ptrvalue;
6897     total_buf = PrepareVariationFeatureLogEntry (sfp, salp);
6898     if (!StringHasNoText (total_buf))
6899     {
6900       fprintf (fp, "%s", total_buf);
6901       if (data_in_log != NULL)
6902       {
6903         *data_in_log = TRUE;
6904       }
6905     }
6906     MemFree (total_buf);
6907   }
6908 
6909 }
6910 
AcceptRMCOrExtend(ButtoN b)6911 static void AcceptRMCOrExtend (ButtoN b)
6912 {
6913   UpsDataPtr   udp;
6914   Int2         sfbval;
6915   Boolean      log_is_local;
6916   Boolean      update_proteins = FALSE;
6917   Uint2        entityID;
6918 
6919   udp = (UpsDataPtr) GetObjectExtra (b);
6920   if (udp == NULL) return;
6921   SafeHide (udp->form);
6922 
6923   sfbval = GetValue (udp->sfb);
6924   udp->rmcval = GetValue (udp->rmc);
6925 
6926   if (udp->log_fp == NULL) {
6927     OpenSequenceUpdateLog (udp);
6928     if (udp->log_fp == NULL) return;
6929     log_is_local = TRUE;
6930   } else {
6931     log_is_local = FALSE;
6932   }
6933   WatchCursor ();
6934   Update ();
6935 
6936   if (udp->do_update)
6937   {
6938     udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
6939     VisitFeaturesOnBsp (udp->oldbsp, udp, VariationAlignmentCallback);
6940     if (1 == VariationFeatureChangesOk (udp->affected_variation_features, udp->salp, FALSE))
6941     {
6942       if (udp->update_proteins != NULL
6943         && Enabled (udp->update_proteins)
6944         && GetStatus (udp->update_proteins))
6945       {
6946         update_proteins = TRUE;
6947       }
6948       AddVariationFeaturesToLog (udp->log_fp, &(udp->data_in_log),
6949                                  udp->affected_variation_features, udp->salp);
6950       UpdateOneSequence (udp, sfbval,
6951                          GetStatus (udp->add_cit_subs),
6952                          update_proteins);
6953     }
6954     udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
6955   }
6956   else
6957   {
6958     if (ExtendOneSequence (udp))
6959     {
6960       entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
6961       ObjMgrSetDirtyFlag (entityID, TRUE);
6962       ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
6963     }
6964   }
6965 
6966   Remove (udp->form);
6967   if (log_is_local) {
6968     CloseOutSequenceUpdateLog (udp);
6969   }
6970   ArrowCursor ();
6971   Update();
6972 }
6973 
DoAcceptRMCOrExtendSet(UpsDataPtr udp)6974 static void DoAcceptRMCOrExtendSet (UpsDataPtr udp)
6975 {
6976   Int2         sfbval = 0;
6977   Boolean      log_is_local = FALSE;
6978   Boolean      update_proteins = FALSE;
6979   Boolean      do_update = TRUE;
6980   Boolean      old_useGUI;
6981   Char         acc_str [256];
6982   SeqIdPtr     sip, sip_next;
6983   Int2         prior_rmcval;
6984   Int4         variation_action = 1;
6985 
6986   if (udp == NULL) return;
6987 
6988   SafeHide (udp->form);
6989   old_useGUI = udp->useGUI;
6990 
6991   prior_rmcval = udp->rmcval;
6992   if (udp->do_update)
6993   {
6994     if (udp->salp == NULL
6995         && (udp->no_aln_choice == UPDATE_REPLACE_THIS
6996          || udp->no_aln_choice == UPDATE_REPLACE_ALL))
6997     {
6998       sfbval = UPDATE_SEQUENCE_ONLY;
6999       udp->rmcval = UPDATE_REPLACE;
7000       udp->useGUI = FALSE;
7001     }
7002     else if (udp->salp == NULL
7003              && (udp->no_aln_choice == UPDATE_SKIP_THIS
7004               || udp->no_aln_choice == UPDATE_SKIP_ALL))
7005     {
7006       do_update = FALSE;
7007     }
7008     else
7009     {
7010       sfbval = GetValue (udp->sfb);
7011       udp->rmcval = GetValue (udp->rmc);
7012       prior_rmcval = udp->rmcval;
7013     }
7014   }
7015   else
7016   {
7017     udp->rmcval = GetValue (udp->rmc);
7018     prior_rmcval = udp->rmcval;
7019   }
7020 
7021   if (udp->log_fp == NULL)
7022   {
7023     OpenSequenceUpdateLog (udp);
7024     if (udp->log_fp == NULL) return;
7025     log_is_local = TRUE;
7026   }
7027   if (do_update && udp->do_update)
7028   {
7029     udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
7030     VisitFeaturesOnBsp (udp->oldbsp, udp, VariationAlignmentCallback);
7031     variation_action = VariationFeatureChangesOk (udp->affected_variation_features, udp->salp, TRUE);
7032     if (1 != variation_action)
7033     {
7034       do_update = FALSE;
7035     }
7036 
7037 
7038   }
7039 
7040   if (do_update)
7041   {
7042     if (udp->do_update)
7043     {
7044       if (udp->update_proteins != NULL
7045           && Enabled (udp->update_proteins)
7046           && GetStatus (udp->update_proteins))
7047       {
7048         update_proteins = TRUE;
7049       }
7050 
7051       AddVariationFeaturesToLog (udp->log_fp, &(udp->data_in_log),
7052                                  udp->affected_variation_features, udp->salp);
7053       UpdateOneSequence (udp, sfbval, GetStatus (udp->add_cit_subs),
7054                          update_proteins);
7055     }
7056     else
7057     {
7058       ExtendOneSequence (udp);
7059     }
7060 
7061     Remove (udp->form);
7062   }
7063   else
7064   {
7065     sip = SeqIdFindBest (udp->oldbsp->id, 0);
7066     if (sip != NULL)
7067     {
7068       sip_next = sip->next;
7069       SeqIdWrite (sip, acc_str, PRINTID_REPORT, sizeof (acc_str));
7070       fprintf (udp->log_fp, "Skipped update for %s\n", acc_str);
7071 	    udp->data_in_log = TRUE;
7072       sip->next = sip_next;
7073     }
7074   }
7075   udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
7076 
7077   if (log_is_local)
7078   {
7079     CloseOutSequenceUpdateLog (udp);
7080   }
7081 
7082   if (2 == variation_action)
7083   {
7084     FileClose (udp->fp);
7085     CloseOutSequenceUpdateLog (udp);
7086   }
7087 
7088   udp->useGUI = old_useGUI;
7089   udp->rmcval = prior_rmcval;
7090   /* if we are updating a set from a SeqSub, we don't want to free the SeqSub yet */
7091   if (udp->seqsubsep != NULL)
7092   {
7093     udp->newbsp = NULL;
7094   }
7095   FreeUdpFields (udp);
7096 }
7097 
7098 /*------------------------------------------------------------------*/
7099 /*                                                                  */
7100 /* AcceptRMCAll () -- Breaks out of the GUI interface and updates   */
7101 /*                    all remaining sequences in the file without   */
7102 /*                    user intervention.                            */
7103 /*                                                                  */
7104 /*------------------------------------------------------------------*/
7105 
AcceptRMCOrExtendAll(ButtoN b)7106 static void AcceptRMCOrExtendAll (ButtoN b)
7107 
7108 {
7109   UpsDataPtr   udp;
7110   Int2         state;
7111   Int4         count;
7112   Char         msgStr[256];
7113 
7114   /* Get current data */
7115 
7116   udp = (UpsDataPtr) GetObjectExtra (b);
7117   if (udp == NULL)
7118     return;
7119 
7120   /* Process the current sequence */
7121 
7122   WatchCursor ();
7123   udp->useGUI = FALSE;
7124 
7125   if (udp->log_fp == NULL) {
7126     OpenSequenceUpdateLog (udp);
7127     if (udp->log_fp == NULL) return;
7128   }
7129 
7130 
7131   udp->rmcval = GetValue (udp->rmc);
7132 
7133   DoAcceptRMCOrExtendSet (udp);
7134 
7135   /* Loop through the file, processing all others */
7136 
7137   state = FASTA_READ_OK;
7138   count = 0;
7139 
7140   while (FASTA_READ_OK == state) {
7141     count++;
7142     WatchCursor ();
7143     state = UpdateNextBioseqInFastaSet (udp);
7144     if (udp->useGUI)
7145       return;
7146   }
7147 
7148   CloseOutSequenceUpdateLog (udp);
7149   ArrowCursor ();
7150 
7151   /* If there was an error, report it, otherwise */
7152   /* print a status message.                     */
7153 
7154   if (FASTA_READ_ERROR == state) {
7155     sprintf (msgStr, "Encountered error while updating.  Only %d sequences "
7156 	     "were updated.", count);
7157     Message (MSG_OK, msgStr);
7158   }
7159   else {
7160     sprintf (msgStr, "Successfully processed %d sequences from file (not"
7161 	     " counting any updated before hitting 'Accept All').", count);
7162     Message (MSG_OK, msgStr);
7163   }
7164 }
7165 
7166 
AcceptRMCOrExtendSet(ButtoN b)7167 static void AcceptRMCOrExtendSet (ButtoN b)
7168 
7169 {
7170   UpsDataPtr   udp;
7171 
7172   udp = (UpsDataPtr) GetObjectExtra (b);
7173   if (udp == NULL)
7174     return;
7175 
7176   if (udp->log_fp == NULL) {
7177     OpenSequenceUpdateLog (udp);
7178     if (udp->log_fp == NULL) return;
7179   }
7180 
7181   udp->rmcval = GetValue (udp->rmc);
7182 
7183   DoAcceptRMCOrExtendSet (udp);
7184 
7185   UpdateNextBioseqInFastaSet (udp);
7186 }
7187 
SetProteinOptionsEnable(UpsDataPtr udp)7188 static void SetProteinOptionsEnable (UpsDataPtr udp)
7189 {
7190   if (udp == NULL || udp->update_proteins == NULL) return;
7191 
7192   if (Enabled (udp->update_proteins) && GetStatus (udp->update_proteins))
7193   {
7194     Enable (udp->truncate_proteins_btn);
7195     Enable (udp->extend_proteins3_btn);
7196     Enable (udp->extend_proteins5_btn);
7197     Enable (udp->correct_cds_genes_btn);
7198   }
7199   else
7200   {
7201     Disable (udp->truncate_proteins_btn);
7202     Disable (udp->extend_proteins3_btn);
7203     Disable (udp->extend_proteins5_btn);
7204     Disable (udp->correct_cds_genes_btn);
7205   }
7206 }
7207 
SetStatusUpdateAcceptBtns(UpsDataPtr udp,Boolean status)7208 static void SetStatusUpdateAcceptBtns (UpsDataPtr udp, Boolean status)
7209 {
7210   if (udp == NULL) return;
7211 
7212   if (status)
7213   {
7214     SafeEnable (udp->accept);
7215     SafeEnable (udp->acceptAll);
7216   }
7217   else
7218   {
7219     SafeDisable (udp->accept);
7220     SafeDisable (udp->acceptAll);
7221   }
7222 }
7223 
UpdateAccept(GrouP g)7224 static void UpdateAccept (GrouP g)
7225 
7226 {
7227   Int2        rmcval, sfbval;
7228   UpsDataPtr  udp;
7229   Int2        nobmval = UPDATE_FEAT_DUP_NOT_SET;
7230 
7231   udp = (UpsDataPtr) GetObjectExtra (g);
7232   if (udp == NULL) return;
7233 
7234   rmcval = GetValue (udp->rmc);
7235   sfbval = GetValue (udp->sfb);
7236 
7237   if (rmcval == UPDATE_REPLACE)
7238   {
7239     sfbval = GetValue (udp->sfb);
7240     if (sfbval == UPDATE_SEQUENCE_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES)
7241     {
7242       Enable (udp->update_quality_scores_btn);
7243     }
7244     else
7245     {
7246       Disable (udp->update_quality_scores_btn);
7247     }
7248   }
7249   else
7250   {
7251     Disable (udp->update_quality_scores_btn);
7252   }
7253 
7254   if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES)
7255   {
7256     if (!GetStatus (udp->replace_all))
7257     {
7258       nobmval = GetValue (udp->nobm);
7259     }
7260   }
7261 
7262   /* set enables for protein updates */
7263   if (sfbval == UPDATE_SEQUENCE_ONLY
7264      || (sfbval == UPDATE_SEQUENCE_AND_FEATURES
7265         && (nobmval == UPDATE_FEAT_DUP_USE_OLD || nobmval == UPDATE_FEAT_DUP_USE_BOTH)))
7266   {
7267     SafeEnable (udp->update_proteins);
7268   }
7269   else
7270   {
7271     SafeDisable (udp->update_proteins);
7272   }
7273   SetProteinOptionsEnable (udp);
7274 
7275   if (rmcval == UPDATE_CHOICE_NOT_SET) {
7276     SetStatusUpdateAcceptBtns (udp, FALSE);
7277     return;
7278   }
7279   if (! udp->do_update) {
7280     SetStatusUpdateAcceptBtns (udp, TRUE);
7281     return;
7282   }
7283 
7284   if (sfbval == UPDATE_CHOICE_NOT_SET || sfbval == UPDATE_SEQUENCE_ONLY || udp->diffOrgs) {
7285     SafeDisable (udp->keepProteinIDs);
7286     if (sfbval == UPDATE_CHOICE_NOT_SET || sfbval == UPDATE_SEQUENCE_ONLY) {
7287       SafeDisable (udp->nobm);
7288       SafeDisable (udp->replace_all);
7289     } else {
7290       SafeEnable (udp->replace_all);
7291       if (GetStatus (udp->replace_all))
7292       {
7293         SafeDisable (udp->nobm);
7294       }
7295       else
7296       {
7297       	SafeEnable (udp->nobm);
7298       }
7299     }
7300   } else if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
7301     SafeEnable (udp->keepProteinIDs);
7302     SafeEnable (udp->replace_all);
7303     if (GetStatus (udp->replace_all))
7304     {
7305       SafeDisable (udp->nobm);
7306     }
7307     else
7308     {
7309       SafeEnable (udp->nobm);
7310     }
7311   }
7312   if (sfbval == UPDATE_CHOICE_NOT_SET) {
7313     SetStatusUpdateAcceptBtns (udp, FALSE);
7314     return;
7315   }
7316   if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
7317     if (!GetStatus (udp->replace_all) && nobmval == UPDATE_FEAT_DUP_NOT_SET)
7318     {
7319       SetStatusUpdateAcceptBtns (udp, FALSE);
7320       return;
7321     }
7322   }
7323 
7324   SetStatusUpdateAcceptBtns (udp, TRUE);
7325 }
7326 
UpdateButtons(GrouP g)7327 static void UpdateButtons (GrouP g)
7328 {
7329   UpsDataPtr        udp;
7330   Int2              rmcval;
7331   Uint2             entityID;
7332   SeqFeatPtr        sfp;
7333   SeqMgrFeatContext fcontext;
7334 
7335   udp = (UpsDataPtr) GetObjectExtra (g);
7336   if (udp == NULL) return;
7337 
7338   rmcval = GetValue (udp->rmc);
7339 
7340   if (udp->new5 <= udp->old5 && udp->new3 <= udp->old3)
7341   {
7342     if (rmcval == UPDATE_PATCH)
7343     {
7344       /* If patch sequence matches, must be feature propagation only */
7345 
7346       if (StringNICmp (udp->seq1 + udp->old5 - udp->new5,
7347                        udp->seq2,
7348                        StringLen (udp->seq2)) == 0) {
7349         SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
7350         Disable (udp->sfb);
7351       }
7352     }
7353     else if (rmcval == UPDATE_REPLACE)
7354     {
7355       /* If no features, must be sequence update only */
7356 
7357       entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
7358       if (! SeqMgrFeaturesAreIndexed (entityID))
7359         SeqMgrIndexFeatures (entityID, NULL);
7360 
7361       sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &fcontext);
7362       if (sfp == NULL)
7363       {
7364         SetValue (udp->sfb, UPDATE_SEQUENCE_ONLY);
7365         Disable (udp->sfb);
7366         Disable (udp->replace_all);
7367         Disable (udp->nobm);
7368       }
7369       else if (!indexerVersion &&
7370                (udp->newbsp->repr != Seq_repr_raw || udp->oldbsp->repr != Seq_repr_raw))
7371       {
7372         SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
7373         Disable (udp->sfb);
7374       }
7375       else
7376       {
7377         Enable (udp->sfb);
7378       }
7379     }
7380   }
7381   UpdateAccept (g);
7382 }
7383 
DrawAlignBlock(SegmenT pict,Int4 top,Int4 bottom,Int4 labelpt,Int2 labelaln,Int4 len5,Int4 lena,Int4 len3,Int4 aln_length)7384 static void DrawAlignBlock (
7385   SegmenT pict,
7386   Int4 top,
7387   Int4 bottom,
7388   Int4 labelpt,
7389   Int2 labelaln,
7390   Int4 len5,
7391   Int4 lena,
7392   Int4 len3,
7393   Int4 aln_length
7394 )
7395 
7396 {
7397   Char  str [96];
7398 
7399   if (len5 > 0) {
7400     AddRectangle (pict, -len5, top, 0, bottom, NO_ARROW, FALSE, 0);
7401   }
7402   sprintf (str, "%ld", (long) len5);
7403   AddLabel (pict, -len5, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
7404 
7405   if (len3 > 0) {
7406     AddRectangle (pict, aln_length, top, aln_length + len3, bottom, NO_ARROW, FALSE, 0);
7407   }
7408   sprintf (str, "%ld", (long) len3);
7409   AddLabel (pict, aln_length + len3, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
7410 
7411   AddRectangle (pict, 0, top, aln_length, bottom, NO_ARROW, TRUE, 0);
7412   sprintf (str, "%ld", (long) lena);
7413   AddLabel (pict, aln_length / 2, labelpt, str, SMALL_TEXT, 5, labelaln, 0);
7414 }
7415 
MakeAlignPicture(UpsDataPtr udp,CharPtr strid1,CharPtr strid2,SeqAlignPtr sap)7416 static SegmenT MakeAlignPicture (
7417   UpsDataPtr udp,
7418   CharPtr strid1,
7419   CharPtr strid2,
7420   SeqAlignPtr sap
7421 )
7422 
7423 {
7424   SegmenT  pict;
7425   Char     str [96];
7426   Int4     top, bottom;
7427 
7428   pict = CreatePicture ();
7429   if (sap == NULL) return pict;
7430 
7431   top = 0;
7432   bottom = top - 10;
7433 
7434   DrawAlignBlock (pict, top, bottom, bottom, LOWER_CENTER, udp->old5, udp->olda, udp->old3, udp->aln_length);
7435 
7436   /*
7437   AddLabel (pict, (udp->stopmax - udp->startmax) / 2, bottom - 20, strid1, SMALL_TEXT, 5, LOWER_CENTER, 0);
7438   */
7439 
7440 
7441   sprintf (str, "%ld", (long) udp->aln_length);
7442   AddLabel (pict, udp->aln_length / 2, 10, str, SMALL_TEXT, 5, MIDDLE_CENTER, 0);
7443 
7444 
7445   top = 30;
7446   bottom = top - 10;
7447 
7448   DrawAlignBlock (pict, top, bottom, top, UPPER_CENTER, udp->new5, udp->newa, udp->new3, udp->aln_length);
7449 
7450   /*
7451   AddLabel (pict, (udp->stopmax - udp->startmax) / 2, top + 20, strid2, SMALL_TEXT, 5, UPPER_CENTER, 0);
7452   */
7453 
7454   return pict;
7455 }
7456 
DrawAlignDiffs(UpsDataPtr udp,SegmenT pict,Int4 top,Int4 bottom,SeqAlignPtr sap)7457 static void DrawAlignDiffs (
7458   UpsDataPtr udp,
7459   SegmenT pict,
7460   Int4 top,
7461   Int4 bottom,
7462   SeqAlignPtr sap
7463 )
7464 
7465 {
7466   AlnMsg2Ptr  amp1, amp2;
7467   SegmenT    seg;
7468   Int4       len1, len2, i;
7469   Int4       seg_i, seg_n, seg_start, seg_stop;
7470 
7471   if (udp->seq1 == NULL || udp->seq2 == NULL) return;
7472   len1 = StringLen (udp->seq1);
7473   len2 = StringLen (udp->seq2);
7474 
7475   seg = CreateSegment (pict, 0, 0);
7476   AddAttribute (seg, COLOR_ATT, RED_COLOR, 0, 0, 0, 0);
7477 
7478   seg_n = AlnMgr2GetNumSegs(sap);
7479   for (seg_i = 1; seg_i<=seg_n; seg_i++) {
7480     AlnMgr2GetNthSegmentRange(sap, seg_i, &seg_start, &seg_stop);
7481 
7482     amp1 = AlnMsgNew2 ();
7483     amp2 = AlnMsgNew2 ();
7484     if (amp1 == NULL || amp2 == NULL) return;
7485 
7486     amp1->from_aln = seg_start;
7487     amp1->to_aln = seg_stop;
7488     amp1->row_num = 1;
7489 
7490     amp2->from_aln = seg_start;
7491     amp2->to_aln = seg_stop;
7492     amp2->row_num = 2;
7493 
7494     AlnMgr2GetNextAlnBit (sap, amp1);
7495     AlnMgr2GetNextAlnBit (sap, amp2);
7496 
7497     if (amp1->to_row - amp1->from_row == amp2->to_row - amp2->from_row &&
7498         amp1->type == AM_SEQ && amp2->type == AM_SEQ) {
7499       for (i=0; i<seg_stop-seg_start+1; i++) {
7500         if (udp->seq1[amp1->from_row+i] != udp->seq2[amp2->from_row+i]) {
7501 
7502           /* record for accurate scrolling to text view */
7503           ValNodeAddInt (&(udp->mismatches), 0, i);
7504 
7505           AddLine (seg, seg_start+i, top, seg_start+i, bottom, FALSE, 0);
7506         }
7507       }
7508     }
7509 
7510     AlnMsgFree2 (amp1);
7511     AlnMsgFree2 (amp2);
7512   }
7513 }
7514 
DrawAlignBits(UpsDataPtr udp,SegmenT pict,Int4 top,Int4 bottom,Int4 row,Int4 pos1,Int4 pos2,SeqAlignPtr sap)7515 static void DrawAlignBits (
7516   UpsDataPtr udp,
7517   SegmenT pict,
7518   Int4 top,
7519   Int4 bottom,
7520   Int4 row,
7521   Int4 pos1,
7522   Int4 pos2,
7523   SeqAlignPtr sap
7524 )
7525 
7526 {
7527   AlnMsg2Ptr  amp;
7528   Int4       len, start, stop, from, to;
7529   Char       str [96];
7530   Boolean    wasgap;
7531 
7532   amp = AlnMsgNew2 ();
7533   if (amp == NULL) return;
7534 
7535   amp->from_aln = 0;
7536   amp->to_aln = -1;
7537   amp->row_num = row;
7538 
7539   start = 0;
7540   stop = 0;
7541   from = 0;
7542   to = 0;
7543   wasgap = FALSE;
7544 
7545   while (AlnMgr2GetNextAlnBit (sap, amp)) {
7546     len = amp->to_row - amp->from_row + 1;
7547     stop = start + len;
7548     if (amp->type == AM_GAP) {
7549       if (wasgap) {
7550         to = stop;
7551       } else {
7552         AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
7553         wasgap = TRUE;
7554         from = start;
7555         to = stop;
7556       }
7557     } else {
7558       if (wasgap) {
7559 
7560         /* record for accurate scrolling to text view */
7561         ValNodeAddInt (&(udp->indels), 0, from);
7562 
7563         AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
7564         wasgap = FALSE;
7565         from = start;
7566         to = stop;
7567       } else {
7568         to = stop;
7569       }
7570     }
7571     start += len;
7572   }
7573 
7574   if (to > from) {
7575     if (wasgap) {
7576 
7577       /* record for accurate scrolling to text view */
7578       ValNodeAddInt (&(udp->indels), 0, from);
7579 
7580       AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
7581     } else {
7582       AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
7583     }
7584   }
7585 
7586   AlnMsgFree2 (amp);
7587 
7588   sprintf (str, "%ld", (long) pos1);
7589   AddLabel (pict, 0, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
7590 
7591   sprintf (str, "%ld", (long) pos2);
7592   AddLabel (pict, to, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
7593 }
7594 
MakeAlignDetails(UpsDataPtr udp,CharPtr strid1,CharPtr strid2,SeqAlignPtr sap)7595 static SegmenT MakeAlignDetails (
7596   UpsDataPtr udp,
7597   CharPtr strid1,
7598   CharPtr strid2,
7599   SeqAlignPtr sap
7600 )
7601 
7602 {
7603   Int4     aln_length;
7604   SegmenT  pict;
7605   Int4     top, bottom;
7606 
7607   pict = CreatePicture ();
7608   if (sap == NULL) return pict;
7609 
7610   aln_length = udp->aln_length;
7611 
7612   top = 0;
7613   bottom = top - 10;
7614 
7615   DrawAlignBits (udp, pict, top, bottom, 1, udp->old5 + 1, udp->old5 + udp->olda, sap);
7616 
7617   /*
7618   AddLabel (pict, aln_length / 2, bottom, strid1, SMALL_TEXT, 5, LOWER_CENTER, 0);
7619   */
7620 
7621   top = 30;
7622   bottom = top - 10;
7623 
7624   if (udp->revcomp) {
7625     DrawAlignBits (udp, pict, top, bottom, 2, udp->new3 + udp->newa, udp->new3 + 1, sap);
7626   } else {
7627     DrawAlignBits (udp, pict, top, bottom, 2, udp->new5 + 1, udp->new5 + udp->newa, sap);
7628   }
7629 
7630   /*
7631   AddLabel (pict, aln_length / 2, top, strid2, SMALL_TEXT, 5, UPPER_CENTER, 0);
7632   */
7633 
7634   top = 15;
7635   bottom = top - 10;
7636 
7637   DrawAlignDiffs (udp, pict, top, bottom, sap);
7638 
7639   return pict;
7640 }
7641 
MakeAlignSequence(UpsDataPtr udp,SeqAlignPtr sap,Int4 row,CharPtr seq)7642 static CharPtr MakeAlignSequence (
7643   UpsDataPtr udp,
7644   SeqAlignPtr sap,
7645   Int4 row,
7646   CharPtr seq
7647 )
7648 
7649 {
7650   CharPtr    aln;
7651   AlnMsg2Ptr  amp;
7652   Int4       aln_length, len, lens, start, stop, from, to, i, j;
7653 
7654   if (udp == NULL || sap == NULL || seq == NULL || udp->aln_length < 1) return NULL;
7655   lens = StringLen (seq);
7656 
7657   aln = (CharPtr) MemNew (sizeof (Char) * (udp->aln_length + 2));
7658   if (aln == NULL) return NULL;
7659   aln_length = udp->aln_length;
7660   MemSet ((Pointer) aln, '-', aln_length);
7661 
7662   amp = AlnMsgNew2 ();
7663   if (amp == NULL) return aln;
7664 
7665   amp->from_aln = 0;
7666   amp->to_aln = -1;
7667   amp->row_num = row;
7668 
7669   start = 0;
7670   stop = 0;
7671   from = 0;
7672   to = 0;
7673 
7674   while (AlnMgr2GetNextAlnBit (sap, amp)) {
7675     len = amp->to_row - amp->from_row + 1;
7676     stop = start + len;
7677 
7678     if (amp->type == AM_SEQ) {
7679       for (i = start, j = amp->from_row; i < stop && j < lens; i++, j++) {
7680         aln [i] = seq [j];
7681       }
7682     }
7683     start += len;
7684   }
7685 
7686   AlnMsgFree2 (amp);
7687 
7688   return aln;
7689 }
7690 
PrintTAln(ButtoN b)7691 static void PrintTAln (ButtoN b)
7692 
7693 {
7694   AsnIoPtr    aip;
7695   Char        path [PATH_MAX];
7696   UpsDataPtr  udp;
7697 
7698   udp = (UpsDataPtr) GetObjectExtra (b);
7699   if (udp == NULL) return;
7700   TmpNam (path);
7701   aip = AsnIoOpen (path, "w");
7702   if (aip != NULL) {
7703     SeqAlignAsnWrite (udp->salp, aip, NULL);
7704     AsnIoClose (aip);
7705     LaunchGeneralTextViewer (path, "Update Sequence Alignment");
7706   }
7707   FileRemove (path);
7708 }
7709 
PrintGAln(ButtoN b)7710 static void PrintGAln (ButtoN b)
7711 
7712 {
7713   UpsDataPtr  udp;
7714 
7715   udp = (UpsDataPtr) GetObjectExtra (b);
7716   if (udp == NULL) return;
7717   PrintViewer (udp->overview);
7718   PrintViewer (udp->details);
7719 }
7720 
CalculateOverhangs(UpsDataPtr udp)7721 static void CalculateOverhangs (
7722   UpsDataPtr udp
7723 )
7724 
7725 {
7726   Int4         aln_length;
7727   Uint2        entityID;
7728   SeqAlignPtr  sap;
7729   SeqEntryPtr  sep;
7730   Int4         stopold, startold, lenold, stopnew, startnew, lennew;
7731 
7732   if (udp == NULL) return;
7733   sap = udp->salp;
7734   if (sap == NULL) return;
7735   aln_length = AlnMgr2GetAlnLength (sap, FALSE);
7736   AlnMgr2GetNthSeqRangeInSA (sap, 1, &startold, &stopold);
7737   AlnMgr2GetNthSeqRangeInSA (sap, 2, &startnew, &stopnew);
7738   lenold = udp->oldbsp->length;
7739   lennew = udp->newbsp->length;
7740 
7741   udp->old5 = startold;
7742   udp->old3 = lenold - stopold - 1;
7743   udp->olda = stopold - startold + 1;
7744 
7745   udp->new5 = startnew;
7746   udp->new3 = lennew - stopnew - 1;
7747   udp->newa = stopnew - startnew + 1;
7748 
7749   udp->aln_length = aln_length;
7750   udp->startmax = MAX (startold, startnew);
7751   udp->stopmax = MAX (aln_length + lenold - stopold, aln_length + lennew - stopnew);
7752 
7753   udp->strandold = AlnMgr2GetNthStrand (sap, 1);
7754   udp->strandnew = AlnMgr2GetNthStrand (sap, 2);
7755 
7756   entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
7757   sep = GetTopSeqEntryForEntityID (entityID);
7758   SeqEntrySetScope (sep);
7759   udp->seq1 = GetSequenceByBsp (udp->oldbsp);
7760   SeqEntrySetScope (NULL);
7761 
7762   entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
7763   sep = GetTopSeqEntryForEntityID (entityID);
7764   SeqEntrySetScope (sep);
7765   udp->seq2 = GetSequenceByBsp (udp->newbsp);
7766   SeqEntrySetScope (NULL);
7767 
7768   udp->aln1 = MakeAlignSequence (udp, sap, 1, udp->seq1);
7769   udp->aln2 = MakeAlignSequence (udp, sap, 2, udp->seq2);
7770 
7771   udp->log10_aln_length = 1;
7772   while (aln_length >= 10) {
7773     aln_length /= 10;
7774     (udp->log10_aln_length)++;
7775   }
7776 }
7777 
CalculateBestScale(UpsDataPtr udp,VieweR vwr,SegmenT pict)7778 static Int4 CalculateBestScale (
7779   UpsDataPtr udp,
7780   VieweR vwr,
7781   SegmenT pict
7782 )
7783 
7784 {
7785   BoxInfo  box;
7786   Int2     i;
7787   Int4     max, worldwid, portwid;
7788   RecT     r;
7789   Int4     scaleX, oldscaleX;
7790   Int4     wid;
7791 
7792   ObjectRect (vwr, &r);
7793   InsetRect (&r, 4, 4);
7794   wid = (Int4) (r.right - r.left + 1);
7795 
7796   SegmentBox (pict, &box);
7797   oldscaleX = (box.right - box.left + wid - 1) / wid;
7798   RecalculateSegment (pict, oldscaleX, 1);
7799   SegmentBox (pict, &box);
7800   portwid = wid * oldscaleX;
7801   worldwid = box.right - box.left + 20 * oldscaleX + 1;
7802   max = MAX (worldwid, portwid);
7803   scaleX = (max + wid - 1) / wid;
7804   i = 0;
7805   while (i < 10 && (scaleX > oldscaleX || portwid < worldwid)) {
7806     oldscaleX = scaleX;
7807     RecalculateSegment (pict, oldscaleX, 1);
7808     SegmentBox (pict, &box);
7809     portwid = wid * oldscaleX;
7810     worldwid = box.right - box.left + 20 * oldscaleX + 1;
7811     max = MAX (worldwid, portwid);
7812     scaleX = (max + wid - 1) / wid;
7813     i++;
7814   }
7815 
7816   return scaleX;
7817 }
7818 
7819 static Uint1 leftTriFillSym [] = {
7820   0x0C, 0x3C, 0xFC, 0x3C, 0x0C, 0x00, 0x00, 0x00
7821 };
7822 static Uint1 rightTriFillSym [] = {
7823   0xC0, 0xF0, 0xFC, 0xF0, 0xC0, 0x00, 0x00, 0x00
7824 };
7825 
LetDraw(PaneL pnl)7826 static void LetDraw (
7827   PaneL pnl
7828 )
7829 
7830 {
7831   Char        ch1, ch2;
7832   Int2        i, k, q, left, top, bottom, arrowwidth;
7833   size_t      len;
7834   Int4        offset, j, pos, realpos;
7835   RecT        r, x;
7836   BaR         sb;
7837   Char        str [32];
7838   UpsDataPtr  udp;
7839 
7840   udp = (UpsDataPtr) GetObjectExtra (pnl);
7841   if (udp == NULL) return;
7842 
7843   ObjectRect (pnl, &r);
7844   InsetRect (&r, 4, 4);
7845 
7846   sb = GetSlateHScrollBar ((SlatE) pnl);
7847   offset = GetBarValue (sb);
7848 
7849   SelectFont (SetSmallFont ());
7850 
7851   /* draw top (new) letters */
7852 
7853   if (udp->aln2 != NULL)
7854   {
7855     MoveTo (r.left, r.top + 8 + 3 * udp->lineheight);
7856     for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
7857       PaintChar (udp->aln2 [j]);
7858     }
7859   }
7860 
7861   /* draw bottom (old) letters */
7862 
7863   if (udp->aln1 != NULL)
7864   {
7865     MoveTo (r.left, r.top + 8 + 5 * udp->lineheight);
7866     for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
7867       PaintChar (udp->aln1 [j]);
7868     }
7869   }
7870 
7871   /* draw recombination arrows */
7872 
7873   arrowwidth = MIN (6, udp->charwidth);
7874   if (udp->recomb1 >= offset && udp->recomb1 <= offset + udp->maxchars) {
7875     left = r.left + udp->charwidth * (udp->recomb1 - offset);
7876     LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
7877     CopyBits (&x, leftTriFillSym);
7878   }
7879 
7880   if (udp->recomb2 >= offset && udp->recomb2 <= offset + udp->maxchars) {
7881     left = r.left + udp->charwidth * (udp->recomb2 - offset - 1);
7882     LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
7883     CopyBits (&x, rightTriFillSym);
7884   }
7885 
7886   if (udp->aln1 == NULL || udp->aln2 == NULL)
7887   {
7888   	return;
7889   }
7890   /* draw red mismatch lines */
7891 
7892   Red ();
7893   top = r.top + 8 + 4 * udp->lineheight - Ascent ();
7894   bottom = top + udp->lineheight - 2;
7895 
7896   for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
7897     ch1 = udp->aln1 [j];
7898     ch2 = udp->aln2 [j];
7899     if (ch1 == ch2) {
7900     } else if (ch1 == '-' || ch2 == '-') {
7901     } else {
7902       left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
7903       MoveTo (left, top);
7904       LineTo (left, bottom);
7905     }
7906   }
7907   Black ();
7908 
7909   /* draw top (new) tick marks and coordinates */
7910 
7911   bottom = r.top + 8 + 3 * udp->lineheight - Ascent () - 2;
7912   top = bottom - 5;
7913   i = 0;
7914   j = offset;
7915   pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 2);
7916   while (pos < 1 && i < udp->maxchars && j < udp->aln_length) {
7917     i++;
7918     j++;
7919     pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 2);
7920   }
7921   for (; i < udp->maxchars + udp->log10_aln_length && j < udp->aln_length; i++, j++) {
7922     ch1 = udp->aln2 [j];
7923     if (ch1 != '-') {
7924       if (udp->revcomp) {
7925         realpos = (udp->newbsp->length - pos - 1);
7926       } else {
7927         realpos = pos;
7928       }
7929       if (((realpos + 1) % 10) == 0) {
7930         left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
7931         if (i < udp->maxchars) {
7932           MoveTo (left, top);
7933           LineTo (left, bottom);
7934         }
7935         sprintf (str, "%ld", (long) (realpos + 1));
7936         len = StringLen (str);
7937         if (len <= j + 1) {
7938           k = i - len + 1;
7939           q = 0;
7940           if (k < 0) {
7941             q -= k;
7942             k = 0;
7943           }
7944           if (q < len) {
7945             left = r.left + k * udp->charwidth;
7946             MoveTo (left, r.top + 8 + udp->lineheight);
7947             while (k < udp->maxchars && q < len) {
7948               PaintChar (str [q]);
7949               k++;
7950               q++;
7951             }
7952           }
7953         }
7954       } else if (((realpos + 1) % 5) == 0) {
7955         left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
7956         if (i < udp->maxchars) {
7957           MoveTo (left, top + 3);
7958           LineTo (left, bottom);
7959         }
7960       }
7961       pos++;
7962     }
7963   }
7964 
7965   /* draw bottom (old) tick marks and coordinates */
7966 
7967   top = r.top + 8 + 6 * udp->lineheight - Ascent () + 2;
7968   bottom = top + 5;
7969   i = 0;
7970   j = offset;
7971   pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 1);
7972   while (pos < 1 && i < udp->maxchars && j < udp->aln_length) {
7973     i++;
7974     j++;
7975     pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 1);
7976   }
7977   for (; i < udp->maxchars + udp->log10_aln_length && j < udp->aln_length; i++, j++) {
7978     ch1 = udp->aln1 [j];
7979     if (ch1 != '-') {
7980       if (((pos + 1) % 10) == 0) {
7981         left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
7982         if (i < udp->maxchars) {
7983           MoveTo (left, top);
7984           LineTo (left, bottom);
7985         }
7986         sprintf (str, "%ld", (long) (pos + 1));
7987         len = StringLen (str);
7988         if (len <= j + 1) {
7989           k = i - len + 1;
7990           q = 0;
7991           if (k < 0) {
7992             q -= k;
7993             k = 0;
7994           }
7995           if (q < len) {
7996             left = r.left + k * udp->charwidth;
7997             MoveTo (left, r.top + 8 + 7 * udp->lineheight);
7998             while (k < udp->maxchars && q < len) {
7999               PaintChar (str [q]);
8000               k++;
8001               q++;
8002             }
8003           }
8004         }
8005       } else if (((pos + 1) % 5) == 0) {
8006         left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
8007         if (i < udp->maxchars) {
8008           MoveTo (left, top);
8009           LineTo (left, bottom - 3);
8010         }
8011       }
8012       pos++;
8013     }
8014   }
8015   SelectFont (systemFont);
8016 }
8017 
LetScrl(BaR sb,SlatE slt,Int4 newval,Int4 oldval)8018 static void LetScrl (
8019   BaR sb,
8020   SlatE slt,
8021   Int4 newval,
8022   Int4 oldval
8023 )
8024 
8025 {
8026   RecT        r;
8027   UpsDataPtr  udp;
8028 
8029   udp = (UpsDataPtr) GetObjectExtra (slt);
8030   if (udp == NULL) return;
8031 
8032   ObjectRect (udp->letters, &r);
8033   InsetRect (&r, 4, 4);
8034   Select (udp->letters);
8035   if (ABS (oldval - newval) < udp->maxchars) {
8036     ScrollRect (&r, (oldval - newval) * udp->charwidth, 0);
8037   } else {
8038     InsetRect (&r, -2, -2);
8039     InvalRect (&r);
8040   }
8041   Update ();
8042 }
8043 
DtlClck(VieweR vwr,SegmenT pict,PoinT pt)8044 static void DtlClck (
8045   VieweR vwr,
8046   SegmenT pict,
8047   PoinT pt
8048 )
8049 
8050 {
8051   Int4        goHere;
8052   Int4        offset;
8053   Int4        maxover2;
8054   PntInfo     pnt;
8055   BaR         sb;
8056   UpsDataPtr  udp;
8057   ValNodePtr  vnp;
8058 
8059   udp = (UpsDataPtr) GetViewerData (vwr);
8060   if (udp == NULL) return;
8061 
8062   sb = GetSlateHScrollBar ((SlatE) udp->letters);
8063 
8064   MapViewerToWorld (vwr, pt, &pnt);
8065   maxover2 = udp->maxchars / 2;
8066   if (pnt.x <= 0) {
8067     pnt.x = 0;
8068   } else if (pnt.x >= udp->aln_length) {
8069     pnt.x = udp->aln_length  - udp->maxchars;
8070   } else if (pnt.x >= maxover2) {
8071 
8072     offset = GetBarValue (sb);
8073 
8074     /* look for clicks within 5 pixels of an indel start or a mismatch */
8075 
8076     goHere = -1;
8077     for (vnp = udp->indels; vnp != NULL && goHere < 0; vnp = vnp->next) {
8078       if (ABS (pnt.x - vnp->data.intvalue) < udp->scaleX * 5) {
8079         goHere = vnp->data.intvalue;
8080       }
8081     }
8082     for (vnp = udp->mismatches; vnp != NULL && goHere < 0; vnp = vnp->next) {
8083       if (ABS (pnt.x - vnp->data.intvalue) < udp->scaleX * 5) {
8084         goHere = vnp->data.intvalue;
8085       }
8086     }
8087 
8088     if (goHere >= 0) {
8089       pnt.x = goHere;
8090     } else {
8091       /* if already visible, no need to scroll */
8092       if (pnt.x - maxover2 > offset && pnt.x - maxover2 < offset + maxover2 - 5) return;
8093       if (pnt.x - maxover2 < offset && pnt.x - maxover2 > offset - maxover2 + 5) return;
8094     }
8095 
8096     /* go left 1/2 screen so desired point is in the middle */
8097 
8098     pnt.x -= maxover2;
8099   }
8100 
8101   ResetClip ();
8102   SetBarValue (sb, pnt.x);
8103   Update ();
8104 }
8105 
FrameVwr(VieweR vwr,SegmenT pict)8106 static void FrameVwr (
8107   VieweR vwr,
8108   SegmenT pict
8109 )
8110 
8111 {
8112   RecT  r;
8113 
8114   ResetClip ();
8115   ObjectRect (vwr, &r);
8116   FrameRect (&r);
8117 }
8118 
SortVnpByInt(VoidPtr ptr1,VoidPtr ptr2)8119 static int LIBCALLBACK SortVnpByInt (VoidPtr ptr1, VoidPtr ptr2)
8120 
8121 {
8122   ValNodePtr  vnp1;
8123   ValNodePtr  vnp2;
8124 
8125   if (ptr1 == NULL || ptr2 == NULL) return 0;
8126   vnp1 = *((ValNodePtr PNTR) ptr1);
8127   vnp2 = *((ValNodePtr PNTR) ptr2);
8128   if (vnp1 == NULL || vnp2 == NULL) return 0;
8129 
8130   if (vnp1->data.intvalue > vnp2->data.intvalue) {
8131     return 1;
8132   } else if (vnp1->data.intvalue < vnp2->data.intvalue) {
8133     return -1;
8134   }
8135 
8136   return 0;
8137 }
8138 
8139 
UpdateSequenceFormMessage(ForM f,Int2 mssg)8140 static void UpdateSequenceFormMessage (ForM f, Int2 mssg)
8141 
8142 {
8143   BaseFormPtr        bfp;
8144   StdEditorProcsPtr  sepp;
8145 
8146   bfp = (BaseFormPtr) GetObjectExtra (f);
8147   if (bfp == NULL) return;
8148   switch (mssg) {
8149     case VIB_MSG_CLOSE :
8150       Remove (f);
8151       break;
8152     case VIB_MSG_QUIT :
8153       QuitProc ();
8154       break;
8155     default :
8156       sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
8157       if (sepp != NULL && sepp->handleMessages != NULL) {
8158         sepp->handleMessages (f, mssg);
8159       }
8160       break;
8161   }
8162 }
8163 
FreeUdpFields(UpsDataPtr udp)8164 static void FreeUdpFields (UpsDataPtr udp)
8165 {
8166   Uint2       entityID;
8167 
8168   udp->ovpict     = DeletePicture (udp->ovpict);
8169   udp->dtpict     = DeletePicture (udp->dtpict);
8170   udp->salp       = SeqAlignFree (udp->salp);
8171   entityID        = ObjMgrGetEntityIDForPointer (udp->newbsp);
8172   udp->newbsp     = ObjMgrFreeByEntityID (entityID);
8173   udp->seq1       = MemFree (udp->seq1);
8174   udp->seq2       = MemFree (udp->seq2);
8175   udp->aln1       = MemFree (udp->aln1);
8176   udp->aln1       = NULL;
8177   udp->aln2       = MemFree (udp->aln2);
8178   udp->aln2       = NULL;
8179   udp->indels     = ValNodeFree (udp->indels);
8180   udp->mismatches = ValNodeFree (udp->mismatches);
8181   udp->transl_except_list = ValNodeFree (udp->transl_except_list);
8182   udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
8183 }
8184 
CleanupUpdateSequenceForm(GraphiC g,VoidPtr data)8185 static void CleanupUpdateSequenceForm (GraphiC g, VoidPtr data)
8186 
8187 {
8188   UpsDataPtr  udp;
8189 
8190   udp = (UpsDataPtr) data;
8191   if (udp != NULL)
8192     FreeUdpFields (udp);
8193   StdCleanupFormProc (g, data);
8194 }
8195 
8196 static CharPtr txt1 =
8197   "Sequence Relationship displays sequence lengths";
8198 
8199 static CharPtr txt2 =
8200   "Alignment Details displays sequence positions";
8201 
8202 static CharPtr txt3 =
8203   "Click above to scroll Alignment Text position";
8204 
8205 /*------------------------------------------------------------------*/
8206 /*                                                                  */
8207 /* DetermineButtonState () -- Enable/disable buttons based on the   */
8208 /*                            nature of the alignment.              */
8209 /*                                                                  */
8210 /*------------------------------------------------------------------*/
8211 
DetermineButtonState(UpsDataPtr udp,ButtoN PNTR replaceButtonPtr,ButtoN PNTR extend5ButtonPtr,ButtoN PNTR extend3ButtonPtr,ButtoN PNTR patchButtonPtr)8212 static void DetermineButtonState (UpsDataPtr   udp,
8213 				  ButtoN PNTR  replaceButtonPtr,
8214 				  ButtoN PNTR  extend5ButtonPtr,
8215 				  ButtoN PNTR  extend3ButtonPtr,
8216 				  ButtoN PNTR  patchButtonPtr)
8217 {
8218   BioSourcePtr       biop1;
8219   BioSourcePtr       biop2;
8220   SeqMgrDescContext  dcontext;
8221   Uint2              entityID;
8222   SeqMgrFeatContext  fcontext;
8223   OrgRefPtr          orp1;
8224   OrgRefPtr          orp2;
8225   SeqDescrPtr        sdp;
8226   SeqFeatPtr         sfp;
8227 
8228   /* If no alignment then disable the patch button */
8229 
8230   if (udp->salp == NULL) {
8231     if (udp->do_update && patchButtonPtr != NULL && *patchButtonPtr != NULL) {
8232       Disable (*patchButtonPtr);
8233     }
8234     if (!udp->do_update)
8235     {
8236       Disable (*replaceButtonPtr);
8237     }
8238   }
8239 
8240   /* Extend 5' */
8241 
8242   else if (udp->new5 > udp->old5 && udp->new3 < udp->old3) {
8243     SetValue (udp->rmc, UPDATE_EXTEND5);
8244     Disable (*extend3ButtonPtr);
8245     udp->recomb2 = udp->aln_length;
8246     if (! udp->do_update) {
8247       Disable (*replaceButtonPtr);
8248     }
8249   }
8250 
8251   /* Extend 3' */
8252 
8253   else if (udp->new5 < udp->old5 && udp->new3 > udp->old3) {
8254     SetValue (udp->rmc, UPDATE_EXTEND3);
8255     Disable (*extend5ButtonPtr);
8256     udp->recomb1 = 0;
8257     if (! udp->do_update) {
8258       Disable (*replaceButtonPtr);
8259     }
8260   }
8261 
8262   /* Replace */
8263 
8264   else {
8265     SetValue (udp->rmc, UPDATE_REPLACE);
8266     Disable (*extend5ButtonPtr);
8267     Disable (*extend3ButtonPtr);
8268     udp->recomb1 = 0;
8269     udp->recomb2 = udp->aln_length;
8270   }
8271 
8272   switch (udp->rmcval)
8273   {
8274     case UPDATE_REPLACE:
8275       if (Enabled (*replaceButtonPtr))
8276       {
8277         SetValue (udp->rmc, UPDATE_REPLACE);
8278       }
8279       break;
8280     case UPDATE_EXTEND5:
8281       if (Enabled (*extend5ButtonPtr))
8282       {
8283         SetValue (udp->rmc, UPDATE_EXTEND5);
8284       }
8285       break;
8286     case UPDATE_EXTEND3:
8287       if (Enabled (*extend3ButtonPtr))
8288       {
8289         SetValue (udp->rmc, UPDATE_EXTEND3);
8290       }
8291       break;
8292     case UPDATE_PATCH:
8293       if (patchButtonPtr != NULL && Enabled (*patchButtonPtr))
8294       {
8295         SetValue (udp->rmc, UPDATE_PATCH);
8296       }
8297       break;
8298   }
8299 
8300   /* If no features, must be sequence update only */
8301 
8302   entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
8303   if (! SeqMgrFeaturesAreIndexed (entityID))
8304     SeqMgrIndexFeatures (entityID, NULL);
8305 
8306   sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &fcontext);
8307   if (sfp == NULL) {
8308     SetValue (udp->sfb, UPDATE_SEQUENCE_ONLY);
8309     Disable (udp->sfb);
8310     Disable (udp->replace_all);
8311     Disable (udp->nobm);
8312   }
8313 
8314   /* If different organisms, must be feature propagation only */
8315 
8316   orp1 = NULL;
8317   orp2 = NULL;
8318   sdp = SeqMgrGetNextDescriptor (udp->oldbsp, NULL, Seq_descr_source, &dcontext);
8319   if (sdp != NULL) {
8320     biop1 = (BioSourcePtr) sdp->data.ptrvalue;
8321     if (biop1 != NULL) {
8322       orp1 = biop1->org;
8323     }
8324   }
8325   sdp = SeqMgrGetNextDescriptor (udp->newbsp, NULL, Seq_descr_source, &dcontext);
8326   if (sdp != NULL) {
8327     biop2 = (BioSourcePtr) sdp->data.ptrvalue;
8328     if (biop2 != NULL) {
8329       orp2 = biop2->org;
8330     }
8331   }
8332   if (orp1 != NULL && orp2 != NULL) {
8333     if (StringICmp (orp1->taxname, orp2->taxname) != 0) {
8334       if (sfp != NULL) {
8335         SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
8336         Disable (udp->sfb);
8337         udp->diffOrgs = TRUE;
8338 	if (FALSE == udp->isSet)
8339 	  Message (MSG_OK, "Organisms are different, so features will"
8340 		   " be propagated, but sequence will not be changed");
8341       } else {
8342         /* no features, cannot do anything */
8343         SetValue (udp->sfb, UPDATE_CHOICE_NOT_SET);
8344         Disable (udp->sfb);
8345         Disable (udp->replace_all);
8346         Disable (udp->nobm);
8347 	if (FALSE == udp->isSet)
8348 	  Message (MSG_OK, "Organisms are different, no features"
8349 		   " to propagate, so nothing to do");
8350       }
8351       Disable (udp->rmc);
8352     }
8353   }
8354 
8355   /* If either sequence is not raw and not indexer version, only allow feature propagation */
8356   if (!indexerVersion &&
8357       (udp->oldbsp->repr != Seq_repr_raw || udp->newbsp->repr != Seq_repr_raw)) {
8358     SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
8359     Disable (udp->sfb);
8360   }
8361 
8362   /* Disable accept button unless rmc and sfb are both preset */
8363 
8364   UpdateAccept (udp->rmc);
8365 
8366 }
8367 
ChangeUpdateReplaceAll(ButtoN b)8368 static void ChangeUpdateReplaceAll (ButtoN b)
8369 {
8370   UpsDataPtr udp;
8371 
8372   if (b == NULL) return;
8373   udp = (UpsDataPtr) GetObjectExtra (b);
8374   if (udp == NULL) return;
8375 
8376   if (GetStatus (b))
8377   {
8378   	Disable (udp->nobm);
8379   }
8380   else
8381   {
8382   	Enable (udp->nobm);
8383   }
8384   /* update accept button */
8385   UpdateAccept (udp->rmc);
8386 }
8387 
CancelUpdate(ButtoN b)8388 static void CancelUpdate (ButtoN b)
8389 {
8390   UpsDataPtr udp;
8391 
8392   if (b == NULL) return;
8393   udp = (UpsDataPtr) GetObjectExtra (b);
8394   if (udp == NULL) return;
8395   CloseOutSequenceUpdateLog (udp);
8396   StdCancelButtonProc (b);
8397 }
8398 
CreateUpdateOperationsGroup(GrouP parent,UpsDataPtr udp)8399 static GrouP CreateUpdateOperationsGroup (GrouP parent, UpsDataPtr udp)
8400 {
8401   GrouP  g;
8402   GrouP  gp1, gp2, gp3;
8403   ButtoN b1 = NULL, b2 = NULL, b3 = NULL, b4 = NULL;
8404 
8405   if (udp == NULL) return NULL;
8406 
8407   g = HiddenGroup (parent, -1, 0, NULL);
8408   SetGroupSpacing (g, 5, 5);
8409 
8410   gp1 = NormalGroup (g, 4, 0, "Alignment Relationship", programFont, NULL);
8411   udp->rmc = HiddenGroup (gp1, 4, 0, UpdateButtons);
8412   SetObjectExtra (udp->rmc, (Pointer) udp, NULL);
8413   SetGroupSpacing (udp->rmc, 10, 5);
8414   if (udp->do_update) {
8415     b1 = RadioButton (udp->rmc, "Replace");
8416   } else {
8417     b1= RadioButton (udp->rmc, "Extend Both Ends");
8418   }
8419   b2 = RadioButton (udp->rmc, "Extend 5'");
8420   b3 = RadioButton (udp->rmc, "Extend 3'");
8421   if (udp->do_update) {
8422     b4 = RadioButton (udp->rmc, "Patch");
8423   } else {
8424     b4 = NULL;
8425   }
8426 
8427   if (udp->do_update) {
8428     gp2 = NormalGroup (g, 4, 0, "Update Operation", programFont, NULL);
8429     udp->sfb = HiddenGroup (gp2, 3, 0, UpdateAccept);
8430     SetObjectExtra (udp->sfb, (Pointer) udp, NULL);
8431     SetGroupSpacing (udp->sfb, 10, 5);
8432     RadioButton (udp->sfb, "Sequence");
8433     RadioButton (udp->sfb, "Features");
8434     RadioButton (udp->sfb, "Sequence + Features");
8435 
8436     udp->keepProteinIDs = CheckBox (g, "Keep Protein IDs", NULL);
8437 
8438     gp3 = NormalGroup (g, 1, 0, "Feature Policy", programFont, NULL);
8439     udp->replace_all = CheckBox (gp3, "Replace All Features", ChangeUpdateReplaceAll);
8440     SetObjectExtra (udp->replace_all, (Pointer) udp, NULL);
8441     SetValue (udp->replace_all, FALSE);
8442 
8443     udp->nobm = NormalGroup (gp3, 5, 0, "Duplicate Features Only", programFont, UpdateAccept);
8444     SetObjectExtra (udp->nobm, (Pointer) udp, NULL);
8445     SetGroupSpacing (udp->nobm, 10, 5);
8446     RadioButton (udp->nobm, "New");
8447     RadioButton (udp->nobm, "Old");
8448     RadioButton (udp->nobm, "Both");
8449     RadioButton (udp->nobm, "Merge");
8450     RadioButton (udp->nobm, "Replace");
8451 
8452     AlignObjects (ALIGN_CENTER, (HANDLE) gp1, (HANDLE) gp2,
8453                   (HANDLE) udp->keepProteinIDs,
8454                   (HANDLE) gp3,  NULL);
8455   }
8456   /* Enable/disable buttons based on the nature of the alignment */
8457 
8458   DetermineButtonState (udp, &b1, &b2, &b3, &b4);
8459   return g;
8460 
8461 }
8462 
8463 
ChangeProteinUpdateStatus(ButtoN b)8464 static void ChangeProteinUpdateStatus (ButtoN b)
8465 {
8466   UpsDataPtr udp;
8467 
8468   udp = (UpsDataPtr) GetObjectExtra (b);
8469   if (udp == NULL) return;
8470   SetProteinOptionsEnable (udp);
8471 }
8472 
SkipUpdate(UpsDataPtr udp)8473 static void SkipUpdate (UpsDataPtr udp)
8474 {
8475   Char     acc_str [256];
8476   SeqIdPtr sip, sip_next;
8477 
8478   if (udp == NULL) return;
8479 
8480   OpenSequenceUpdateLog (udp);
8481   if (udp->log_fp != NULL && udp->oldbsp != NULL && udp->oldbsp->id != NULL)
8482   {
8483     sip = SeqIdFindBest (udp->oldbsp->id, 0);
8484     if (sip != NULL)
8485     {
8486       sip_next = sip->next;
8487       sip->next = NULL;
8488       SeqIdWrite (sip, acc_str, PRINTID_REPORT, sizeof (acc_str));
8489       fprintf (udp->log_fp, "Skipped update for %s\n", acc_str);
8490 	    udp->data_in_log = TRUE;
8491 	    sip->next = sip_next;
8492     }
8493   }
8494 
8495   /* if we are updating a set from a SeqSub, we don't want to free the SeqSub yet */
8496   if (udp->seqsubsep != NULL)
8497   {
8498     udp->newbsp = NULL;
8499   }
8500   FreeUdpFields (udp);
8501   UpdateNextBioseqInFastaSet (udp);
8502 }
8503 
CreateExtraUpdateOptionsGroup(GrouP g,UpsDataPtr udp)8504 static GrouP CreateExtraUpdateOptionsGroup (GrouP g, UpsDataPtr udp)
8505 {
8506   GrouP y, protein_options = NULL;
8507 
8508   if (udp == NULL || g == NULL) return NULL;
8509 
8510   y = HiddenGroup (g, -1, 0, NULL);
8511 
8512   udp->add_cit_subs = CheckBox (y, "Add Cit-subs for Updated Sequences", NULL);
8513   udp->update_quality_scores_btn = NULL;
8514   if (! ISA_aa (udp->oldbsp->mol) && udp->do_update)
8515   {
8516     udp->update_quality_scores_btn = CheckBox (y, "Replace Quality Scores", NULL);
8517     SetStatus (udp->update_quality_scores_btn, TRUE);
8518 
8519     udp->update_proteins = CheckBox (y, "Update Proteins for Updated Sequences", ChangeProteinUpdateStatus);
8520     SetObjectExtra (udp->update_proteins, (Pointer) udp, NULL);
8521     SetStatus (udp->update_proteins, FALSE);
8522     protein_options = HiddenGroup (y, 1, 0, NULL);
8523     udp->truncate_proteins_btn = CheckBox (protein_options,
8524                                      "Truncate retranslated proteins at stops",
8525                                            NULL);
8526     SetStatus (udp->truncate_proteins_btn,
8527                udp->truncate_proteins);
8528     udp->extend_proteins3_btn = CheckBox (protein_options,
8529                                   "Extend retranslated proteins without stops",
8530                                          NULL);
8531     udp->extend_proteins5_btn = CheckBox (protein_options,
8532                                   "Extend retranslated proteins without starts",
8533                                          NULL);
8534     udp->correct_cds_genes_btn = CheckBox (protein_options, "Correct CDS genes", NULL);
8535 
8536     SetStatus (udp->extend_proteins3_btn, udp->extend_proteins3);
8537     SetStatus (udp->extend_proteins5_btn, udp->extend_proteins5);
8538     SetStatus (udp->correct_cds_genes_btn, udp->correct_cds_genes);
8539   }
8540   AlignObjects (ALIGN_CENTER, (HANDLE) udp->add_cit_subs,
8541                 (HANDLE) udp->update_quality_scores_btn,
8542                 (HANDLE) udp->update_proteins,
8543                 (HANDLE) protein_options,
8544                 NULL);
8545   return y;
8546 }
8547 
SkipUpdateBtn(ButtoN b)8548 static void SkipUpdateBtn (ButtoN b)
8549 {
8550   UpsDataPtr udp;
8551 
8552   udp = (UpsDataPtr) GetObjectExtra (b);
8553   if (udp == NULL) return;
8554   SafeHide (udp->form);
8555   Remove (udp->form);
8556 
8557   SkipUpdate (udp);
8558 }
8559 
8560 /*------------------------------------------------------------------*/
8561 /*                                                                  */
8562 /* UpdateSequenceForm () -- Compares two sequences and displays a   */
8563 /*                          window giving the user options on how   */
8564 /*                          to update one from the other.           */
8565 /*                                                                  */
8566 /*------------------------------------------------------------------*/
8567 
UpdateSequenceForm(UpsDataPtr udp)8568 static ForM UpdateSequenceForm (UpsDataPtr udp)
8569 {
8570   ButtoN             b;
8571   GrouP              c, g, y, k, x, z = NULL;
8572   Uint2              hgt;
8573   GrouP              ppt0, ppt1, ppt2, ppt3;
8574   RecT               r;
8575   BaR                sb;
8576   Int4               scaleX;
8577   SeqIdPtr           sip;
8578   Char               strid1 [MAX_ID_LEN], strid2 [MAX_ID_LEN], txt0 [256];
8579   CharPtr            title;
8580   WindoW             w;
8581   GrouP              misc_options;
8582   Int4               prompt_width = 400;
8583   GrouP              left_panel;
8584   GrouP              right_panel;
8585 
8586   /* Check parameters */
8587 
8588   if ((udp->oldbsp == NULL) || (udp->newbsp == NULL))
8589     return NULL;
8590 
8591   /* Create window */
8592 
8593   if (udp->do_update) {
8594     title = "Update Sequence";
8595   } else {
8596     title = "Extend Sequence";
8597   }
8598   w = FixedWindow (-50, -33, -10, -10, title, NULL);
8599 
8600   if (w == NULL)
8601     return NULL;
8602 
8603   if (FALSE == udp->isSet)
8604     SetObjectExtra (w, (Pointer) udp, CleanupUpdateSequenceForm);
8605   udp->form = (ForM) w;
8606 
8607   /* Get string IDs for the Bioseqs */
8608 
8609   sip = SeqIdFindWorst (udp->oldbsp->id);
8610   SeqIdWrite (sip, strid1, PRINTID_REPORT, sizeof (strid1) - 1);
8611   sip = SeqIdFindWorst (udp->newbsp->id);
8612   SeqIdWrite (sip, strid2, PRINTID_REPORT, sizeof (strid2) - 1);
8613   if (StringNICmp (strid2, "SequinUpdateSequence", 20) == 0 &&
8614       udp->newbsp->id->next != NULL) {
8615     sip = SeqIdFindWorst (udp->newbsp->id->next);
8616     SeqIdWrite (sip, strid2, PRINTID_REPORT, sizeof (strid2) - 1);
8617   }
8618 
8619   /* FIll in some of the data structure */
8620   /* for passing to the callbacks.      */
8621 
8622   udp->formmessage = UpdateSequenceFormMessage;
8623 
8624 #ifdef WIN_MAC
8625   udp->activate = UpdateSequenceFormActivated;
8626   SetActivate (w, UpdateSequenceFormActivate);
8627 #endif
8628 
8629   udp->diffOrgs = FALSE;
8630 
8631   CalculateOverhangs (udp);
8632 
8633   /* Display the sequences */
8634 
8635   sprintf (txt0,
8636 	   "New sequence: %s - Length: %ld\nOld Sequence: %s - Length: %ld",
8637 	   strid2, (long) udp->newbsp->length, strid1,
8638 	   (long) udp->oldbsp->length);
8639   ppt0 = MultiLinePrompt (w, txt0, prompt_width, programFont);
8640 
8641   x = HiddenGroup (w, 2, 0, NULL);
8642   left_panel = HiddenGroup (x, -1, 0, NULL);
8643   y = left_panel;
8644 
8645   ppt1 = MultiLinePrompt (y, txt1, prompt_width, programFont);
8646   udp->overview = CreateViewer (y, prompt_width + Nlm_vScrollBarWidth, 100,
8647 				FALSE, FALSE);
8648 
8649   ppt2 = MultiLinePrompt (y, txt2, prompt_width, programFont);
8650   udp->details = CreateViewer (y, prompt_width + Nlm_vScrollBarWidth, 80,
8651 			       FALSE, FALSE);
8652 
8653   ppt3 = MultiLinePrompt (y, txt3, prompt_width, programFont);
8654 
8655 #ifdef WIN_MAC
8656   hgt = 90;
8657 #else
8658   hgt = 110;
8659 #endif
8660   udp->letters = AutonomousPanel4 (y, prompt_width + Nlm_vScrollBarWidth, hgt,
8661 				   LetDraw, NULL, LetScrl, 0, NULL, NULL);
8662   SetObjectExtra (udp->letters, (Pointer) udp, NULL);
8663 
8664   if (indexerVersion && shftKey) {
8665     ButtoN  b;
8666     z = HiddenGroup (y, 2, 0, NULL);
8667     SetGroupSpacing (z, 10, 3);
8668     b = PushButton (z, "Print Graphic", PrintGAln);
8669     SetObjectExtra (b, (Pointer) udp, NULL);
8670     b = PushButton (z, "Display Alignment", PrintTAln);
8671     SetObjectExtra (b, (Pointer) udp, NULL);
8672   }
8673 
8674   udp->ovpict = NULL;
8675   udp->dtpict = NULL;
8676 
8677   AlignObjects (ALIGN_CENTER, (HANDLE) udp->overview,
8678                 (HANDLE) udp->details, (HANDLE) udp->letters,
8679                 (HANDLE) ppt1, (HANDLE) ppt2,
8680                 (HANDLE) ppt3, NULL);
8681 
8682   right_panel = HiddenGroup (x, -1, 0, NULL);
8683   y = right_panel;
8684 
8685   k = HiddenGroup (y, -1, 0, NULL);
8686   g = CreateUpdateOperationsGroup (k, udp);
8687   misc_options = CreateExtraUpdateOptionsGroup (k, udp);
8688   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) misc_options, NULL);
8689 
8690   c = HiddenGroup (w, 5, 0, NULL);
8691   if (udp->isSet)
8692   {
8693     udp->accept = DefaultButton (c, "Accept", AcceptRMCOrExtendSet);
8694     SetObjectExtra (udp->accept, (Pointer) udp, NULL);
8695     udp->acceptAll = DefaultButton (c, "Accept All", AcceptRMCOrExtendAll);
8696     SetObjectExtra (udp->acceptAll, (Pointer) udp, NULL);
8697     b = PushButton (c, "Skip", SkipUpdateBtn);
8698     SetObjectExtra (b, (Pointer) udp, NULL);
8699   }
8700   else
8701   {
8702     udp->accept = DefaultButton (c, "Accept", AcceptRMCOrExtend);
8703     SetObjectExtra (udp->accept, (Pointer) udp, NULL);
8704   }
8705 
8706   b = PushButton (c, "Cancel", CancelUpdate);
8707   SetObjectExtra (b, (Pointer) udp, NULL);
8708   UpdateButtons (udp->rmc);
8709 
8710   AlignObjects (ALIGN_CENTER,
8711                 (HANDLE) ppt0,
8712                 (HANDLE) x,
8713                 (HANDLE) c, (HANDLE) z, NULL);
8714   RealizeWindow (w);
8715 
8716   udp->ovpict = MakeAlignPicture (udp, strid1, strid2, udp->salp);
8717   scaleX = CalculateBestScale (udp, udp->overview, udp->ovpict);
8718   AttachPicture (udp->overview, udp->ovpict, 0, 0, UPPER_LEFT,
8719 		 scaleX, 1, FrameVwr);
8720 
8721   udp->dtpict = MakeAlignDetails (udp, strid1, strid2, udp->salp);
8722   scaleX = CalculateBestScale (udp, udp->details, udp->dtpict);
8723   udp->scaleX = scaleX;
8724   AttachPicture (udp->details, udp->dtpict, 0, 0, UPPER_LEFT,
8725 		 scaleX, 1, FrameVwr);
8726   SetViewerData (udp->details, (Pointer) udp, NULL);
8727   SetViewerProcs (udp->details, DtlClck, NULL, NULL, NULL);
8728 
8729   udp->indels = ValNodeSort (udp->indels, SortVnpByInt);
8730   udp->mismatches = ValNodeSort (udp->mismatches, SortVnpByInt);
8731 
8732   SelectFont (SetSmallFont ());
8733   ObjectRect (udp->letters, &r);
8734   InsetRect (&r, 4, 4);
8735   udp->lineheight = LineHeight ();
8736   udp->charwidth = MaxCharWidth ();
8737   udp->maxchars = (r.right-r.left-2+udp->charwidth - 1) / udp->charwidth;
8738   SelectFont (systemFont);
8739 
8740   sb = GetSlateHScrollBar ((SlatE) udp->letters);
8741   SetBarMax (sb, udp->aln_length - (Int4) udp->maxchars);
8742   CorrectBarPage (sb, (Int4) udp->maxchars - 1, (Int4) udp->maxchars - 1);
8743 
8744   udp->recomb1 = -1;
8745   udp->recomb2 = -1;
8746 
8747   return (ForM) w;
8748 }
8749 
8750 
8751 /*=====================================================================*/
8752 /*                                                                     */
8753 /* PrepareToUpdateSequences ()                                         */
8754 /*                                                                     */
8755 /*=====================================================================*/
8756 
PrepareToUpdateSequences(UpsDataPtr udp)8757 static Boolean PrepareToUpdateSequences (UpsDataPtr udp)
8758 {
8759   ForM         f;
8760 
8761   if ( ! PrepareUpdatePtr (udp))
8762   {
8763     CloseOutSequenceUpdateLog (udp);
8764     return FALSE;
8765   }
8766 
8767   if (TRUE == udp->useGUI)
8768   {
8769     if (udp->salp == NULL && udp->do_update &&
8770         (udp->no_aln_choice == UPDATE_REPLACE_THIS
8771          || udp->no_aln_choice == UPDATE_SKIP_THIS
8772          || udp->no_aln_choice == UPDATE_REPLACE_ALL
8773          || udp->no_aln_choice == UPDATE_REPLACE_THIS))
8774     {
8775       CalculateOverhangs (udp);
8776       DoAcceptRMCOrExtendSet (udp);
8777       UpdateNextBioseqInFastaSet (udp);
8778     }
8779     else
8780     {
8781       f = UpdateSequenceForm (udp);
8782       if (f == NULL)
8783       {
8784         CloseOutSequenceUpdateLog (udp);
8785         return FALSE;
8786       }
8787       Show (f);
8788       Select (f);
8789       SendHelpScrollMessage (helpForm, "Edit Menu", "Update Sequence");
8790     }
8791   }
8792   else {
8793     CalculateOverhangs (udp);
8794     DoAcceptRMCOrExtendSet (udp);
8795   }
8796   return TRUE;
8797 }
8798 
8799 /*=====================================================================*/
8800 /*                                                                     */
8801 /* FindMatchingBioseq () -- Callback function for exploring Bioseqs.   */
8802 /*                          Finds the bioseq that matches a given      */
8803 /*                          string ID.                                 */
8804 /*                                                                     */
8805 /*=====================================================================*/
8806 
FindMatchingBioseq(BioseqPtr bsp,SeqMgrBioseqContextPtr bContext)8807 static Boolean LIBCALLBACK FindMatchingBioseq (BioseqPtr bsp,
8808 					SeqMgrBioseqContextPtr bContext)
8809 {
8810   Char          currentId[MAX_ID_LEN];
8811   UpdateDataPtr pUpdateData;
8812   Int2          result;
8813   SeqIdPtr      sip, sip_next;
8814 
8815   pUpdateData = (UpdateDataPtr) bContext->userdata;
8816 
8817   /* Get the string IDs for the current Bioseq */
8818 
8819   for (sip = bsp->id; sip != NULL; sip = sip->next)
8820   {
8821     sip_next = sip->next;
8822     sip->next = NULL;
8823     SeqIdWrite (sip, currentId, PRINTID_TEXTID_ACC_ONLY,
8824 	            sizeof (currentId) - 1);
8825 
8826     /* Compare it to the string ID of the new Bioseq */
8827 
8828     result = StringICmp (pUpdateData->newId, currentId);
8829 
8830     /* if TEXTID_ACC_ONLY doesn't match, try PRINTID_REPORT */
8831     if (result != 0)
8832     {
8833       SeqIdWrite (sip, currentId, PRINTID_REPORT,
8834 	                sizeof (currentId) - 1);
8835 
8836       /* Compare it to the string ID of the new Bioseq */
8837 
8838       result = StringICmp (pUpdateData->newId, currentId);
8839     }
8840 
8841 	  sip->next = sip_next;
8842     /* If they match, save the Bioseq and quit searching */
8843 
8844     if (0 == result) {
8845       pUpdateData->matchingBsp = bsp;
8846       return FALSE;
8847     }
8848   }
8849 
8850   /* Else continue */
8851 
8852   return TRUE;
8853 }
8854 
SkipProteinInNucUpdate(SeqEntryPtr sep,UpsDataPtr udp)8855 static Boolean SkipProteinInNucUpdate (SeqEntryPtr sep, UpsDataPtr udp)
8856 {
8857   Char       newId[MAX_ID_LEN];
8858   SeqIdPtr   sip;
8859   BioseqPtr  bsp;
8860   Boolean    rval = FALSE;
8861   MsgAnswer  ans;
8862 
8863   if (sep == NULL || ! IS_Bioseq (sep) || sep->data.ptrvalue == NULL || udp == NULL)
8864   {
8865     return FALSE;
8866   }
8867 
8868   bsp = (BioseqPtr) sep->data.ptrvalue;
8869   if (ISA_na (bsp->mol))
8870   {
8871     return FALSE;
8872   }
8873 
8874   sip = SeqIdFindWorst (bsp->id);
8875   SeqIdWrite (sip, newId, PRINTID_REPORT, sizeof (newId) - 1);
8876   ans = Message (MSG_YN, "Found a protein (%s) in the update file, expecting "
8877          "only nucleotides.  Do you want to skip this sequence and continue?", newId);
8878   if (ans == ANS_YES)
8879   {
8880     rval = TRUE;
8881     fprintf (udp->log_fp, "Skipped protein Bioseq (%s) in nucleotide update\n", newId);
8882 	  udp->data_in_log = TRUE;
8883   }
8884   return rval;
8885 }
8886 
RemoveUpdateSet(UpsDataPtr udp)8887 static void RemoveUpdateSet (UpsDataPtr udp)
8888 {
8889 #if 0
8890   ObjMgrPtr omp;
8891   Int2      entityID;
8892 
8893   if (udp == NULL || udp->seqsubsep == NULL)
8894   {
8895     return;
8896   }
8897   entityID = SeqMgrGetEntityIDForSeqEntry (udp->seqsubsep);
8898   udp->seqsubsep = SeqEntryFree (udp->seqsubsep);
8899 	omp = ObjMgrGet ();
8900 	ObjMgrReapOne (omp);
8901 	ObjMgrFreeCache (0);
8902   ObjMgrSendMsg(OM_MSG_DEL, entityID, 0, 0);
8903 #endif
8904 }
8905 
8906 /*=====================================================================*/
8907 /*                                                                     */
8908 /* UpdateNextBioseqInFastaSet () - Reads in one Bioseq from a FASTA set*/
8909 /*                                 file and updates the corresponding  */
8910 /*                                 Bioseq in memory.                   */
8911 /*                                                                     */
8912 /*=====================================================================*/
8913 
UpdateNextBioseqInFastaSet(UpsDataPtr udp)8914 static Int2 UpdateNextBioseqInFastaSet (UpsDataPtr udp)
8915 {
8916   BioseqPtr     bsp;
8917   BioseqSetPtr  bssp;
8918   Pointer       dataptr;
8919   Uint2         datatype;
8920   Char          errMsg[256];
8921   BioseqPtr     nbsp;
8922   SeqEntryPtr   nwsep = NULL;
8923   SeqEntryPtr   sep = NULL;
8924   SeqIdPtr      sip;
8925   SeqSubmitPtr  ssp;
8926   UpdateData    updateData;
8927   SeqEntryPtr   nthBspSep;
8928   BioseqPtr     nthBsp;
8929   Boolean       skip_prot_in_nuc;
8930 
8931   sep = GetTopSeqEntryForEntityID (udp->input_entityID);
8932   bsp = GetBioseqGivenIDs (udp->input_entityID,
8933 			   udp->input_itemID,
8934 			   udp->input_itemtype);
8935 
8936   updateData.matchingBsp = NULL;
8937   /* keep reading file until we find a sequence that matches
8938    * one that we have.
8939    */
8940   while (updateData.matchingBsp == NULL)
8941   {
8942     skip_prot_in_nuc = FALSE;
8943     if (udp->seqsubsep == NULL)
8944     {
8945       /* Read in one sequence from the file */
8946       dataptr = ReadAsnFastaOrFlatFile (udp->fp, &datatype, NULL, FALSE, FALSE,
8947 		                   	                  TRUE, FALSE);
8948 
8949       if (NULL == dataptr)
8950       {
8951         FileClose (udp->fp);
8952         CloseOutSequenceUpdateLog (udp);
8953         RemoveUpdateSet (udp);
8954         return FASTA_READ_DONE;
8955       }
8956 
8957       /* Convert the file data to a SeqEntry */
8958 
8959       if (datatype == OBJ_SEQENTRY)
8960         nwsep = (SeqEntryPtr) dataptr;
8961       else if (datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET)
8962         nwsep = SeqMgrGetSeqEntryForData (dataptr);
8963       else if (datatype == OBJ_SEQSUB)
8964       {
8965         ssp = (SeqSubmitPtr) dataptr;
8966         if (ssp != NULL && ssp->datatype == 1)
8967         {
8968           nwsep = (SeqEntryPtr) ssp->data;
8969           udp->seqsubsep = nwsep;
8970           udp->seqsubpos = 1;
8971         }
8972       }
8973 
8974       if (nwsep == NULL)
8975       {
8976         FileClose (udp->fp);
8977         ErrPostEx (SEV_ERROR, 0, 0, "Unable to convert file data into SeqEntry.");
8978         CloseOutSequenceUpdateLog (udp);
8979         return FASTA_READ_ERROR;
8980       }
8981 
8982       /* Use the new SeqEntry to get a Bioseq */
8983 
8984       if (ISA_na (bsp->mol))
8985       {
8986         nbsp = FindNucBioseq (nwsep);
8987       }
8988       else
8989       {
8990         nwsep = FindNthBioseq (nwsep, 1);
8991         if (nwsep == NULL || nwsep->choice != 1)
8992         {
8993           CloseOutSequenceUpdateLog (udp);
8994           return FASTA_READ_ERROR;
8995         }
8996         nbsp = (BioseqPtr) nwsep->data.ptrvalue;
8997       }
8998       if (nbsp == NULL)
8999       {
9000         if (ISA_na (bsp->mol))
9001         {
9002           skip_prot_in_nuc = SkipProteinInNucUpdate (nwsep, udp);
9003         }
9004         if (! skip_prot_in_nuc)
9005         {
9006           FileClose (udp->fp);
9007           ErrPostEx (SEV_ERROR, 0, 0, "Unable to convert file data into Bioseq.");
9008           CloseOutSequenceUpdateLog (udp);
9009           return FASTA_READ_ERROR;
9010         }
9011       }
9012     }
9013     else
9014     {
9015       /* get the next Bioseq from the record */
9016       udp->seqsubpos ++;
9017       nthBspSep = FindNthBioseq (udp->seqsubsep, udp->seqsubpos);
9018       nbsp = NULL;
9019       while (nthBspSep != NULL && nbsp == NULL)
9020       {
9021         if (!IS_Bioseq (nthBspSep))
9022         {
9023           udp->seqsubpos++;
9024           nthBspSep = FindNthBioseq (udp->seqsubsep, udp->seqsubpos);
9025         }
9026         else
9027         {
9028           nthBsp = nthBspSep->data.ptrvalue;
9029           if (ISA_na (bsp->mol) && ISA_na (nthBsp->mol))
9030           {
9031             nbsp = nthBsp;
9032           }
9033           else if (ISA_aa (bsp->mol) && ISA_aa (nthBsp->mol))
9034           {
9035             nbsp = nthBsp;
9036           }
9037           else
9038           {
9039             udp->seqsubpos++;
9040             nthBspSep = FindNthBioseq (udp->seqsubsep, udp->seqsubpos);
9041           }
9042         }
9043       }
9044       if (nthBspSep == NULL)
9045       {
9046         RemoveUpdateSet (udp);
9047         return FASTA_READ_DONE;
9048       }
9049     }
9050 
9051     if (!skip_prot_in_nuc)
9052     {
9053       /* Get the string ID for the new Bioseq so that we */
9054       /* can find a matching ID among current Bioseqs.   */
9055 
9056       sip = SeqIdFindWorst (nbsp->id);
9057       SeqIdWrite (sip, updateData.newId, PRINTID_REPORT,
9058 	                sizeof (updateData.newId) - 1);
9059 
9060       /* Find the matching bioseq in the current sequence set */
9061 
9062       updateData.matchingBsp = NULL;
9063       if (2 == sep->choice )
9064       {
9065         bssp = (BioseqSetPtr) sep->data.ptrvalue;
9066         SeqMgrExploreBioseqs (0, (Pointer) bssp, &updateData, FindMatchingBioseq,
9067 			                     TRUE, TRUE, TRUE);
9068       }
9069       else
9070       {
9071         bsp = (BioseqPtr) sep->data.ptrvalue;
9072         SeqMgrExploreBioseqs (0, (Pointer) bsp, &updateData, FindMatchingBioseq,
9073 			                        TRUE, TRUE, TRUE);
9074       }
9075 
9076 
9077       if (updateData.matchingBsp == NULL)
9078       {
9079         OpenSequenceUpdateLog (udp);
9080         if (udp->log_fp != NULL)
9081         {
9082           fprintf (udp->log_fp, "No Bioseq found with ID matching that of the"
9083 	                     " one in the file (%s)\n", updateData.newId);
9084 	        udp->data_in_log = TRUE;
9085         }
9086         sprintf (errMsg, "No Bioseq found with ID matching that of the"
9087                        " one in the file (%s)", updateData.newId);
9088         ErrPostEx (SEV_ERROR, 0, 0, errMsg);
9089       }
9090     }
9091   }
9092 
9093   /* Do the updating of the sequences */
9094 
9095   udp->oldbsp = updateData.matchingBsp;
9096   udp->newbsp = nbsp;
9097 
9098   if (! PrepareToUpdateSequences (udp))
9099   {
9100     return FASTA_READ_DONE;
9101   }
9102 
9103   return FASTA_READ_OK;
9104 }
9105 
9106 /*=====================================================================*/
9107 /*                                                                     */
9108 /* UpdateFastaSet () - Updates a set of sequence from a FASTA file     */
9109 /*                     containing a set of sequences.                  */
9110 /*                                                                     */
9111 /*=====================================================================*/
9112 
UpdateOrExtendFastaSet(IteM i,Boolean do_update)9113 static void UpdateOrExtendFastaSet (IteM i, Boolean do_update)
9114 {
9115   BaseFormPtr   bfp;
9116   FILE         *fp;
9117   Char          path [PATH_MAX];
9118   UpsDataPtr    udp;
9119 
9120   /* Check parameters */
9121 
9122 #ifdef WIN_MAC
9123   bfp = currentFormDataPtr;
9124 #else
9125   bfp = GetObjectExtra (i);
9126 #endif
9127 
9128   if (bfp == NULL)
9129     return;
9130 
9131   /* Read in the update data from a file */
9132 
9133   if (! GetInputFileName (path, sizeof (path),"","TEXT"))
9134     return;
9135   fp = FileOpen (path, "r");
9136   if (fp == NULL)
9137     return;
9138 
9139   /* Create data ptr */
9140 
9141   udp = (UpsDataPtr) MemNew (sizeof (UpsData));
9142   if (udp == NULL)
9143     return;
9144 
9145   udp->input_entityID = bfp->input_entityID;
9146   udp->input_itemID   = bfp->input_itemID;
9147   udp->input_itemtype = bfp->input_itemtype;
9148   udp->fp             = fp;
9149   udp->useGUI         = TRUE;
9150   udp->isSet          = TRUE;
9151   udp->convertPubs    = CONVERTPUBS_NO; /* was CONVERTPUBS_NOT_SET */
9152   udp->do_update      = do_update;
9153   udp->suppress_continue_msg = FALSE;
9154   udp->suppress_instant_refresh = FALSE;
9155   udp->log_fp         = NULL;
9156   udp->data_in_log    = FALSE;
9157   udp->transl_except_list = NULL;
9158   udp->aln1           = NULL;
9159   udp->aln2           = NULL;
9160 
9161   /* Update one Bioseq from the file.  Note that this chains */
9162   /* to the processing of the Bioseq after that, so that     */
9163   /* actually all Bioseqs are processed by this call.        */
9164 
9165   UpdateNextBioseqInFastaSet (udp);
9166 
9167 }
9168 
UpdateFastaSet(IteM i)9169 extern void UpdateFastaSet (IteM i)
9170 {
9171   UpdateOrExtendFastaSet (i, TRUE);
9172 }
9173 
9174 typedef struct extendsequences
9175 {
9176   FEATURE_FORM_BLOCK
9177 
9178   BioseqPtr  newbsp;
9179   Boolean    add_cit_sub;
9180   Boolean    extend5;
9181   FILE *     log_fp;
9182   Char       log_path [PATH_MAX];
9183   ValNodePtr sequence_list;
9184   Boolean    data_in_log;
9185   LisT       sequence_list_ctrl;
9186   ButtoN     add_cit_sub_btn;
9187   GrouP      extend_end;
9188 
9189 } ExtendSequencesData, PNTR ExtendSequencesPtr;
9190 
ExtendAllSequencesInSetCallback(BioseqPtr bsp,Pointer userdata)9191 static void ExtendAllSequencesInSetCallback (BioseqPtr bsp, Pointer userdata)
9192 {
9193   ExtendSequencesPtr    esp;
9194   SeqIdPtr              sip, id_next;
9195   Char                  acc_str [256];
9196   CharPtr               origSeqStr;
9197   CharPtr               newSeqStr;
9198   CharPtr               mergedSeqStr;
9199   Int4                  mergedLen;
9200   ByteStorePtr          mergedBS;
9201   Int4                  offset;
9202   SeqMgrFeatContext     context;
9203   SeqFeatPtr            sfp;
9204   CdRegionPtr           crp;
9205   CodeBreakPtr          cbp;
9206   RnaRefPtr             rrp;
9207   tRNAPtr               trp;
9208 
9209   if (bsp == NULL || userdata == NULL) return;
9210   esp = (ExtendSequencesPtr) userdata;
9211 
9212   if (bsp == esp->newbsp) return;
9213 
9214   /* Get original and new sequences */
9215 
9216   origSeqStr = GetSequenceByBsp (bsp);
9217   newSeqStr = GetSequenceByBsp (esp->newbsp);
9218 
9219   /* create string to hold extended sequence */
9220   mergedLen =  StringLen (newSeqStr) + StringLen (origSeqStr);
9221   mergedSeqStr = (CharPtr) MemNew (mergedLen + 1);
9222 
9223   if (esp->extend5)
9224   {
9225     /* prepend the new sequence */
9226     sprintf (mergedSeqStr, "%s%s", newSeqStr, origSeqStr);
9227   }
9228   else
9229   {
9230     /* append the new sequence */
9231     sprintf (mergedSeqStr, "%s%s", origSeqStr, newSeqStr);
9232   }
9233 
9234   /* Convert the new sequence into a ByteStore */
9235 
9236   mergedBS = BSNew (mergedLen);
9237   BSWrite (mergedBS, (VoidPtr) mergedSeqStr, mergedLen);
9238 
9239   /* Replace the original sequence with the */
9240   /* new concatenated sequence.             */
9241 
9242   bsp->seq_data      = SeqDataFree (bsp->seq_data, bsp->seq_data_type);
9243   bsp->seq_data      = (SeqDataPtr) mergedBS;
9244   bsp->seq_data_type = Seq_code_iupacna;
9245   bsp->length        = mergedLen;
9246 
9247   /* shift the features downstream for 5' extension */
9248   offset = StringLen (newSeqStr);
9249   sip = SeqIdFindBest (bsp->id, 0);
9250   if (sip == NULL) return;
9251   if (esp->extend5 && offset > 0)
9252   {
9253     sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
9254     while (sfp != NULL) {
9255       OffsetLocation (sfp->location, offset, sip);
9256       switch (sfp->data.choice) {
9257         case SEQFEAT_CDREGION :
9258           crp = (CdRegionPtr) sfp->data.value.ptrvalue;
9259           if (crp != NULL) {
9260             for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
9261               OffsetLocation (cbp->loc, offset, sip);
9262             }
9263           }
9264           break;
9265         case SEQFEAT_RNA :
9266           rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
9267           if (rrp != NULL && rrp->ext.choice == 2) {
9268             trp = (tRNAPtr) rrp->ext.value.ptrvalue;
9269             if (trp != NULL && trp->anticodon != NULL) {
9270               OffsetLocation (trp->anticodon, offset, sip);
9271             }
9272           }
9273           break;
9274         default :
9275           break;
9276       }
9277       sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
9278     }
9279   }
9280 
9281   if (esp->add_cit_sub)
9282   {
9283     AddCitSubToUpdatedSequence ( bsp, esp->input_entityID, kSubmitterUpdateText);
9284   }
9285 
9286   if (esp->log_fp != NULL)
9287   {
9288     id_next = sip->next;
9289     sip->next = NULL;
9290     SeqIdWrite (sip, acc_str, PRINTID_REPORT, sizeof (acc_str) - 1);
9291     sip->next = id_next;
9292     if (esp->extend5)
9293     {
9294       fprintf (esp->log_fp, "Extended %s at 5' end\n", acc_str);
9295     }
9296     else
9297     {
9298       fprintf (esp->log_fp, "Extended %s at 3' end\n", acc_str);
9299     }
9300     esp->data_in_log = TRUE;
9301   }
9302 }
9303 
DoExtendAllSequencesInSet(ButtoN b)9304 static void DoExtendAllSequencesInSet (ButtoN b)
9305 {
9306   ExtendSequencesPtr    esp;
9307   SeqEntryPtr           topsep;
9308   ValNodePtr            sip_list, vnp;
9309   SeqIdPtr              sip;
9310   BioseqPtr             bsp;
9311 
9312   esp = (ExtendSequencesPtr) GetObjectExtra (b);
9313   if (esp == NULL)
9314   {
9315     return;
9316   }
9317 
9318   esp->add_cit_sub = GetStatus (esp->add_cit_sub_btn);
9319   if (GetValue (esp->extend_end) == 1)
9320   {
9321     esp->extend5 = TRUE;
9322   }
9323   else
9324   {
9325     esp->extend5 = FALSE;
9326   }
9327   sip_list = GetSelectedSequenceList (esp->sequence_list_ctrl);
9328 
9329   /* create file for log */
9330   TmpNam (esp->log_path);
9331   esp->log_fp = FileOpen (esp->log_path, "wb");
9332 
9333   topsep = GetTopSeqEntryForEntityID (esp->input_entityID);
9334   if (topsep == NULL)
9335     return;
9336 
9337   for (vnp = sip_list; vnp != NULL; vnp = vnp->next)
9338   {
9339     sip = (SeqIdPtr) vnp->data.ptrvalue;
9340     bsp = BioseqFind (sip);
9341     if (bsp != NULL)
9342     {
9343       ExtendAllSequencesInSetCallback (bsp, esp);
9344     }
9345   }
9346 
9347   if (esp->log_fp != NULL)
9348   {
9349     FileClose (esp->log_fp);
9350     esp->log_fp = NULL;
9351     if (esp->data_in_log)
9352     {
9353       LaunchGeneralTextViewer (esp->log_path, "Extended Sequences");
9354       esp->data_in_log = FALSE;
9355     }
9356     FileRemove (esp->log_path);
9357   }
9358   ObjMgrSetDirtyFlag (esp->input_entityID, TRUE);
9359   ObjMgrSendMsg (OM_MSG_UPDATE, esp->input_entityID, 0, 0);
9360   Remove (esp->form);
9361   Update ();
9362 }
9363 
SelectAllSequencesForExtend(ButtoN b)9364 static void SelectAllSequencesForExtend (ButtoN b)
9365 {
9366   ExtendSequencesPtr    esp;
9367 
9368   esp = (ExtendSequencesPtr) GetObjectExtra (b);
9369   if (esp == NULL)
9370   {
9371     return;
9372   }
9373   SelectAllSequencesInListCtrl (esp->sequence_list_ctrl);
9374 }
9375 
UnSelectAllSequencesForExtend(ButtoN b)9376 static void UnSelectAllSequencesForExtend (ButtoN b)
9377 {
9378   ExtendSequencesPtr    esp;
9379 
9380   esp = (ExtendSequencesPtr) GetObjectExtra (b);
9381   if (esp == NULL)
9382   {
9383     return;
9384   }
9385   UnSelectAllSequencesInListCtrl (esp->sequence_list_ctrl);
9386 }
9387 
9388 
ExtendAllSequencesInSet(IteM i)9389 extern void ExtendAllSequencesInSet (IteM i)
9390 {
9391   BaseFormPtr        bfp;
9392   FILE              *fp;
9393   Char               path [PATH_MAX];
9394   Pointer            dataptr;
9395   Uint2              datatype;
9396   SeqEntryPtr        nwsep = NULL, topsep;
9397   SeqSubmitPtr       ssp;
9398   BioseqPtr          nbsp;
9399   BioseqPtr          bsp;
9400   ExtendSequencesPtr esp;
9401   WindoW             w;
9402   GrouP              h, g, c;
9403   ButtoN             b;
9404 
9405 #ifdef WIN_MAC
9406   bfp = currentFormDataPtr;
9407 #else
9408   bfp = GetObjectExtra (i);
9409 #endif
9410 
9411   if (bfp == NULL)
9412     return;
9413 
9414   topsep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9415   if (topsep == NULL)
9416     return;
9417 
9418   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID,
9419 			   bfp->input_itemtype);
9420   if (bsp == NULL)
9421   {
9422     Message (MSG_ERROR, "You must select a bioseq");
9423     return;
9424   }
9425 
9426   /* Read in the update data from a file */
9427 
9428   if (! GetInputFileName (path, sizeof (path),"","TEXT"))
9429     return;
9430   fp = FileOpen (path, "r");
9431   if (fp == NULL)
9432   {
9433     Message (MSG_ERROR, "Unable to open %s", path);
9434     return;
9435   }
9436 
9437   /* Create data ptr */
9438   dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, NULL, FALSE, FALSE,
9439 		                 	              TRUE, FALSE);
9440 
9441   FileClose (fp);
9442   if (NULL == dataptr)
9443   {
9444     Message (MSG_ERROR, "Unable to read sequence data from %s", path);
9445     return;
9446   }
9447 
9448   /* Convert the file data to a SeqEntry */
9449 
9450   if (datatype == OBJ_SEQENTRY)
9451     nwsep = (SeqEntryPtr) dataptr;
9452   else if (datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET)
9453     nwsep = SeqMgrGetSeqEntryForData (dataptr);
9454   else if (datatype == OBJ_SEQSUB)
9455   {
9456     ssp = (SeqSubmitPtr) dataptr;
9457     if (ssp != NULL && ssp->datatype == 1)
9458     {
9459       nwsep = (SeqEntryPtr) ssp->data;
9460     }
9461   }
9462 
9463   if (nwsep == NULL)
9464   {
9465     ErrPostEx (SEV_ERROR, 0, 0, "Unable to convert file data into SeqEntry.");
9466     return;
9467   }
9468 
9469   /* Use the new SeqEntry to get a Bioseq */
9470 
9471   if (ISA_na (bsp->mol))
9472   {
9473     nbsp = FindNucBioseq (nwsep);
9474   }
9475   else
9476   {
9477     nwsep = FindNthBioseq (nwsep, 1);
9478     if (nwsep == NULL || nwsep->choice != 1)
9479     {
9480       return;
9481     }
9482     nbsp = (BioseqPtr) nwsep->data.ptrvalue;
9483   }
9484 
9485   if (nbsp == NULL)
9486   {
9487     ErrPostEx (SEV_ERROR, 0, 0, "Unable to convert file data into Bioseq.");
9488     return;
9489   }
9490 
9491   esp = (ExtendSequencesPtr) MemNew (sizeof (ExtendSequencesData));
9492   if (esp == NULL) return;
9493   esp->newbsp = nbsp;
9494 
9495   w = FixedWindow (-50, -33, -10, -10, "Extend Sequences", NULL);
9496 
9497   SetObjectExtra (w, esp, StdCleanupFormProc);
9498   esp->form = (ForM) w;
9499   esp->input_entityID = bfp->input_entityID;
9500 
9501   h = HiddenGroup (w, -1, 0, NULL);
9502   SetGroupSpacing (h, 10, 10);
9503 
9504   esp->sequence_list_ctrl = MakeSequenceListControl (h, topsep, NULL, NULL, TRUE, TRUE);
9505   g = HiddenGroup (h, 2, 0, NULL);
9506   b = PushButton (g, "Select All", SelectAllSequencesForExtend);
9507   SetObjectExtra (b, esp, NULL);
9508   b = PushButton (g, "Unselect All", UnSelectAllSequencesForExtend);
9509   SetObjectExtra (b, esp, NULL);
9510 
9511   esp->extend_end = HiddenGroup (h, 2, 0, NULL);
9512   RadioButton (esp->extend_end, "5' end");
9513   RadioButton (esp->extend_end, "3' end");
9514   SetValue (esp->extend_end, 1);
9515 
9516   esp->add_cit_sub_btn = CheckBox (h, "Add Cit Subs to extended sequences", NULL);
9517 
9518 
9519   c = HiddenGroup (h, 4, 0, NULL);
9520   b = DefaultButton (c, "Accept", DoExtendAllSequencesInSet);
9521   SetObjectExtra (b, esp, NULL);
9522   PushButton (c, "Cancel", StdCancelButtonProc);
9523   AlignObjects (ALIGN_CENTER, (HANDLE) esp->sequence_list_ctrl,
9524                 (HANDLE) esp->add_cit_sub_btn, (HANDLE) g,
9525                 (HANDLE) esp->extend_end,
9526                 (HANDLE) c, NULL);
9527   RealizeWindow (w);
9528   Show (w);
9529   Update ();
9530 }
9531 
9532 
9533 
9534 /*=====================================================================*/
9535 /*                                                                     */
9536 /* NewUpdateSequence () - Updates a sequence from a file.              */
9537 /*                                                                     */
9538 /*=====================================================================*/
9539 
NewUpdateOrExtendSequence(IteM i,Boolean do_update)9540 static void NewUpdateOrExtendSequence (IteM i, Boolean do_update)
9541 {
9542   MsgAnswer     ans;
9543   BaseFormPtr   bfp;
9544   BioseqPtr     bsp, nbsp;
9545   Pointer       dataptr = NULL;
9546   Uint2         datatype;
9547   FILE          *fp;
9548   Char          path [PATH_MAX];
9549   SeqEntryPtr   sep, nwsep = NULL;
9550   SeqSubmitPtr  ssp;
9551   UpsDataPtr    udp;
9552 
9553 #ifdef WIN_MAC
9554   bfp = currentFormDataPtr;
9555 #else
9556   bfp = GetObjectExtra (i);
9557 #endif
9558 
9559   /* Get the current Bioseq */
9560 
9561   if (bfp == NULL)
9562     return;
9563 
9564   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9565   if (sep == NULL)
9566     return;
9567   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID,
9568 			   bfp->input_itemtype);
9569   if (bsp == NULL)
9570     return;
9571 
9572   /* Read in the update data from a file */
9573 
9574   if (! GetInputFileName (path, sizeof (path),"","TEXT"))
9575     return;
9576   fp = FileOpen (path, "r");
9577   if (fp == NULL)
9578   {
9579     Message (MSG_ERROR, "Unable to open %s", path);
9580     return;
9581   }
9582   if (bsp->repr == Seq_repr_delta)
9583   {
9584     nwsep = ImportOneGappedSequence (fp);
9585     if (nwsep != NULL && IS_Bioseq (nwsep))
9586     {
9587       nbsp = (BioseqPtr) nwsep->data.ptrvalue;
9588       if (nbsp->repr != Seq_repr_delta)
9589       {
9590         if (ANS_CANCEL == Message (MSG_OKC, "You are updating a delta sequence with a non-delta sequence. "
9591                           "If you choose replace, your delta sequence will no longer be a delta sequence. "
9592                           "Do you wish to continue?"))
9593         {
9594           SeqEntryFree (nwsep);
9595           return;
9596         }
9597       }
9598       SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) nwsep->data.ptrvalue, nwsep);
9599       SeqMgrAddToBioseqIndex (nwsep->data.ptrvalue);
9600       dataptr = nwsep;
9601       datatype = OBJ_SEQENTRY;
9602     }
9603   }
9604   else
9605   {
9606     dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, NULL, FALSE, FALSE,
9607 		  		    TRUE, FALSE);
9608   }
9609   FileClose (fp);
9610   if (dataptr == NULL)
9611     return;
9612 
9613   /* Get a pointer to the new SeqEntry */
9614 
9615   if (datatype == OBJ_SEQENTRY)
9616     nwsep = (SeqEntryPtr) dataptr;
9617   else if (datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET)
9618     nwsep = SeqMgrGetSeqEntryForData (dataptr);
9619   else if (datatype == OBJ_SEQSUB) {
9620     ssp = (SeqSubmitPtr) dataptr;
9621     if (ssp != NULL && ssp->datatype == 1)
9622       nwsep = (SeqEntryPtr) ssp->data;
9623   }
9624 
9625   if (nwsep == NULL)
9626     return;
9627 
9628   /* Use the new SeqEntry to get a Bioseq */
9629 
9630   if (ISA_na (bsp->mol))
9631     nbsp = FindNucBioseq (nwsep);
9632   else {
9633     nwsep = FindNthBioseq (nwsep, 1);
9634     if (nwsep == NULL || nwsep->choice != 1) return;
9635     nbsp = (BioseqPtr) nwsep->data.ptrvalue;
9636   }
9637 
9638   if (nbsp == NULL)
9639     return;
9640 
9641   /* convert delta lit to raw so sequence can be updated */
9642   if (!indexerVersion)
9643   {
9644     /* If original sequence is a not a raw sequence then */
9645     /* ask user for advice on how to proceed.      */
9646 
9647     if (bsp->repr != Seq_repr_raw) {
9648       ans = Message (MSG_YN, "Only raw sequences can be updated."
9649 		     " Do you wish to proceed for copying features?");
9650       if (ans == ANS_NO)
9651         return;
9652     }
9653   }
9654 
9655   /* Create data ptr */
9656 
9657   udp = (UpsDataPtr) MemNew (sizeof (UpsData));
9658   if (udp == NULL)
9659     return;
9660 
9661   udp->input_entityID = bfp->input_entityID;
9662   udp->input_itemID   = bfp->input_itemID;
9663   udp->input_itemtype = bfp->input_itemtype;
9664   udp->oldbsp         = bsp;
9665   udp->newbsp         = nbsp;
9666   udp->fp             = NULL;
9667   udp->isSet          = FALSE;
9668   udp->useGUI         = TRUE;
9669   udp->convertPubs    = CONVERTPUBS_NO; /* was CONVERTPUBS_NOT_SET */
9670   udp->do_update      = do_update;
9671   udp->suppress_continue_msg = FALSE;
9672   udp->suppress_instant_refresh = FALSE;
9673   udp->log_fp         = NULL;
9674   udp->data_in_log    = FALSE;
9675   udp->transl_except_list = NULL;
9676   udp->aln1           = NULL;
9677   udp->aln2           = NULL;
9678 
9679   /* Do the updating of the sequences */
9680 
9681   PrepareToUpdateSequences (udp);
9682 }
9683 
NewUpdateSequence(IteM i)9684 extern void NewUpdateSequence (IteM i)
9685 
9686 {
9687   NewUpdateOrExtendSequence (i, TRUE);
9688 }
9689 
UpdateSeqAfterDownload(BaseFormPtr bfp,BioseqPtr oldbsp,BioseqPtr newbsp)9690 extern void UpdateSeqAfterDownload
9691 (BaseFormPtr bfp,
9692  BioseqPtr oldbsp,
9693  BioseqPtr newbsp)
9694 {
9695   MsgAnswer   ans;
9696   UpsDataPtr  udp;
9697 
9698   /* convert delta lit to raw so sequence can be updated */
9699 
9700   if (oldbsp->repr == Seq_repr_delta && DeltaLitOnly (oldbsp)) {
9701     if (indexerVersion) {
9702       SegOrDeltaBioseqToRaw (oldbsp);
9703       ObjMgrSetDirtyFlag (oldbsp->idx.entityID, TRUE);
9704     } else {
9705       ans = Message (MSG_YN, "Only raw sequences can be updated."
9706 		     " Do you wish to convert this delta sequence to raw?");
9707       if (ans == ANS_YES) {
9708         SegOrDeltaBioseqToRaw (oldbsp);
9709         ObjMgrSetDirtyFlag (oldbsp->idx.entityID, TRUE);
9710       }
9711     }
9712   }
9713 
9714   if (newbsp->repr == Seq_repr_delta && DeltaLitOnly (newbsp)) {
9715     if (indexerVersion) {
9716       SegOrDeltaBioseqToRaw (newbsp);
9717       ObjMgrSetDirtyFlag (newbsp->idx.entityID, TRUE);
9718     } else {
9719       ans = Message (MSG_YN, "Only raw sequences can be updated."
9720 		     " Do you wish to convert this delta sequence to raw?");
9721       if (ans == ANS_YES) {
9722         SegOrDeltaBioseqToRaw (newbsp);
9723         ObjMgrSetDirtyFlag (newbsp->idx.entityID, TRUE);
9724       }
9725     }
9726   }
9727   /* Create data ptr */
9728 
9729   udp = (UpsDataPtr) MemNew (sizeof (UpsData));
9730   if (udp == NULL)
9731     return;
9732 
9733   udp->input_entityID = bfp->input_entityID;
9734   udp->input_itemID   = bfp->input_itemID;
9735   udp->input_itemtype = bfp->input_itemtype;
9736   udp->oldbsp         = oldbsp;
9737   udp->newbsp         = newbsp;
9738   udp->fp             = NULL;
9739   udp->isSet          = FALSE;
9740   udp->useGUI         = TRUE;
9741   udp->convertPubs    = CONVERTPUBS_NO; /* was CONVERTPUBS_NOT_SET */
9742   udp->do_update      = TRUE;
9743   udp->suppress_continue_msg = FALSE;
9744   udp->suppress_instant_refresh = FALSE;
9745   udp->log_fp         = NULL;
9746   udp->data_in_log    = FALSE;
9747   udp->transl_except_list = NULL;
9748   udp->aln1           = NULL;
9749   udp->aln2           = NULL;
9750 
9751   /* Do the updating of the sequences */
9752 
9753   PrepareToUpdateSequences (udp);
9754 }
9755 
9756 
ExtendSeqAfterDownload(BaseFormPtr bfp,BioseqPtr oldbsp,BioseqPtr newbsp)9757 extern void ExtendSeqAfterDownload
9758 (BaseFormPtr bfp,
9759  BioseqPtr oldbsp,
9760  BioseqPtr newbsp)
9761 
9762 {
9763   MsgAnswer   ans;
9764   UpsDataPtr  udp;
9765 
9766   /* convert delta lit to raw so sequence can be updated */
9767 
9768   if (oldbsp->repr == Seq_repr_delta && DeltaLitOnly (oldbsp)) {
9769     if (indexerVersion) {
9770       SegOrDeltaBioseqToRaw (oldbsp);
9771       ObjMgrSetDirtyFlag (oldbsp->idx.entityID, TRUE);
9772     } else {
9773       ans = Message (MSG_YN, "Only raw sequences can be extended."
9774 		     " Do you wish to convert this delta sequence to raw?");
9775       if (ans == ANS_YES) {
9776         SegOrDeltaBioseqToRaw (oldbsp);
9777         ObjMgrSetDirtyFlag (oldbsp->idx.entityID, TRUE);
9778       }
9779     }
9780   }
9781 
9782   if (newbsp->repr == Seq_repr_delta && DeltaLitOnly (newbsp)) {
9783     if (indexerVersion) {
9784       SegOrDeltaBioseqToRaw (newbsp);
9785       ObjMgrSetDirtyFlag (newbsp->idx.entityID, TRUE);
9786     } else {
9787       ans = Message (MSG_YN, "Only raw sequences can be extended."
9788 		     " Do you wish to convert this delta sequence to raw?");
9789       if (ans == ANS_YES) {
9790         SegOrDeltaBioseqToRaw (newbsp);
9791         ObjMgrSetDirtyFlag (newbsp->idx.entityID, TRUE);
9792       }
9793     }
9794   }
9795   /* Create data ptr */
9796 
9797   udp = (UpsDataPtr) MemNew (sizeof (UpsData));
9798   if (udp == NULL)
9799     return;
9800 
9801   udp->input_entityID = bfp->input_entityID;
9802   udp->input_itemID   = bfp->input_itemID;
9803   udp->input_itemtype = bfp->input_itemtype;
9804   udp->oldbsp         = oldbsp;
9805   udp->newbsp         = newbsp;
9806   udp->fp             = NULL;
9807   udp->isSet          = FALSE;
9808   udp->useGUI         = TRUE;
9809   udp->convertPubs    = CONVERTPUBS_NO; /* was CONVERTPUBS_NOT_SET */
9810   udp->do_update      = FALSE;
9811   udp->suppress_continue_msg = FALSE;
9812   udp->suppress_instant_refresh = FALSE;
9813   udp->log_fp         = NULL;
9814   udp->data_in_log    = FALSE;
9815   udp->transl_except_list = NULL;
9816   udp->aln1           = NULL;
9817   udp->aln2           = NULL;
9818 
9819   /* Do the updating of the sequences */
9820 
9821   PrepareToUpdateSequences (udp);
9822 }
9823 
9824 
9825 
9826 /* NEW FEATURE PROPAGATION SECTION */
9827 
9828 
NewFeaturePropagate(IteM i)9829 extern void NewFeaturePropagate (
9830   IteM i
9831 )
9832 
9833 {
9834   BaseFormPtr        bfp;
9835   BioseqPtr          bsp;
9836   ForM               f;
9837   SeqMgrFeatContext  fcontext;
9838   Uint4              itemID = 0;
9839   SeqAlignPtr        salp;
9840   SeqFeatPtr         sfp;
9841   SelStructPtr       sel;
9842   SeqEntryPtr        sep;
9843   BioseqPtr          other_bsp = NULL;
9844 
9845 #ifdef WIN_MAC
9846   bfp = currentFormDataPtr;
9847 #else
9848   bfp = GetObjectExtra (i);
9849 #endif
9850   if (bfp == NULL) return;
9851   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9852   if (sep == NULL) return;
9853   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
9854   if (bsp == NULL) {
9855     Message (MSG_OK, "You must target a single sequence in order to propagate");
9856     return;
9857   }
9858   sfp = GetNextFeatureOnSegOrMaster (bsp, NULL, 0, 0, &fcontext);
9859   if (sfp == NULL)
9860   {
9861     Message (MSG_OK, "The sequence must have features in order to propagate");
9862     return;
9863   }
9864 
9865   sel = ObjMgrGetSelected ();
9866   if (sel != NULL && sel->entityID == bfp->input_entityID &&
9867       sel->next == NULL && sel->itemtype == OBJ_SEQFEAT) {
9868     sfp = SeqMgrGetDesiredFeature (bfp->input_entityID, NULL, sel->itemID, 0, NULL, &fcontext);
9869     if (sfp != NULL) {
9870       if (fcontext.bsp == bsp) {
9871         itemID = sel->itemID;
9872       } else {
9873         other_bsp = fcontext.bsp;
9874       }
9875     }
9876   }
9877 
9878 
9879   salp = FindAlignmentsForBioseq (bsp);
9880 
9881   if (salp == NULL) {
9882     salp = FindAlignmentsForBioseq (other_bsp);
9883     if (salp == NULL) {
9884       Message (MSG_ERROR, "The record must have an alignment in order to propagate");
9885     } else if (other_bsp != NULL) {
9886       if (ISA_aa (other_bsp->mol)) {
9887         Message (MSG_ERROR, "If you want to propagate protein features, you must view the protein sequence where the features are located, not the nucleotide sequence.");
9888       } else if (!ISA_aa (other_bsp->mol) && ISA_aa(bsp->mol)) {
9889         Message (MSG_ERROR, "If you want to propagate nucleotide features, you must view the nucleotide sequence where the features are located, not the protein sequence.");
9890       } else {
9891         Message (MSG_ERROR, "You must view the sequence where the selected feature is located in order to propagate.");
9892       }
9893     }
9894     return;
9895   }
9896 
9897 
9898   f = FeaturePropagateForm (bsp, salp, itemID);
9899   if (f == NULL) return;
9900   Show (f);
9901   Select (f);
9902   SendHelpScrollMessage (helpForm, "Edit Menu", "Feature Propagate");
9903 }
9904 
9905 
FuseFeatJoins(SeqFeatPtr sfp,Pointer userdata)9906 static void FuseFeatJoins (SeqFeatPtr sfp, Pointer userdata)
9907 
9908 {
9909   BioseqPtr  bsp;
9910   Boolean    partial5;
9911   Boolean    partial3;
9912   SeqLocPtr  slp;
9913 
9914   bsp = BioseqFindFromSeqLoc (sfp->location);
9915   if (bsp == NULL) return;
9916 
9917   slp = SeqLocFindNext (sfp->location, NULL);
9918   if (slp == NULL) return;
9919   slp = SeqLocFindNext (sfp->location, slp);
9920   if (slp == NULL) return;
9921 
9922   slp = SeqLocMerge (bsp, sfp->location, NULL, FALSE, TRUE, FALSE);
9923   if (slp == NULL) return;
9924   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
9925   sfp->location = SeqLocFree (sfp->location);
9926   sfp->location = slp;
9927   SetSeqLocPartial (sfp->location, partial5, partial3);
9928 }
9929 
FuseSlpJoins(IteM i)9930 extern void FuseSlpJoins (IteM i)
9931 
9932 {
9933   BaseFormPtr        bfp;
9934   SeqEntryPtr        sep;
9935 
9936 #ifdef WIN_MAC
9937   bfp = currentFormDataPtr;
9938 #else
9939   bfp = GetObjectExtra (i);
9940 #endif
9941   if (bfp == NULL) return;
9942   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9943   if (sep == NULL) return;
9944 
9945   VisitFeaturesInSep (sep, NULL, FuseFeatJoins);
9946 
9947   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
9948   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
9949 }
9950 
DoAuthorityPrefix(BioSourcePtr biop,Pointer userdata)9951 static void DoAuthorityPrefix (BioSourcePtr biop, Pointer userdata)
9952 
9953 {
9954   size_t      len;
9955   OrgModPtr   omp;
9956   OrgNamePtr  onp;
9957   OrgRefPtr   orp;
9958   CharPtr     str;
9959 
9960   if (biop == NULL) return;
9961   orp = biop->org;
9962   if (orp == NULL) return;
9963   if (StringHasNoText (orp->taxname)) return;
9964   len = StringLen (orp->taxname);
9965   onp = orp->orgname;
9966   if (onp == NULL) return;
9967   for (omp = onp->mod; omp != NULL; omp = omp->next) {
9968     if (omp->subtype != ORGMOD_authority) continue;
9969     if (StringNCmp (omp->subname, orp->taxname, len) == 0) continue;
9970     str = MemNew (StringLen (omp->subname) + len + 3);
9971     if (str == NULL) continue;
9972     StringCpy (str, orp->taxname);
9973     StringCat (str, " ");
9974     StringCat (str, omp->subname);
9975     omp->subname = MemFree (omp->subname);
9976     omp->subname = str;
9977   }
9978 }
9979 
PrefixAuthorityWithOrganism(IteM i)9980 extern void PrefixAuthorityWithOrganism (IteM i)
9981 
9982 {
9983   BaseFormPtr  bfp;
9984   SeqEntryPtr  sep;
9985 
9986 #ifdef WIN_MAC
9987   bfp = currentFormDataPtr;
9988 #else
9989   bfp = GetObjectExtra (i);
9990 #endif
9991   if (bfp == NULL) return;
9992   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9993   if (sep == NULL) return;
9994   VisitBioSourcesInSep (sep, NULL, DoAuthorityPrefix);
9995   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
9996   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
9997 }
9998 
9999 typedef struct addtranslexceptdata {
10000   FEATURE_FORM_BLOCK
10001 
10002   TexT        cds_comment;
10003   ButtoN      strict_checking_btn;
10004   ButtoN      extend_btn;
10005   ButtoN      adjust_gene_btn;
10006   CharPtr     cds_comment_txt;
10007   Boolean     strict_checking;
10008   Boolean     extend;
10009   Boolean     adjust_gene;
10010 } AddTranslExceptData, PNTR AddTranslExceptPtr;
10011 
10012 
10013 
SeqLocForTermination(SeqLocPtr slp,Int4 except_len)10014 static SeqLocPtr SeqLocForTermination (SeqLocPtr slp, Int4 except_len)
10015 {
10016   SeqLocPtr term_slp;
10017   BioseqPtr bsp;
10018   Uint1     strand;
10019   Int4      end;
10020 
10021   if (slp == NULL || except_len < 1 || except_len > 2) return NULL;
10022   bsp = BioseqFindFromSeqLoc (slp);
10023   if (bsp == NULL) return NULL;
10024 
10025   strand = SeqLocStrand (slp);
10026   if (strand == Seq_strand_minus) {
10027     end = SeqLocStart (slp);
10028     term_slp = SeqLocIntNew (end, end + except_len - 1, strand, SeqIdDup (SeqIdFindBest (bsp->id, 0)));
10029   } else {
10030     end = SeqLocStop (slp);
10031     term_slp = SeqLocIntNew (end - except_len + 1, end, strand, SeqIdDup (SeqIdFindBest (bsp->id, 0)));
10032   }
10033   return term_slp;
10034 }
10035 
10036 
DoesCodingRegionEndWithStopCodon(SeqFeatPtr sfp)10037 static Boolean DoesCodingRegionEndWithStopCodon (SeqFeatPtr sfp)
10038 {
10039   ByteStorePtr bs;
10040   CharPtr      prot_str;
10041   Boolean      rval = FALSE;
10042 
10043   bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
10044   prot_str = BSMerge (bs, NULL);
10045   bs = BSFree (bs);
10046   if (prot_str != NULL && prot_str[StringLen (prot_str) - 1] == '*') {
10047     rval = TRUE;
10048   }
10049   prot_str = MemFree (prot_str);
10050   return rval;
10051 }
10052 
10053 
AddTerminalExceptionLen(SeqFeatPtr sfp)10054 static Int4 AddTerminalExceptionLen (SeqFeatPtr sfp)
10055 {
10056   BioseqPtr bsp;
10057   Uint1     strand;
10058   Int4      stop, len, except_len = 0, gene_stop;
10059   Char      buf[4];
10060   Int4      rval = 0;
10061   SeqFeatPtr gene;
10062 
10063   if (sfp == NULL || sfp->location == NULL) return FALSE;
10064 
10065   bsp = BioseqFindFromSeqLoc (sfp->location);
10066   if (bsp == NULL) return 0;
10067   strand = SeqLocStrand (sfp->location);
10068   if (strand == Seq_strand_minus) {
10069     stop = SeqLocStart (sfp->location);
10070     len = MIN (stop, 3);
10071     if (len > 0) {
10072       SeqPortStreamInt (bsp, stop - len, stop - 1,
10073                         Seq_strand_minus,STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL,
10074                         buf, NULL);
10075     }
10076   } else {
10077     stop = SeqLocStop (sfp->location);
10078     len = MIN (bsp->length - stop - 1, 3);
10079     if (len > 0) {
10080       SeqPortStreamInt (bsp, stop + 1, stop + len,
10081                         Seq_strand_plus,STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL,
10082                         buf, NULL);
10083     }
10084   }
10085   if (len > 0) {
10086     if (buf[0] == 'T') {
10087       except_len++;
10088       if (buf[1] == 'A') {
10089         except_len++;
10090         if (buf[2] == 'A') {
10091           /* has real stop codon */
10092           except_len++;
10093         }
10094       }
10095     }
10096     if (except_len < 3 && except_len > 0) {
10097       gene = GetGeneForFeature (sfp);
10098       if (strand == Seq_strand_minus) {
10099         if (gene != NULL) {
10100           gene_stop = SeqLocStart (gene->location);
10101           if (gene_stop > stop - except_len) {
10102             ExtendSeqLocToPosition (gene->location, FALSE, stop - except_len);
10103           }
10104         }
10105         ExtendSeqLocToPosition (sfp->location, FALSE, stop - except_len);
10106       } else {
10107         if (gene != NULL) {
10108           gene_stop = SeqLocStop (gene->location);
10109           if (gene_stop < stop + except_len) {
10110             ExtendSeqLocToPosition (gene->location, FALSE, stop + except_len);
10111           }
10112         }
10113         ExtendSeqLocToPosition (sfp->location, FALSE, stop + except_len);
10114       }
10115       rval = except_len;
10116     }
10117   }
10118   return rval;
10119 }
10120 
10121 
AddTranslExcept(SeqFeatPtr sfp,CharPtr cds_comment,Boolean use_strict,Boolean extend,Boolean adjust_gene)10122 extern void AddTranslExcept (SeqFeatPtr sfp, CharPtr cds_comment, Boolean use_strict, Boolean extend, Boolean adjust_gene)
10123 
10124 {
10125   CdRegionPtr        crp;
10126   Boolean            partial5, partial3;
10127   Int4               dna_len;
10128   CharPtr            bases;
10129   Int4               except_len;
10130   Int4               total;
10131   TransTablePtr      tbl = NULL;
10132   Int2               state;
10133   CharPtr            codon_start;
10134   CodeBreakPtr       new_cbp, last_cbp;
10135   Boolean            table_is_local;
10136   CharPtr            new_comment;
10137   Int4               comment_len;
10138   SeqFeatPtr         gene = NULL;
10139   SeqMgrFeatContext  fcontext;
10140 
10141   if (sfp == NULL
10142       || sfp->idx.subtype != FEATDEF_CDS
10143       || (crp = (CdRegionPtr)sfp->data.value.ptrvalue)== NULL) {
10144     return;
10145   }
10146 
10147   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
10148   if (partial3) return;
10149 
10150   dna_len = SeqLocLen (sfp->location);
10151   if (partial5 && crp->frame > 1) {
10152     except_len = (dna_len - crp->frame + 1) % 3;
10153   } else {
10154     except_len = dna_len % 3;
10155   }
10156 
10157   /* if adjusting gene, collect now before location changes */
10158   if (adjust_gene) {
10159     gene = SeqMgrGetOverlappingGene (sfp->location, &fcontext);
10160   }
10161 
10162   if (except_len == 0 && extend && !DoesCodingRegionEndWithStopCodon(sfp)) {
10163     except_len = AddTerminalExceptionLen (sfp);
10164     dna_len = SeqLocLen (sfp->location);
10165   }
10166 
10167   if (except_len == 0) return;
10168 
10169   /* don't add code break if one already exists */
10170   last_cbp = crp->code_break;
10171   if (last_cbp != NULL && last_cbp->aa.choice == 1 && last_cbp->aa.value.intvalue == 42) {
10172     last_cbp->loc = SeqLocFree (last_cbp->loc);
10173     last_cbp->loc = SeqLocForTermination (sfp->location, except_len);
10174     return;
10175   }
10176   while (last_cbp != NULL && last_cbp->next != NULL) {
10177     if (last_cbp->aa.choice == 1 && last_cbp->aa.value.intvalue == 42) {
10178       last_cbp->loc = SeqLocFree (last_cbp->loc);
10179       last_cbp->loc = SeqLocForTermination (sfp->location, except_len);
10180       return;
10181     }
10182     last_cbp = last_cbp->next;
10183   }
10184 
10185   bases = ReadCodingRegionBases (sfp->location, dna_len, crp->frame, &total);
10186   if (bases == NULL) return;
10187 
10188   /* don't add transl_except if cds has valid stop codon */
10189   state = 0;
10190   codon_start = bases + StringLen (bases) - 6;
10191   if (codon_start < bases) {
10192     MemFree (bases);
10193     return;
10194   }
10195   tbl = GetTranslationTable (crp, &table_is_local);
10196   state = 0;
10197   state = NextCodonState (tbl, state, (Uint1)*codon_start);
10198   state = NextCodonState (tbl, state, (Uint1)*(codon_start + 1));
10199   state = NextCodonState (tbl, state, (Uint1)*(codon_start + 2));
10200   if (IsOrfStop (tbl, state, TTBL_TOP_STRAND)) {
10201     MemFree (bases);
10202     if (table_is_local) {
10203       TransTableFree (tbl);
10204     }
10205     return;
10206   }
10207   if (table_is_local) {
10208     TransTableFree (tbl);
10209     tbl = NULL;
10210   }
10211 
10212   if (use_strict)
10213   {
10214   	if (except_len == 2)
10215   	{
10216   	  if (toupper (*(codon_start + 3)) != 'T' || toupper(*(codon_start + 4)) != 'A')
10217   	  {
10218   	  	MemFree (bases);
10219   	  	return;
10220   	  }
10221   	}
10222   	else
10223   	{
10224   	  if (toupper (*(codon_start + 3)) != 'T')
10225   	  {
10226   	  	MemFree (bases);
10227   	  	return;
10228   	  }
10229   	}
10230 
10231   }
10232   else
10233   {
10234     /* don't add transl_except if exception location does not start with 'T' or 'N' */
10235     if (*(codon_start + 3) != 'T' && *(codon_start + 3) != 't'
10236         && *(codon_start + 3) != 'N' && *(codon_start + 3) != 'n') {
10237       MemFree (bases);
10238       return;
10239     }
10240   }
10241   MemFree (bases);
10242 
10243   new_cbp = CodeBreakNew ();
10244   new_cbp->aa.choice = 1;
10245   new_cbp->aa.value.intvalue = 42;
10246   new_cbp->loc = SeqLocForTermination (sfp->location, except_len);
10247 
10248   /* add code break to end of list */
10249   if (last_cbp == NULL) {
10250     crp->code_break = new_cbp;
10251   } else {
10252     last_cbp->next = new_cbp;
10253   }
10254 
10255   /* add comment if there is one, unless it's already there */
10256   if (cds_comment != NULL && StringISearch (sfp->comment, cds_comment) == NULL)
10257   {
10258   	if (StringHasNoText (sfp->comment))
10259   	{
10260   	  sfp->comment = MemFree (sfp->comment);
10261   	  sfp->comment = StringSave (cds_comment);
10262   	}
10263   	else
10264   	{
10265       comment_len = StringLen (sfp->comment) + StringLen (cds_comment) + 3;
10266       new_comment = (CharPtr) MemNew (sizeof (Char) * comment_len);
10267       if (new_comment != NULL)
10268       {
10269       	StringCpy (new_comment, sfp->comment);
10270       	StringCat (new_comment, "; ");
10271       	StringCat (new_comment, cds_comment);
10272       	sfp->comment = MemFree (sfp->comment);
10273       	sfp->comment = new_comment;
10274       }
10275   	}
10276   }
10277 
10278   /* adjust gene if requested */
10279   if (gene != NULL)
10280   {
10281     if (SeqLocCompare (gene->location, sfp->location) != SLC_A_EQ_B)
10282     {
10283       gene->location = SeqLocFree (gene->location);
10284       gene->location = SeqLocCopy (sfp->location);
10285     }
10286   }
10287 }
10288 
10289 
AddTranslExceptCallback(SeqFeatPtr sfp,Pointer userdata)10290 static void AddTranslExceptCallback (SeqFeatPtr sfp, Pointer userdata)
10291 
10292 {
10293   AddTranslExceptPtr ap;
10294   Boolean            use_strict = FALSE;
10295   Boolean            extend = FALSE;
10296   Boolean            adjust_gene = FALSE;
10297   CharPtr            cds_comment = NULL;
10298 
10299   ap = (AddTranslExceptPtr) userdata;
10300   if (ap != NULL)
10301   {
10302     cds_comment = ap->cds_comment_txt;
10303   	use_strict = ap->strict_checking;
10304     extend = ap->extend;
10305     adjust_gene = ap->adjust_gene;
10306   }
10307 
10308   AddTranslExcept (sfp, cds_comment, use_strict, extend, adjust_gene);
10309 }
10310 
10311 
DoAddTranslExceptWithComment(ButtoN b)10312 static void DoAddTranslExceptWithComment (ButtoN b)
10313 {
10314   AddTranslExceptPtr ap;
10315   SeqEntryPtr  sep, oldscope;
10316 
10317   ap = (AddTranslExceptPtr) GetObjectExtra (b);
10318   if (ap == NULL) return;
10319   Hide (ap->form);
10320   sep = GetTopSeqEntryForEntityID (ap->input_entityID);
10321   if (sep == NULL) return;
10322   oldscope = SeqEntrySetScope (sep);
10323   ap->cds_comment_txt = SaveStringFromText (ap->cds_comment);
10324   ap->strict_checking = GetStatus (ap->strict_checking_btn);
10325   ap->extend = GetStatus (ap->extend_btn);
10326   ap->adjust_gene = GetStatus (ap->adjust_gene_btn);
10327   if (StringHasNoText (ap->cds_comment_txt))
10328   {
10329   	ap->cds_comment_txt = MemFree (ap->cds_comment_txt);
10330   }
10331   VisitFeaturesInSep (sep, ap, AddTranslExceptCallback);
10332   ObjMgrSetDirtyFlag (ap->input_entityID, TRUE);
10333   ObjMgrSendMsg (OM_MSG_UPDATE, ap->input_entityID, 0, 0);
10334   ap->cds_comment_txt = MemFree (ap->cds_comment_txt);
10335   Remove (ap->form);
10336   SeqEntrySetScope (oldscope);
10337 }
10338 
ClearComment(ButtoN b)10339 static void ClearComment(ButtoN b)
10340 {
10341   AddTranslExceptPtr ap;
10342 
10343   ap = (AddTranslExceptPtr) GetObjectExtra (b);
10344   if (ap != NULL) {
10345       SetTitle (ap->cds_comment, "");
10346   }
10347 }
10348 
AddTranslExceptWithCommentBaseForm(BaseFormPtr bfp)10349 extern void AddTranslExceptWithCommentBaseForm (BaseFormPtr bfp)
10350 {
10351   AddTranslExceptPtr ap;
10352   WindoW             w;
10353   GrouP              h, g, c;
10354   ButtoN             b, clear_btn;
10355 
10356   if (bfp == NULL) return;
10357 
10358   ap = (AddTranslExceptPtr) MemNew (sizeof (AddTranslExceptData));
10359   w = FixedWindow (-50, -33, -10, -10, "Add Translation Exception", NULL);
10360 
10361   SetObjectExtra (w, ap, StdCleanupFormProc);
10362   ap->form = (ForM) w;
10363   ap->input_entityID = bfp->input_entityID;
10364 
10365   h = HiddenGroup (w, -1, 0, NULL);
10366   SetGroupSpacing (h, 10, 10);
10367 
10368   g = HiddenGroup (h, 2, 0, NULL);
10369   StaticPrompt (g, "CDS comment", 0, 0, programFont, 'c');
10370   ap->cds_comment = DialogText (g, "TAA stop codon is completed by the addition of 3' A residues to the mRNA", 20, NULL);
10371   clear_btn = PushButton (h, "Clear Comment", ClearComment);
10372   SetObjectExtra (clear_btn, ap, NULL);
10373   ap->strict_checking_btn = CheckBox (h, "Overhang must be T or TA", NULL);
10374   SetStatus (ap->strict_checking_btn, TRUE);
10375   ap->extend_btn = CheckBox (h, "Extend for T/TA overhang", NULL);
10376   ap->adjust_gene_btn = CheckBox (h, "Adjust gene to match coding region location", NULL);
10377   SetStatus (ap->adjust_gene_btn, TRUE);
10378 
10379   c = HiddenGroup (h, 4, 0, NULL);
10380   b = DefaultButton (c, "Accept", DoAddTranslExceptWithComment);
10381   SetObjectExtra (b, ap, NULL);
10382   PushButton (c, "Cancel", StdCancelButtonProc);
10383   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) clear_btn,
10384                (HANDLE) ap->strict_checking_btn,
10385                (HANDLE) ap->extend_btn,
10386                (HANDLE) ap->adjust_gene_btn,
10387                (HANDLE) c, NULL);
10388   RealizeWindow (w);
10389   Show (w);
10390   Update ();
10391 }
10392 
10393 
AddTranslExceptWithComment(IteM i)10394 extern void AddTranslExceptWithComment (IteM i)
10395 {
10396   BaseFormPtr        bfp;
10397 
10398 #ifdef WIN_MAC
10399   bfp = currentFormDataPtr;
10400 #else
10401   bfp = GetObjectExtra (i);
10402 #endif
10403   if (bfp == NULL) return;
10404 
10405   AddTranslExceptWithCommentBaseForm (bfp);
10406 }
10407 
10408 
10409 typedef struct updatealignmentlengths
10410 {
10411   Int4 aln_length; /* length of alignment */
10412   Int4 old5;       /* length of 5' end of original sequence that is not
10413                     * included in the alignment.
10414                     */
10415   Int4 old3;       /* length of 3' end of original sequence that is not
10416                     * included in the alignment.
10417                     */
10418   Int4 olda;       /* length of update sequence that is included in the alignment. */
10419   Int4 new5;       /* length of 5' end of update sequence that is not
10420                     * included in the alignment.
10421                     */
10422   Int4 new3;       /* length of 3' end of update sequence that is not
10423                     * included in the alignment.
10424                     */
10425   Int4 newa;       /* length of update sequence that is included in the alignment. */
10426 
10427   Int4 log10_aln_length;
10428 
10429   Int4 recomb1;
10430   Int4 recomb2;
10431 } UpdateAlignmentLengthsData, PNTR UpdateAlignmentLengthsPtr;
10432 
10433 /* holds information about an update pair */
10434 typedef struct updatepair
10435 {
10436   SeqAlignPtr salp;
10437   Boolean     revcomp;
10438   BioseqPtr   orig_bsp;
10439   BioseqPtr   update_bsp;
10440   Boolean     feature_update_successful;
10441   SeqAnnotPtr newfeat_sap;
10442 } UpdatePairData, PNTR UpdatePairPtr;
10443 
10444 /* These structures hold information about how to perform the updates.
10445  * The dialogs for displaying and collecting these structures are farther
10446  * down in the code.
10447  */
10448 typedef enum {
10449   eSequenceUpdateNoChange = 1,
10450   eSequenceUpdateReplace,
10451   eSequenceUpdatePatch,
10452   eSequenceUpdateExtend5,
10453   eSequenceUpdateExtend3
10454 } ESequenceUpdateType;
10455 
10456 typedef enum {
10457   eFeatureUpdateNoChange = 1,
10458   eFeatureUpdateAllExceptDups,
10459   eFeatureUpdateAllMergeDups,
10460   eFeatureUpdateAllReplaceDups,
10461   eFeatureUpdateAll
10462 } EFeatureUpdateType;
10463 
10464 typedef enum {
10465   eFeatureRemoveNone = 1,
10466   eFeatureRemoveAligned,
10467   eFeatureRemoveNotAligned,
10468   eFeatureRemoveAll
10469 } EFeatureRemoveType;
10470 
10471 typedef struct featureimportoptions
10472 {
10473   Uint1      feature_import_type;
10474   ValNodePtr feature_types;
10475 } FeatureImportOptionsData, PNTR FeatureImportOptionsPtr;
10476 
10477 
FeatureImportOptionsNew(void)10478 static FeatureImportOptionsPtr FeatureImportOptionsNew (void)
10479 {
10480   FeatureImportOptionsPtr f;
10481 
10482   f = (FeatureImportOptionsPtr) MemNew (sizeof (FeatureImportOptionsData));
10483   f->feature_import_type = eFeatureUpdateNoChange;
10484   f->feature_types = NULL;
10485   return f;
10486 }
10487 
10488 
FeatureImportOptionsFree(FeatureImportOptionsPtr f)10489 static FeatureImportOptionsPtr FeatureImportOptionsFree (FeatureImportOptionsPtr f)
10490 {
10491   if (f != NULL) {
10492     f->feature_types = ValNodeFree (f->feature_types);
10493     f = MemFree (f);
10494   }
10495   return f;
10496 }
10497 
10498 
10499 typedef struct submitterupdateoptions
10500 {
10501   ESequenceUpdateType     sequence_update_type;
10502   FeatureImportOptionsPtr feature_import_options;
10503   EFeatureRemoveType      feature_remove_type;
10504   Boolean                 ignore_alignment;
10505 } SubmitterUpdateOptionsData, PNTR SubmitterUpdateOptionsPtr;
10506 
10507 
SubmitterUpdateOptionsFree(SubmitterUpdateOptionsPtr s)10508 static SubmitterUpdateOptionsPtr SubmitterUpdateOptionsFree (SubmitterUpdateOptionsPtr s)
10509 {
10510   if (s != NULL) {
10511     s->feature_import_options = FeatureImportOptionsFree(s->feature_import_options);
10512     s = MemFree (s);
10513   }
10514   return s;
10515 }
10516 
10517 
AreSubmitterOptsValid(SubmitterUpdateOptionsPtr opts)10518 static Boolean AreSubmitterOptsValid (SubmitterUpdateOptionsPtr opts)
10519 {
10520   if (opts == NULL
10521       || (opts->sequence_update_type == eSequenceUpdateNoChange
10522           && (opts->feature_import_options == NULL
10523               || opts->feature_import_options->feature_import_type == eFeatureUpdateNoChange
10524               || opts->feature_import_options->feature_import_type == eFeatureRemoveNone)))
10525   {
10526     return FALSE;
10527   } else {
10528     return TRUE;
10529   }
10530 }
10531 
10532 
10533 typedef struct indexer_options
10534 {
10535   Boolean keep_protein_ids;
10536   Boolean add_cit_subs;
10537   Boolean update_quality_scores;
10538   Boolean update_proteins;
10539   Boolean truncate_proteins;
10540   Boolean extend_proteins3;
10541   Boolean extend_proteins5;
10542   Boolean correct_cds_genes;
10543 } IndexerOptionsData, PNTR IndexerOptionsPtr;
10544 
10545 typedef struct updateoptions
10546 {
10547   SubmitterUpdateOptionsPtr submitter_opts;
10548   IndexerOptionsPtr         indexer_opts;
10549 } UpdateOptionsData, PNTR UpdateOptionsPtr;
10550 
UpdateOptionsFree(UpdateOptionsPtr uop)10551 static UpdateOptionsPtr UpdateOptionsFree (UpdateOptionsPtr uop)
10552 {
10553   if (uop != NULL)
10554   {
10555   	uop->submitter_opts = SubmitterUpdateOptionsFree (uop->submitter_opts);
10556   	uop->indexer_opts = MemFree (uop->indexer_opts);
10557   	uop = MemFree (uop);
10558   }
10559   return uop;
10560 }
10561 
10562 /* These functions remove features from portions of the updated sequence:
10563  * RemoveFeatsInAlignedRegion
10564  * RemoveFeatsNotInAlignedRegion
10565  */
10566 static Boolean
RemoveFeatsInAlignedRegion(BioseqPtr orig_bsp,UpdateAlignmentLengthsPtr ualp)10567 RemoveFeatsInAlignedRegion
10568 (BioseqPtr                 orig_bsp,
10569  UpdateAlignmentLengthsPtr ualp)
10570 
10571 {
10572   SeqMgrFeatContext  context;
10573   Int4               left, right;
10574   SeqFeatPtr         sfp;
10575   Boolean            rval = FALSE;
10576 
10577   if (orig_bsp == NULL || ualp == NULL) return FALSE;
10578 
10579   left = ualp->old5;
10580   right = ualp->old5 + ualp->olda;
10581 
10582   sfp = SeqMgrGetNextFeature (orig_bsp, NULL, 0, 0, &context);
10583 
10584   while (sfp != NULL) {
10585 
10586     if (context.right >= left && context.left <= right) {
10587       sfp->idx.deleteme = TRUE;
10588       rval = TRUE;
10589       MarkProductForDeletion (sfp->product);
10590     }
10591 
10592     sfp = SeqMgrGetNextFeature (orig_bsp, sfp, 0, 0, &context);
10593   }
10594   return rval;
10595 }
10596 
10597 static Boolean
RemoveFeatsNotInAlignedRegion(BioseqPtr orig_bsp,UpdateAlignmentLengthsPtr ualp)10598 RemoveFeatsNotInAlignedRegion
10599 (BioseqPtr                 orig_bsp,
10600  UpdateAlignmentLengthsPtr ualp)
10601 
10602 {
10603   SeqMgrFeatContext  context;
10604   Int4               left, right;
10605   SeqFeatPtr         sfp;
10606   Boolean            rval = FALSE;
10607 
10608   if (orig_bsp == NULL || ualp == NULL) return FALSE;
10609 
10610   left = ualp->old5;
10611   right = ualp->old5 + ualp->olda;
10612 
10613   sfp = SeqMgrGetNextFeature (orig_bsp, NULL, 0, 0, &context);
10614 
10615   while (sfp != NULL) {
10616 
10617     if (context.right < left || context.left > right) {
10618       sfp->idx.deleteme = TRUE;
10619       rval = TRUE;
10620       MarkProductForDeletion (sfp->product);
10621     }
10622 
10623     sfp = SeqMgrGetNextFeature (orig_bsp, sfp, 0, 0, &context);
10624   }
10625   return rval;
10626 }
10627 
10628 /* This function adjusts an alignment based on updates to the sequence. */
ShiftAlignmentForUpdate(SeqAlignPtr sap,UpdateAlignmentLengthsPtr ualp,ESequenceUpdateType choice)10629 static Boolean ShiftAlignmentForUpdate
10630 (SeqAlignPtr sap,
10631  UpdateAlignmentLengthsPtr ualp,
10632  ESequenceUpdateType choice)
10633 
10634 {
10635   DenseSegPtr  dsp;
10636   Int2         j;
10637 
10638   if (ualp == NULL || sap == NULL) return FALSE;
10639 
10640   AMFreeAllIndexes (sap);
10641 
10642   if (sap->segtype == SAS_DENSEG) {
10643     dsp = (DenseSegPtr) sap->segs;
10644 
10645     switch (choice) {
10646       case eSequenceUpdateExtend5 :
10647         /* adjust alignment 5' */
10648         if (dsp != NULL && dsp->lens != NULL && dsp->numseg > 0) {
10649           dsp->lens [dsp->numseg - 1] += ualp->old3;
10650         }
10651         break;
10652       case eSequenceUpdateExtend3 :
10653         /* adjust alignment 3' */
10654         if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
10655           dsp->lens [0] += ualp->old5;
10656           dsp->starts [0] = 0;
10657           dsp->starts [1] = 0;
10658           for (j = 1; j < dsp->numseg; j++) {
10659             if (dsp->starts [1 + j * 2] != -1) {
10660               dsp->starts [1 + j * 2] += ualp->old5 - ualp->new5;
10661             }
10662           }
10663         }
10664         break;
10665       case eSequenceUpdatePatch :
10666         /* adjust alignment patch */
10667         if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
10668           dsp->lens [dsp->numseg - 1] += ualp->old3;
10669           dsp->lens [0] += ualp->old5;
10670           dsp->starts [0] = 0;
10671           dsp->starts [1] = 0;
10672           for (j = 1; j < dsp->numseg; j++) {
10673             if (dsp->starts [1 + j * 2] != -1) {
10674               dsp->starts [1 + j * 2] += ualp->old5 - ualp->new5;
10675             }
10676           }
10677         }
10678         break;
10679       default :
10680         break;
10681     }
10682   }
10683 
10684   AlnMgr2IndexSingleChildSeqAlign (sap);
10685 
10686   return TRUE;
10687 }
10688 
10689 /* This function shifts the position of features on the updated sequence based on
10690  * the number of nucleotides added upstream.
10691  */
10692 static Boolean
ShiftFeaturesForUpdate(BioseqPtr orig_bsp,BioseqPtr update_bsp,Int4 offset)10693 ShiftFeaturesForUpdate
10694 (BioseqPtr orig_bsp,
10695  BioseqPtr update_bsp,
10696  Int4 offset)
10697 
10698 {
10699   CodeBreakPtr       cbp;
10700   SeqMgrFeatContext  context;
10701   CdRegionPtr        crp;
10702   Int4               len;
10703   RnaRefPtr          rrp;
10704   Uint1              seq_data_type;
10705   SeqFeatPtr         sfp;
10706   SeqIdPtr           sip;
10707   tRNAPtr            trp;
10708   SeqDataPtr         sdp;
10709 
10710   if (orig_bsp == NULL || update_bsp == NULL)
10711   {
10712     return FALSE;
10713   }
10714 
10715   sip = SeqIdFindBest (orig_bsp->id, 0);
10716   if (sip == NULL) return FALSE;
10717 
10718   if (offset > 0) {
10719     sfp = SeqMgrGetNextFeature (orig_bsp, NULL, 0, 0, &context);
10720     while (sfp != NULL) {
10721       OffsetLocation (sfp->location, offset, sip);
10722       switch (sfp->data.choice) {
10723         case SEQFEAT_CDREGION :
10724           crp = (CdRegionPtr) sfp->data.value.ptrvalue;
10725           if (crp != NULL) {
10726             for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
10727               OffsetLocation (cbp->loc, offset, sip);
10728             }
10729           }
10730           break;
10731         case SEQFEAT_RNA :
10732           rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
10733           if (rrp != NULL && rrp->ext.choice == 2) {
10734             trp = (tRNAPtr) rrp->ext.value.ptrvalue;
10735             if (trp != NULL && trp->anticodon != NULL) {
10736               OffsetLocation (trp->anticodon, offset, sip);
10737             }
10738           }
10739           break;
10740         default :
10741           break;
10742       }
10743       sfp = SeqMgrGetNextFeature (orig_bsp, sfp, 0, 0, &context);
10744     }
10745   }
10746 
10747   /* switch bioseqs to finish extension */
10748 
10749   sdp = orig_bsp->seq_data;
10750   orig_bsp->seq_data = update_bsp->seq_data;
10751   update_bsp->seq_data = sdp;
10752   len = orig_bsp->length;
10753   orig_bsp->length = update_bsp->length;
10754   update_bsp->length = len;
10755   seq_data_type = orig_bsp->seq_data_type;
10756   orig_bsp->seq_data_type = update_bsp->seq_data_type;
10757   update_bsp->seq_data_type = seq_data_type;
10758 
10759   return TRUE;
10760 }
10761 
ReadLongDataToString(SeqPortPtr spp,Int4 how_much,CharPtr str)10762 static Int4 ReadLongDataToString (SeqPortPtr spp, Int4 how_much, CharPtr str)
10763 {
10764   Int4          ctr = 0, left_to_read, read_this;
10765 
10766   if (spp == NULL || str == NULL)
10767   {
10768     return 0;
10769   }
10770   left_to_read = how_much;
10771   while (left_to_read > 0)
10772   {
10773     read_this = SeqPortRead (spp, (Uint1Ptr)(str + ctr), MIN (left_to_read, INT2_MAX));
10774     left_to_read -= read_this;
10775     ctr += read_this;
10776   }
10777   return ctr;
10778 }
10779 
SeqLitFromBioseq(BioseqPtr bsp,Int4 start,Int4 stop)10780 static SeqLitPtr SeqLitFromBioseq (BioseqPtr bsp, Int4 start, Int4 stop)
10781 {
10782   CharPtr    str;
10783   SeqLitPtr  slip;
10784   Uint1      seqcode;
10785   SeqPortPtr spp;
10786   Int4       ctr;
10787 
10788   if (bsp == NULL || bsp->length < 1 || start < 0 || stop >= bsp->length)
10789   {
10790     return NULL;
10791   }
10792 
10793   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (stop - start + 5));
10794   if (str == NULL)
10795     return NULL;
10796 
10797   if (ISA_na (bsp->mol))
10798   {
10799     seqcode = Seq_code_iupacna;
10800   }
10801   else
10802   {
10803     seqcode = Seq_code_iupacaa;
10804   }
10805 
10806   slip = SeqLitNew ();
10807 
10808   slip->seq_data_type = seqcode;
10809   slip->length = stop - start + 1;
10810   slip->seq_data = (SeqDataPtr) BSNew (slip->length);
10811 
10812   /* copy in the data */
10813   spp = SeqPortNew(bsp, start, stop, Seq_strand_plus, seqcode);
10814   ctr = ReadLongDataToString (spp, stop - start + 1, str);
10815   spp = SeqPortFree (spp);
10816   str[ctr] = '\0';
10817 
10818   BSWrite ((ByteStorePtr) slip->seq_data, (VoidPtr) str, stop - start + 1);
10819   return slip;
10820 }
10821 
DeltaSeqListFree(DeltaSeqPtr list)10822 static DeltaSeqPtr DeltaSeqListFree (DeltaSeqPtr list)
10823 {
10824   DeltaSeqPtr dsp;
10825   SeqLitPtr   slip;
10826 
10827   dsp = list;
10828   while (dsp != NULL)
10829   {
10830     slip = (SeqLitPtr) (dsp->data.ptrvalue);
10831     SeqLitFree (slip);
10832     dsp = dsp->next;
10833   }
10834   ValNodeFree (list);
10835   return NULL;
10836 }
10837 
10838 static Boolean
UpdateSequenceExtendDelta5Prime(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)10839 UpdateSequenceExtendDelta5Prime
10840 (UpdatePairPtr             upp,
10841  UpdateAlignmentLengthsPtr ualp)
10842 
10843 {
10844   Int4        currold_pos;
10845   SeqLitPtr   slip, slip_new;
10846   DeltaSeqPtr dspold, dspnew, dspold_prev;
10847   Int4        seqstart;
10848   DeltaSeqPtr new_list = NULL;
10849 
10850   if (upp == NULL
10851       || upp->orig_bsp == NULL
10852       || upp->update_bsp == NULL
10853       || (upp->orig_bsp->repr != Seq_repr_delta && upp->update_bsp->repr != Seq_repr_delta)
10854       || (upp->orig_bsp->repr == Seq_repr_delta && upp->orig_bsp->seq_ext_type != 4)
10855       || (upp->update_bsp->repr == Seq_repr_delta && upp->update_bsp->seq_ext_type != 4))
10856   {
10857     return FALSE;
10858   }
10859 
10860   /* copy in entire new sequence */
10861   if (upp->update_bsp->repr == Seq_repr_delta)
10862   {
10863     dspnew = (DeltaSeqPtr) upp->update_bsp->seq_ext;
10864     while (dspnew != NULL)
10865     {
10866       if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
10867       {
10868         return FALSE;
10869       }
10870 	    slip = (SeqLitPtr) (dspnew->data.ptrvalue);
10871 		  slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
10872 		                                       (AsnWriteFunc) SeqLitAsnWrite);
10873 
10874       ValNodeAddPointer (&new_list, 2, slip_new);
10875 	    dspnew = dspnew->next;
10876     }
10877   }
10878   else
10879   {
10880     slip = SeqLitFromBioseq (upp->update_bsp, 0, upp->update_bsp->length - 1);
10881     if (slip == NULL)
10882     {
10883       return FALSE;
10884     }
10885     ValNodeAddPointer (&new_list, 2, slip);
10886   }
10887 
10888   /* now copy in old sequence, all if no alignment, after alignment if present */
10889   if (upp->orig_bsp->repr == Seq_repr_delta)
10890   {
10891     if (upp->salp == NULL)
10892     {
10893       ValNodeLink (&new_list, upp->orig_bsp->seq_ext);
10894       upp->orig_bsp->seq_ext = new_list;
10895       upp->orig_bsp->length += upp->update_bsp->length;
10896     }
10897     else
10898     {
10899       /* skip over old 5 and aligned area */
10900       dspold = (DeltaSeqPtr) upp->orig_bsp->seq_ext;
10901       currold_pos = 0;
10902       dspold_prev = NULL;
10903       while (dspold != NULL && currold_pos < ualp->old5 + ualp->olda)
10904       {
10905         seqstart = currold_pos;
10906         if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
10907         {
10908           return FALSE;
10909         }
10910         slip = (SeqLitPtr) (dspold->data.ptrvalue);
10911 	      currold_pos += slip->length;
10912 		    if (currold_pos > ualp->old5 + ualp->olda)
10913   		  {
10914           SplitDeltaSeq (dspold, ualp->old5 + ualp->olda - seqstart);
10915           slip = (SeqLitPtr) (dspold->data.ptrvalue);
10916           currold_pos = ualp->old5 + ualp->olda;
10917         }
10918   		  dspold_prev = dspold;
10919     	  dspold = dspold->next;
10920       }
10921       if (dspold_prev == NULL)
10922       {
10923         ValNodeLink (&new_list, upp->orig_bsp->seq_ext);
10924       }
10925       else
10926       {
10927         /* attach remainder of list to new list */
10928         ValNodeLink (&new_list, dspold);
10929         dspold_prev->next = NULL;
10930 
10931         /* free dsps in old sequence that are being replaced */
10932         upp->orig_bsp->seq_ext = DeltaSeqListFree (upp->orig_bsp->seq_ext);
10933 
10934         /* put new list in place */
10935         upp->orig_bsp->seq_ext = new_list;
10936       }
10937       upp->orig_bsp->length = ualp->new5 + ualp->newa + ualp->old3;
10938     }
10939   }
10940   else
10941   {
10942     if (upp->salp == NULL)
10943     {
10944       slip = SeqLitFromBioseq (upp->orig_bsp, 0, upp->orig_bsp->length - 1);
10945     }
10946     else
10947     {
10948       slip = SeqLitFromBioseq (upp->orig_bsp, ualp->old5 + ualp->olda, upp->orig_bsp->length - 1);
10949     }
10950     if (slip == NULL)
10951     {
10952       return FALSE;
10953     }
10954     ValNodeAddPointer (&new_list, 2, slip);
10955     upp->orig_bsp->seq_data = SeqDataFree (upp->orig_bsp->seq_data, upp->orig_bsp->seq_data_type);
10956     upp->orig_bsp->seq_ext = new_list;
10957     upp->orig_bsp->repr = Seq_repr_delta;
10958 
10959     upp->orig_bsp->length = ualp->new5 + ualp->newa + ualp->old3;
10960   }
10961 
10962   return TRUE;
10963 }
10964 
10965 static Boolean
UpdateSequenceExtend5Prime(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)10966 UpdateSequenceExtend5Prime
10967 (UpdatePairPtr             upp,
10968  UpdateAlignmentLengthsPtr ualp)
10969 
10970 {
10971   ByteStorePtr  bs;
10972   Int4          newlen;
10973   CharPtr       str;
10974   SeqPortPtr    spp;
10975   Uint1         seqcode;
10976   Int4          ctr;
10977   Boolean       rval;
10978   Int4          shift_len = 0;
10979 
10980   if (upp == NULL || upp->orig_bsp == NULL || upp->update_bsp == NULL || ualp == NULL)
10981   {
10982     return FALSE;
10983   }
10984 
10985   if (upp->orig_bsp->repr == Seq_repr_delta
10986       || upp->update_bsp->repr == Seq_repr_delta)
10987   {
10988     return UpdateSequenceExtendDelta5Prime (upp, ualp);
10989   }
10990 
10991   if (upp->salp == NULL)
10992   {
10993     /* add to 5' end */
10994     newlen = upp->update_bsp->length + upp->orig_bsp->length;
10995     shift_len = upp->update_bsp->length;
10996   }
10997   else
10998   {
10999     /* construct replacement sequence by recombining between old and overlap */
11000     newlen = ualp->new5 + ualp->newa + ualp->old3;
11001     shift_len = ualp->new5;
11002   }
11003 
11004   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
11005   if (str == NULL)
11006     return FALSE;
11007 
11008   if (ISA_na (upp->orig_bsp->mol))
11009   {
11010     seqcode = Seq_code_iupacna;
11011   }
11012   else
11013   {
11014     seqcode = Seq_code_iupacaa;
11015   }
11016 
11017   if (upp->salp == NULL)
11018   {
11019     /* add new sequence */
11020     spp = SeqPortNew(upp->update_bsp, 0, upp->update_bsp->length - 1, Seq_strand_plus, seqcode);
11021     ctr = ReadLongDataToString (spp, upp->update_bsp->length, str);
11022     spp = SeqPortFree (spp);
11023     /* add old sequence */
11024     spp = SeqPortNew(upp->orig_bsp, 0,upp-> orig_bsp->length - 1, Seq_strand_plus, seqcode);
11025     ctr += ReadLongDataToString(spp, upp->orig_bsp->length, str + ctr);
11026     spp = SeqPortFree (spp);
11027   }
11028   else
11029   {
11030     /* take new 5' and aligned middle */
11031     spp = SeqPortNew(upp->update_bsp, 0, ualp->new5 + ualp->newa - 1, Seq_strand_plus, seqcode);
11032     ctr = ReadLongDataToString (spp, ualp->new5 + ualp->newa, str);
11033     spp = SeqPortFree (spp);
11034     /* take old 3' end */
11035     if (ualp->old3 > 0)
11036     {
11037       spp = SeqPortNew(upp->orig_bsp, ualp->old5 + ualp->olda, upp->orig_bsp->length - 1, Seq_strand_plus, seqcode);
11038       ctr += ReadLongDataToString (spp, ualp->old3, str + ctr);
11039       spp = SeqPortFree (spp);
11040     }
11041   }
11042 
11043   str[ctr] = '\0';
11044 
11045   bs = BSNew (newlen);
11046   BSWrite (bs, (VoidPtr) str, newlen);
11047 
11048   if (bs != NULL && BSLen (bs) < 1) {
11049     bs = BSFree (bs);
11050   }
11051   if (bs == NULL) return FALSE;
11052 
11053   /* overlap turned into replacement sequence */
11054 
11055   upp->update_bsp->seq_data = SeqDataFree (upp->update_bsp->seq_data, upp->update_bsp->seq_data_type);
11056   upp->update_bsp->seq_data = (SeqDataPtr) bs;
11057   upp->update_bsp->seq_data_type = seqcode;
11058   upp->update_bsp->length = newlen;
11059 
11060 
11061   if (upp->salp == NULL)
11062   {
11063     /* then finish by replacing with new sequence */
11064     rval = ShiftFeaturesForUpdate (upp->orig_bsp, upp->update_bsp, shift_len);
11065   }
11066   else
11067   {
11068     /* adjust alignment and reindex */
11069     rval = ShiftAlignmentForUpdate (upp->salp, ualp, eSequenceUpdateExtend5);
11070     if (rval)
11071     {
11072       /* then finish by replacing with new sequence */
11073       ReplaceOneSequence (upp->salp, upp->orig_bsp, upp->update_bsp);
11074     }
11075   }
11076 
11077   return rval;
11078 }
11079 
11080 static Boolean
UpdateSequenceExtendDelta3Prime(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)11081 UpdateSequenceExtendDelta3Prime
11082 (UpdatePairPtr             upp,
11083  UpdateAlignmentLengthsPtr ualp)
11084 
11085 {
11086   Int4        currnew_pos = 0, currold_pos;
11087   SeqLitPtr   slip, slip_new;
11088   DeltaSeqPtr dspold, dspnew, dspold_prev;
11089   Int4        seqstart;
11090   DeltaSeqPtr new_list = NULL;
11091 
11092   if (upp == NULL
11093       || upp->orig_bsp == NULL
11094       || upp->update_bsp == NULL
11095       || (upp->orig_bsp->repr != Seq_repr_delta && upp->update_bsp->repr != Seq_repr_delta)
11096       || (upp->orig_bsp->repr == Seq_repr_delta && upp->orig_bsp->seq_ext_type != 4)
11097       || (upp->update_bsp->repr == Seq_repr_delta && upp->update_bsp->seq_ext_type != 4))
11098   {
11099     return FALSE;
11100   }
11101 
11102   /* retain 5' end of original sequence */
11103   if (upp->orig_bsp->repr == Seq_repr_delta)
11104   {
11105     if (upp->salp == NULL)
11106     {
11107       /* do nothing, keep the entire sequence */
11108     }
11109     else
11110     {
11111       /* discard the portion after the old 5' */
11112       dspold_prev = NULL;
11113       dspold = (DeltaSeqPtr) upp->orig_bsp->seq_ext;
11114       currold_pos = 0;
11115       while (dspold != NULL && currold_pos < ualp->old5)
11116       {
11117         seqstart = currold_pos;
11118         if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
11119         {
11120           return FALSE;
11121         }
11122         slip = (SeqLitPtr) (dspold->data.ptrvalue);
11123 	      currold_pos += slip->length;
11124 		    if (currold_pos > ualp->old5)
11125   		  {
11126           SplitDeltaSeq (dspold, ualp->old5 - seqstart);
11127           slip = (SeqLitPtr) (dspold->data.ptrvalue);
11128           currold_pos = ualp->old5;
11129         }
11130   		  dspold_prev = dspold;
11131     	  dspold = dspold->next;
11132       }
11133 
11134       if (dspold_prev == NULL)
11135       {
11136         /* discard the entire sequence */
11137         upp->orig_bsp->seq_ext = DeltaSeqListFree (upp->orig_bsp->seq_ext);
11138       }
11139       else
11140       {
11141         dspold_prev->next = DeltaSeqListFree (dspold_prev->next);
11142       }
11143     }
11144   }
11145   else
11146   {
11147     if (upp->salp == NULL)
11148     {
11149       slip = SeqLitFromBioseq (upp->orig_bsp, 0, upp->orig_bsp->length - 1);
11150     }
11151     else
11152     {
11153       slip = SeqLitFromBioseq (upp->orig_bsp, 0, ualp->old5);
11154     }
11155     upp->orig_bsp->seq_data = SeqDataFree (upp->orig_bsp->seq_data, upp->orig_bsp->seq_data_type);
11156     new_list = upp->orig_bsp->seq_ext;
11157     ValNodeAddPointer (&new_list, 2, slip);
11158     upp->orig_bsp->seq_ext = new_list;
11159     upp->orig_bsp->repr = Seq_repr_delta;
11160   }
11161 
11162 
11163   /* now add in new sequence */
11164   if (upp->update_bsp->repr == Seq_repr_delta)
11165   {
11166     /* skip over new5 */
11167     dspnew = (DeltaSeqPtr) upp->update_bsp->seq_ext;
11168     currnew_pos = 0;
11169     if (upp->salp != NULL)
11170     {
11171       while (dspnew != NULL && currnew_pos < ualp->new5)
11172       {
11173         seqstart = currnew_pos;
11174         if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
11175         {
11176           return FALSE;
11177         }
11178         slip = (SeqLitPtr) (dspnew->data.ptrvalue);
11179 	      currnew_pos += slip->length;
11180 		    if (currnew_pos > ualp->new5)
11181   		  {
11182           SplitDeltaSeq (dspnew, ualp->old5 - seqstart);
11183           slip = (SeqLitPtr) (dspnew->data.ptrvalue);
11184           currnew_pos = ualp->new5;
11185         }
11186     	  dspnew = dspnew->next;
11187       }
11188     }
11189 
11190     while (dspnew != NULL)
11191     {
11192       if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
11193       {
11194         return FALSE;
11195       }
11196       slip = (SeqLitPtr) (dspnew->data.ptrvalue);
11197 		  slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
11198 		                                       (AsnWriteFunc) SeqLitAsnWrite);
11199       new_list = upp->orig_bsp->seq_ext;
11200       ValNodeAddPointer (&new_list, 2, slip_new);
11201       upp->orig_bsp->seq_ext = new_list;
11202       dspnew = dspnew->next;
11203     }
11204   }
11205   else
11206   {
11207     if (upp->salp == NULL)
11208     {
11209       slip = SeqLitFromBioseq (upp->update_bsp, 0, upp->update_bsp->length - 1);
11210     }
11211     else
11212     {
11213       slip = SeqLitFromBioseq (upp->orig_bsp, ualp->new5, upp->update_bsp->length - 1);
11214     }
11215     new_list = upp->orig_bsp->seq_ext;
11216     ValNodeAddPointer (&new_list, 2, slip);
11217     upp->orig_bsp->seq_ext = new_list;
11218   }
11219 
11220   if (upp->salp == NULL)
11221   {
11222     upp->orig_bsp->length = upp->orig_bsp->length + upp->update_bsp->length;
11223   }
11224   else
11225   {
11226     upp->orig_bsp->length = ualp->old5 + ualp->newa + ualp->new3;
11227   }
11228 
11229   return TRUE;
11230 }
11231 
11232 static Boolean
UpdateSequenceExtend3Prime(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)11233 UpdateSequenceExtend3Prime
11234 (UpdatePairPtr             upp,
11235  UpdateAlignmentLengthsPtr ualp)
11236 {
11237   ByteStorePtr  bs;
11238   Int4          newlen;
11239   CharPtr       str;
11240   SeqPortPtr    spp;
11241   Uint1         seqcode;
11242   Int4          ctr;
11243   Boolean       rval;
11244 
11245   if (upp == NULL || upp->orig_bsp == NULL || upp->update_bsp == NULL || ualp == NULL)
11246   {
11247     return FALSE;
11248   }
11249 
11250   if (upp->orig_bsp->repr == Seq_repr_delta
11251       || upp->update_bsp->repr == Seq_repr_delta)
11252   {
11253     return UpdateSequenceExtendDelta3Prime (upp, ualp);
11254   }
11255 
11256   /* construct replacement sequence by recombining between old and overlap */
11257   if (upp->salp == NULL)
11258   {
11259     newlen = upp->orig_bsp->length + upp->update_bsp->length;
11260   }
11261   else
11262   {
11263     newlen = ualp->old5 + ualp->newa + ualp->new3;
11264   }
11265 
11266   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
11267   if (str == NULL)
11268     return FALSE;
11269 
11270   if (ISA_na (upp->orig_bsp->mol))
11271   {
11272     seqcode = Seq_code_iupacna;
11273   }
11274   else
11275   {
11276     seqcode = Seq_code_iupacaa;
11277   }
11278 
11279   if (upp->salp == NULL)
11280   {
11281     /* add old sequence */
11282     spp = SeqPortNew(upp->orig_bsp, 0, upp->orig_bsp->length - 1, Seq_strand_plus, seqcode);
11283     ctr = ReadLongDataToString (spp, upp->orig_bsp->length, str);
11284     spp = SeqPortFree (spp);
11285     /* add new sequence */
11286     spp = SeqPortNew(upp->update_bsp, 0, upp->update_bsp->length - 1, Seq_strand_plus, seqcode);
11287     ctr += ReadLongDataToString (spp, upp->update_bsp->length, str + ctr);
11288     spp = SeqPortFree (spp);
11289   }
11290   else
11291   {
11292     /* take old 5'  */
11293     spp = SeqPortNew(upp->orig_bsp, 0, ualp->old5 - 1, Seq_strand_plus, seqcode);
11294     ctr = ReadLongDataToString(spp, ualp->old5, str);
11295     spp = SeqPortFree (spp);
11296     /* take aligned middle and new 3' end */
11297     spp = SeqPortNew(upp->update_bsp, ualp->new5, upp->update_bsp->length - 1, Seq_strand_plus, seqcode);
11298     ctr += ReadLongDataToString (spp, ualp->newa + ualp->new3, str + ctr);
11299     spp = SeqPortFree (spp);
11300   }
11301 
11302   str[ctr] = '\0';
11303 
11304   bs = BSNew (newlen);
11305   BSWrite (bs, (VoidPtr) str, newlen);
11306 
11307   if (bs != NULL && BSLen (bs) < 1) {
11308     bs = BSFree (bs);
11309   }
11310   if (bs == NULL) return FALSE;
11311 
11312   /* overlap turned into replacement sequence */
11313 
11314   upp->update_bsp->seq_data = SeqDataFree (upp->update_bsp->seq_data, upp->update_bsp->seq_data_type);
11315   upp->update_bsp->seq_data = (SeqDataPtr) bs;
11316   upp->update_bsp->seq_data_type = Seq_code_iupacna;
11317   upp->update_bsp->length = newlen;
11318 
11319   if (upp->salp == NULL)
11320   {
11321     /* then finish by replacing with new sequence */
11322     rval = ShiftFeaturesForUpdate (upp->orig_bsp, upp->update_bsp, 0);
11323   }
11324   else
11325   {
11326     /* adjust alignment and reindex */
11327     rval = ShiftAlignmentForUpdate (upp->salp, ualp, eSequenceUpdateExtend3);
11328     if (rval)
11329     {
11330       /* then finish by replacing with new sequence */
11331       ReplaceOneSequence (upp->salp, upp->orig_bsp, upp->update_bsp);
11332     }
11333   }
11334 
11335   return rval;
11336 }
11337 
RawSequencePatchOk(BioseqPtr orig_bsp,BioseqPtr update_bsp)11338 static Boolean RawSequencePatchOk (BioseqPtr orig_bsp, BioseqPtr update_bsp)
11339 {
11340   Boolean rval = TRUE;
11341 
11342   if (orig_bsp == NULL || update_bsp == NULL
11343       || orig_bsp->repr != Seq_repr_raw
11344       || update_bsp->repr != Seq_repr_raw)
11345   {
11346     rval = FALSE;
11347   }
11348 
11349   return rval;
11350 }
11351 
11352 /* this replaces just the middle */
11353 static Boolean
UpdateSequencePatchRaw(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)11354 UpdateSequencePatchRaw
11355 (UpdatePairPtr             upp,
11356  UpdateAlignmentLengthsPtr ualp)
11357 
11358 {
11359   ByteStorePtr  bs;
11360   Int4          newlen;
11361   CharPtr       str;
11362   Uint1         seqcode;
11363   Int4          ctr = 0;
11364   StreamFlgType flags = STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL;
11365 
11366   if (upp == NULL || upp->orig_bsp == NULL || upp->update_bsp == NULL
11367       || upp->salp == NULL || ualp == NULL)
11368   {
11369     return FALSE;
11370   }
11371 
11372   newlen = ualp->old5 + ualp->newa + ualp->old3;
11373   str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
11374   if (str == NULL) return FALSE;
11375 
11376   if (ISA_na (upp->orig_bsp->mol))
11377   {
11378     seqcode = Seq_code_iupacna;
11379   }
11380   else
11381   {
11382     seqcode = Seq_code_iupacaa;
11383   }
11384 
11385   /* construct replacement sequence by double recombination */
11386 
11387   /* take old 5'  */
11388   if (ualp->old5 > 0) {
11389     ctr = SeqPortStreamInt (upp->orig_bsp, 0, ualp->old5 - 1, Seq_strand_plus,
11390                             flags, (Pointer) str, NULL);
11391   }
11392 
11393   /* take aligned middle */
11394   if (ualp->new5 + ualp->newa > 0) {
11395     ctr += SeqPortStreamInt (upp->update_bsp, ualp->new5, ualp->new5 + ualp->newa - 1, Seq_strand_plus,
11396                              flags, (Pointer) (str + ctr), NULL);
11397   }
11398 
11399   /* take old 3' (if any) */
11400   if (ualp->old5 + ualp->olda < upp->orig_bsp->length) {
11401     ctr += SeqPortStreamInt (upp->orig_bsp, ualp->old5 + ualp->olda, upp->orig_bsp->length - 1, Seq_strand_plus,
11402                       flags, (Pointer) (str + ctr), NULL);
11403   }
11404 
11405   str[ctr] = '\0';
11406 
11407   bs = BSNew (newlen);
11408   BSWrite (bs, (VoidPtr) str, newlen);
11409 
11410   if (bs != NULL && BSLen (bs) < 1) {
11411     bs = BSFree (bs);
11412   }
11413   if (bs == NULL) return FALSE;
11414 
11415   /* overlap turned into replacement sequence */
11416 
11417   upp->update_bsp->seq_data = SeqDataFree (upp->update_bsp->seq_data, upp->update_bsp->seq_data_type);
11418   upp->update_bsp->seq_data = (SeqDataPtr) bs;
11419   upp->update_bsp->seq_data_type = seqcode;
11420   upp->update_bsp->length = newlen;
11421   return TRUE;
11422 }
11423 
DeltaSequencePatchOk(BioseqPtr orig_bsp,BioseqPtr update_bsp)11424 static Boolean DeltaSequencePatchOk (BioseqPtr orig_bsp, BioseqPtr update_bsp)
11425 {
11426   Boolean rval = TRUE;
11427 
11428   if (orig_bsp == NULL || update_bsp == NULL
11429       || orig_bsp->repr != Seq_repr_delta || update_bsp->repr != Seq_repr_delta
11430       || orig_bsp->seq_ext_type != 4 || update_bsp->seq_ext_type != 4)
11431   {
11432     rval = FALSE;
11433   }
11434 
11435   return rval;
11436 }
11437 
11438 /* This function will patch a delta sequence with another delta sequence.
11439  * The pieces in the overlap from the old sequence will be replaced by pieces
11440  * in the overlap from the new sequence.
11441  */
UpdateSequencePatchDelta(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)11442 static Boolean UpdateSequencePatchDelta
11443 (UpdatePairPtr             upp,
11444  UpdateAlignmentLengthsPtr ualp)
11445 
11446 {
11447   Int4        currnew_pos = 0, currold_pos;
11448   SeqLitPtr   slip, slip_new;
11449   DeltaSeqPtr dspold, dspnew;
11450   Int4        seqstart;
11451   DeltaSeqPtr new_list = NULL;
11452 
11453   if (upp == NULL)
11454   {
11455     return FALSE;
11456   }
11457   if (! DeltaSequencePatchOk (upp->orig_bsp, upp->update_bsp)
11458       || upp->salp == NULL || ualp == NULL)
11459   {
11460     return FALSE;
11461   }
11462 
11463   /* keep old 5' end intact */
11464   currold_pos = 0;
11465   seqstart = 0;
11466   dspold = (DeltaSeqPtr) upp->orig_bsp->seq_ext;
11467   while (dspold != NULL && currold_pos < ualp->old5)
11468   {
11469     seqstart = currold_pos;
11470     if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
11471     {
11472       return FALSE;
11473     }
11474     slip = (SeqLitPtr) (dspold->data.ptrvalue);
11475 	  currold_pos += slip->length;
11476 		if (currold_pos > ualp->old5)
11477 		{
11478       SplitDeltaSeq (dspold, ualp->old5 - seqstart);
11479       slip = (SeqLitPtr) (dspold->data.ptrvalue);
11480       currold_pos = ualp->old5;
11481 		}
11482 		slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
11483 		                                     (AsnWriteFunc) SeqLitAsnWrite);
11484 		ValNodeAddPointer (&new_list, 2, slip_new);
11485 	  dspold = dspold->next;
11486   }
11487 
11488   /* skip over new 5' end */
11489   currnew_pos = 0;
11490   seqstart = 0;
11491   dspnew = (DeltaSeqPtr) upp->update_bsp->seq_ext;
11492   while (dspnew != NULL && currnew_pos < ualp->new5)
11493   {
11494     seqstart = currold_pos;
11495     if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
11496     {
11497       return FALSE;
11498     }
11499 	  slip = (SeqLitPtr) (dspnew->data.ptrvalue);
11500 	  currnew_pos += slip->length;
11501 	  if (currnew_pos > ualp->new5)
11502 	  {
11503       SplitDeltaSeq (dspnew, ualp->new5 - seqstart);
11504       currnew_pos = ualp->new5;
11505 	  }
11506 	  dspnew = dspnew->next;
11507   }
11508 
11509   /* copy in new overlap */
11510   while (dspnew != NULL && currnew_pos < ualp->new5 + ualp->newa)
11511   {
11512     seqstart = currold_pos;
11513     if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
11514     {
11515       return FALSE;
11516     }
11517 	  slip = (SeqLitPtr) (dspnew->data.ptrvalue);
11518 	  currnew_pos += slip->length;
11519 		if (currnew_pos > ualp->new5 + ualp->newa)
11520 		{
11521       SplitDeltaSeq (dspnew, ualp->new5 + ualp->newa - seqstart);
11522       slip = (SeqLitPtr) (dspnew->data.ptrvalue);
11523       currnew_pos = ualp->new5 + ualp->newa;
11524 		}
11525 		slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
11526 		                                     (AsnWriteFunc) SeqLitAsnWrite);
11527 		ValNodeAddPointer (&new_list, 2, slip_new);
11528 		dspnew = dspnew->next;
11529   }
11530 
11531   /* skip over old overlap */
11532 
11533   while (dspold != NULL && currold_pos < ualp->old5 + ualp->olda)
11534   {
11535     seqstart = currold_pos;
11536     if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
11537     {
11538       return FALSE;
11539     }
11540     slip = (SeqLitPtr) (dspold->data.ptrvalue);
11541     currold_pos += slip->length;
11542     if (currold_pos > ualp->old5 + ualp->olda)
11543     {
11544       SplitDeltaSeq (dspold, ualp->new5 + ualp->newa - seqstart);
11545       currold_pos = ualp->old5 + ualp->olda;
11546     }
11547     dspold = dspold->next;
11548   }
11549 
11550   /* copy in old 3' */
11551 
11552   while (dspold != NULL)
11553   {
11554     if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
11555     {
11556       return FALSE;
11557     }
11558     slip = (SeqLitPtr) (dspold->data.ptrvalue);
11559 		slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
11560 		                                     (AsnWriteFunc) SeqLitAsnWrite);
11561 		ValNodeAddPointer (&new_list, 2, slip_new);
11562 		dspold = dspold->next;
11563   }
11564 
11565   /* free newbsp's old SeqLit List */
11566   for (dspnew = (DeltaSeqPtr) upp->update_bsp->seq_ext;
11567        dspnew != NULL;
11568        dspnew = dspnew->next)
11569   {
11570     slip = (SeqLitPtr) (dspnew->data.ptrvalue);
11571     SeqLitFree (slip);
11572   }
11573   upp->update_bsp->seq_ext = ValNodeFree (upp->update_bsp->seq_ext);
11574   upp->update_bsp->seq_ext = new_list;
11575   upp->update_bsp->length = ualp->old5 + ualp->newa + ualp->old3;
11576   return TRUE;
11577 }
11578 
UpdateSequencePatch(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)11579 static Boolean UpdateSequencePatch
11580 (UpdatePairPtr             upp,
11581  UpdateAlignmentLengthsPtr ualp)
11582 
11583 {
11584   Boolean rval = FALSE;
11585   if (upp == NULL || upp->orig_bsp == NULL || upp->update_bsp == NULL
11586       || upp->salp == NULL)
11587   {
11588     return FALSE;
11589   }
11590 
11591   if (RawSequencePatchOk (upp->orig_bsp, upp->update_bsp))
11592   {
11593     rval = UpdateSequencePatchRaw (upp, ualp);
11594   }
11595   else if (DeltaSequencePatchOk (upp->orig_bsp, upp->update_bsp))
11596   {
11597     rval = UpdateSequencePatchDelta (upp, ualp);
11598   }
11599 
11600   if (!rval)
11601   {
11602     return rval;
11603   }
11604 
11605   /* adjust alignment and reindex */
11606   rval = ShiftAlignmentForUpdate (upp->salp, ualp, eSequenceUpdatePatch);
11607   if (rval)
11608   {
11609     /* then finish by replacing with new sequence */
11610     ReplaceOneSequence (upp->salp, upp->orig_bsp, upp->update_bsp);
11611   }
11612 
11613   return rval;
11614 }
11615 
DoSequencesHaveDifferentOrganisms(BioseqPtr bsp1,BioseqPtr bsp2)11616 static Boolean DoSequencesHaveDifferentOrganisms (BioseqPtr bsp1, BioseqPtr bsp2)
11617 {
11618   OrgRefPtr         orp1 = NULL, orp2 = NULL;
11619   SeqDescrPtr       sdp;
11620   SeqMgrDescContext dcontext;
11621   BioSourcePtr      biop1, biop2;
11622   Boolean           rval = FALSE;
11623 
11624   sdp = SeqMgrGetNextDescriptor (bsp1, NULL, Seq_descr_source, &dcontext);
11625   if (sdp != NULL) {
11626     biop1 = (BioSourcePtr) sdp->data.ptrvalue;
11627     if (biop1 != NULL) {
11628       orp1 = biop1->org;
11629     }
11630   }
11631   sdp = SeqMgrGetNextDescriptor (bsp2, NULL, Seq_descr_source, &dcontext);
11632   if (sdp != NULL) {
11633     biop2 = (BioSourcePtr) sdp->data.ptrvalue;
11634     if (biop2 != NULL)
11635     {
11636       orp2 = biop2->org;
11637     }
11638   }
11639   if (orp1 != NULL && orp2 != NULL
11640       && StringICmp (orp1->taxname, orp2->taxname) != 0)
11641   {
11642     rval = TRUE;
11643   }
11644   return rval;
11645 }
11646 
11647 /*This function removes RefTrackDescriptors from the specified Bioseq */
RemoveRefTrackDescriptors(BioseqPtr bsp)11648 static void RemoveRefTrackDescriptors (BioseqPtr bsp)
11649 {
11650 	UserObjectPtr uop;
11651   ObjectIdPtr		oip;
11652   SeqDescrPtr   desc, prev_desc = NULL, next_desc;
11653 
11654 	for (desc=bsp->descr; desc != NULL; desc=next_desc)
11655 	{
11656 	  next_desc = desc->next;
11657 		if (desc->choice != Seq_descr_user || desc->data.ptrvalue == NULL)
11658 		{
11659 		  prev_desc = desc;
11660 		  continue;
11661 		}
11662 	  uop = desc->data.ptrvalue;
11663 	  if ((oip = uop->type) == NULL || StringCmp(oip->str, "RefGeneTracking") != 0)
11664 	  {
11665 	    prev_desc = desc;
11666 	  }
11667 	  else
11668 	  {
11669 	    if (prev_desc == NULL)
11670 	    {
11671 	      bsp->descr = desc->next;
11672 	    }
11673 	    else
11674 	    {
11675 	      prev_desc->next = desc->next;
11676 	    }
11677 	    desc->next = NULL;
11678 	    SeqDescrFree (desc);
11679 	  }
11680 	}
11681 }
11682 
RemoveCreateDateDescriptors(BioseqPtr bsp)11683 static void RemoveCreateDateDescriptors (BioseqPtr bsp)
11684 {
11685   ValNodePtr vnp;
11686 
11687   vnp = ValNodeExtract (&(bsp->descr), Seq_descr_create_date);
11688   vnp = ValNodeFree (vnp);
11689 }
11690 
11691 static void
ImportFeatureProduct(SeqFeatPtr dup,Boolean keepProteinIDs,SeqEntryPtr top,SeqIdPtr nuc_sip,Uint2 update_entityID)11692 ImportFeatureProduct
11693 (SeqFeatPtr  dup,
11694  Boolean     keepProteinIDs,
11695  SeqEntryPtr top,
11696  SeqIdPtr    nuc_sip,
11697  Uint2       update_entityID)
11698 {
11699   BioseqPtr   bsp, newbsp;
11700   SeqEntryPtr prdsep, newsep;
11701   SeqEntryPtr newscope, oldscope;
11702 
11703   if (dup == NULL || dup->product == NULL || nuc_sip == NULL || top == NULL)
11704   {
11705     return;
11706   }
11707 
11708   newscope = GetTopSeqEntryForEntityID (update_entityID);
11709   oldscope = SeqEntrySetScope (newscope);
11710   bsp = BioseqFindFromSeqLoc (dup->product);
11711   SeqEntrySetScope (oldscope);
11712   if (bsp != NULL) {
11713     prdsep = SeqMgrGetSeqEntryForData (bsp);
11714     if (prdsep != NULL) {
11715       newsep = AsnIoMemCopy ((Pointer) prdsep,
11716                              (AsnReadFunc) SeqEntryAsnRead,
11717                              (AsnWriteFunc) SeqEntryAsnWrite);
11718       if (newsep != NULL) {
11719         if (IS_Bioseq (newsep)) {
11720           newbsp = (BioseqPtr) newsep->data.ptrvalue;
11721           if (newbsp != NULL) {
11722             /* we do not want to import reftrack descriptors with the products */
11723             RemoveRefTrackDescriptors (newbsp);
11724             /* we do not want to import create-date descriptors with the products */
11725             RemoveCreateDateDescriptors (newbsp);
11726             if (! keepProteinIDs) {
11727               newbsp->id = SeqIdSetFree (newbsp->id);
11728               newbsp->id = MakeNewProteinSeqId (NULL, nuc_sip);
11729               newbsp->hist = SeqHistFree (newbsp->hist);
11730               VisitFeaturesOnBsp (newbsp, (Pointer) newbsp->id, CorrectFeatureSeqIds);
11731               SetSeqFeatProduct (dup, newbsp);
11732             }
11733             SeqMgrReplaceInBioseqIndex (newbsp);
11734           }
11735         }
11736         AddSeqEntryToSeqEntry (top, newsep, TRUE);
11737       }
11738     }
11739   }
11740 }
11741 
11742 
IsFeatureOkForFeatureTypes(SeqFeatPtr sfp,ValNodePtr list)11743 static Boolean IsFeatureOkForFeatureTypes (SeqFeatPtr sfp, ValNodePtr list)
11744 {
11745   Int4 ftype;
11746   Boolean rval = FALSE;
11747 
11748   if (sfp == NULL) {
11749     rval = FALSE;
11750   } else if (list == NULL) {
11751     rval = TRUE;
11752   } else {
11753     ftype = GetFeatureTypeFromFeatdef (sfp->idx.subtype);
11754     while (list != NULL && !rval) {
11755       if (list->choice == ftype) {
11756         rval = TRUE;
11757       }
11758       list = list->next;
11759     }
11760   }
11761   return rval;
11762 }
11763 
11764 
11765 static Boolean
ImportFeaturesWithOffset(UpdatePairPtr upp,UpdateOptionsPtr uop,UpdateAlignmentLengthsPtr ualp,Int4 offset)11766 ImportFeaturesWithOffset
11767 (UpdatePairPtr             upp,
11768  UpdateOptionsPtr          uop,
11769  UpdateAlignmentLengthsPtr ualp,
11770   Int4         offset)
11771 
11772 {
11773   CodeBreakPtr       cbp;
11774   SeqMgrFeatContext  context;
11775   CdRegionPtr        crp;
11776   SeqFeatPtr         dup, sfp, last = NULL;
11777   Uint2              entityID;
11778   Boolean            keepProteinIDs = FALSE;
11779   SeqEntryPtr        top;
11780   RnaRefPtr          rrp;
11781   SeqAnnotPtr        sap = NULL, saptmp;
11782   SeqDescrPtr        sdp;
11783   SeqIdPtr           sip;
11784   tRNAPtr            trp;
11785 
11786   if (upp == NULL || uop == NULL || ualp == NULL) return FALSE;
11787   upp->newfeat_sap = NULL;
11788   SeqEntrySetScope (NULL);
11789 
11790   sfp = SeqMgrGetNextFeature (upp->update_bsp, NULL, 0, 0, &context);
11791 
11792   if (sfp == NULL)
11793   {
11794     /* no features to update, done */
11795     return TRUE;
11796   }
11797 
11798   if (uop->indexer_opts != NULL
11799       && uop->indexer_opts->keep_protein_ids
11800       && ! DoSequencesHaveDifferentOrganisms (upp->orig_bsp, upp->update_bsp))
11801   {
11802     keepProteinIDs = TRUE;
11803   }
11804 
11805   entityID = ObjMgrGetEntityIDForPointer (upp->orig_bsp);
11806   top = GetBestTopParentForData (entityID, upp->orig_bsp);
11807 
11808   sdp = ExtractBioSourceAndPubs (top);
11809 
11810   sip = SeqIdFindBest (upp->orig_bsp->id, 0);
11811 
11812   for (; sfp != NULL; sfp = SeqMgrGetNextFeature (upp->update_bsp, sfp, 0, 0, &context))
11813   {
11814     if (uop->submitter_opts->sequence_update_type == eSequenceUpdatePatch
11815         && (context.right < ualp->new5 || context.left > ualp->new5 + ualp->newa))
11816     {
11817       /* this was a patch operation, and feature is outside patch area */
11818       continue;
11819     }
11820     if (sfp->data.choice == SEQFEAT_USER)
11821     {
11822       /* this is where we will continue if this is a RefTrack object */
11823     }
11824 
11825     /* skip if it's not in the list of feature types */
11826     if (uop->submitter_opts->feature_import_options != NULL
11827         && !IsFeatureOkForFeatureTypes(sfp, uop->submitter_opts->feature_import_options->feature_types))
11828     {
11829       continue;
11830     }
11831     dup = AsnIoMemCopy ((Pointer) sfp,
11832                         (AsnReadFunc) SeqFeatAsnRead,
11833                         (AsnWriteFunc) SeqFeatAsnWrite);
11834 
11835     /* if this is the first feature we have imported, create an annotation to hold it.
11836      * we put the features on a separate annotation so that we will be able to resolve
11837      * duplicates later.
11838      */
11839     if (last == NULL)
11840     {
11841       sap = SeqAnnotNew ();
11842       if (upp->orig_bsp->annot == NULL)
11843       {
11844         upp->orig_bsp->annot = sap;
11845       }
11846       else
11847       {
11848         for (saptmp = upp->orig_bsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
11849         saptmp->next = sap;
11850       }
11851       sap->type = 1;
11852       sap->data = (Pointer) dup;
11853     } else {
11854       last->next = dup;
11855     }
11856     last = dup;
11857 
11858     OffsetLocation (dup->location, offset, sip);
11859     switch (dup->data.choice) {
11860       case SEQFEAT_CDREGION :
11861         crp = (CdRegionPtr) dup->data.value.ptrvalue;
11862         if (crp != NULL) {
11863           for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
11864             OffsetLocation (cbp->loc, offset, sip);
11865           }
11866         }
11867         break;
11868       case SEQFEAT_RNA :
11869         rrp = (RnaRefPtr) dup->data.value.ptrvalue;
11870         if (rrp != NULL && rrp->ext.choice == 2) {
11871           trp = (tRNAPtr) rrp->ext.value.ptrvalue;
11872           if (trp != NULL && trp->anticodon != NULL) {
11873             OffsetLocation (trp->anticodon, offset, sip);
11874           }
11875         }
11876         break;
11877       default :
11878         break;
11879     }
11880     ImportFeatureProduct (dup, keepProteinIDs, top, sip, sfp->idx.entityID);
11881   }
11882 
11883   ReplaceBioSourceAndPubs (top, sdp);
11884 
11885   upp->newfeat_sap = sap;
11886 
11887   return TRUE;
11888 }
11889 
GetMaxPositionForUpdate(BioseqPtr orig_bsp,UpdateOptionsPtr uop,UpdateAlignmentLengthsPtr ualp)11890 static Int4 GetMaxPositionForUpdate
11891 (BioseqPtr                 orig_bsp,
11892  UpdateOptionsPtr          uop,
11893  UpdateAlignmentLengthsPtr ualp)
11894 {
11895   Int4 new_len = 0;
11896 
11897   if (uop == NULL || uop->submitter_opts == NULL)
11898   {
11899     return 0;
11900   }
11901 
11902   switch (uop->submitter_opts->sequence_update_type)
11903   {
11904     case eSequenceUpdateNoChange:
11905       if (orig_bsp != NULL)
11906       {
11907         new_len = orig_bsp->length;
11908       }
11909       break;
11910     case eSequenceUpdatePatch:
11911       if (ualp != NULL)
11912       {
11913         new_len = ualp->old5 + ualp->newa + ualp->old3;
11914       }
11915       break;
11916     case eSequenceUpdateReplace:
11917       if (ualp != NULL)
11918       {
11919         new_len = ualp->new5 + ualp->newa + ualp->new3;
11920       }
11921       break;
11922     case eSequenceUpdateExtend5:
11923       if (ualp != NULL)
11924       {
11925         new_len = ualp->new5 + ualp->newa + ualp->old3;
11926       }
11927       break;
11928     case eSequenceUpdateExtend3:
11929       if (ualp != NULL)
11930       {
11931         new_len = ualp->old5 + ualp->newa + ualp->new3;
11932       }
11933       break;
11934   }
11935   return new_len;
11936 }
11937 
ImportFeaturesViaAlignment(UpdatePairPtr upp,UpdateOptionsPtr uop,UpdateAlignmentLengthsPtr ualp)11938 static Boolean ImportFeaturesViaAlignment
11939 (UpdatePairPtr             upp,
11940  UpdateOptionsPtr          uop,
11941  UpdateAlignmentLengthsPtr ualp)
11942 
11943 {
11944   CodeBreakPtr       cbp, prevcbp, nextcbp;
11945   SeqMgrFeatContext  context;
11946   CdRegionPtr        crp;
11947   SeqFeatPtr         dup, sfp, last = NULL;
11948   Uint2              entityID;
11949   Int4               from, to, max_position;
11950   Boolean            keepProteinIDs = FALSE;
11951   SeqLocPtr          newloc;
11952   SeqEntryPtr        top;
11953   RnaRefPtr          rrp;
11954   SeqAnnotPtr        sap = NULL, saptmp;
11955   SeqDescrPtr        sdp;
11956   SeqIdPtr           sip;
11957   Boolean            split;
11958   tRNAPtr            trp;
11959   Boolean            partial5, partial3;
11960 
11961   if (upp == NULL || uop == NULL || ualp == NULL) return FALSE;
11962   upp->newfeat_sap = NULL;
11963 
11964   SeqEntrySetScope (NULL);
11965 
11966   sfp = SeqMgrGetNextFeature (upp->update_bsp, NULL, 0, 0, &context);
11967   if (sfp == NULL) return FALSE;
11968 
11969   if (uop->indexer_opts != NULL && uop->indexer_opts->keep_protein_ids)
11970   {
11971     keepProteinIDs = TRUE;
11972   }
11973 
11974   entityID = ObjMgrGetEntityIDForPointer (upp->orig_bsp);
11975   top = GetBestTopParentForData (entityID, upp->orig_bsp);
11976 
11977   sdp = ExtractBioSourceAndPubs (top);
11978 
11979   sip = SeqIdFindBest (upp->orig_bsp->id, 0);
11980 
11981   from = ualp->new5;
11982   to = ualp->new5 + ualp->newa;
11983 
11984   max_position = GetMaxPositionForUpdate (upp->orig_bsp, uop, ualp);
11985 
11986   while (sfp != NULL) {
11987 
11988     if (uop->submitter_opts->feature_import_options != NULL
11989         && !IsFeatureOkForFeatureTypes(sfp, uop->submitter_opts->feature_import_options->feature_types))
11990     {
11991       /* skip if it's not in the list of feature types */
11992     } else if (context.right >= from && context.left <= to) {
11993       /* only use if in correct range */
11994       split = FALSE;
11995       newloc = GetPropagatedLocation (sfp->location, upp->update_bsp, upp->orig_bsp,
11996                                       max_position, upp->salp);
11997       if (newloc != NULL) {
11998         CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
11999         SetSeqLocPartial (newloc, partial5, partial3);
12000         dup = AsnIoMemCopy ((Pointer) sfp,
12001                             (AsnReadFunc) SeqFeatAsnRead,
12002                             (AsnWriteFunc) SeqFeatAsnWrite);
12003 
12004         SeqLocFree (dup->location);
12005         dup->location = newloc;
12006         if (split) {
12007           dup->partial = TRUE;
12008         }
12009         dup->partial |= partial5;
12010         dup->partial |= partial3;
12011 
12012         if (last == NULL) {
12013           sap = SeqAnnotNew ();
12014           if (upp->orig_bsp->annot == NULL) {
12015             upp->orig_bsp->annot = sap;
12016           } else {
12017             for (saptmp = upp->orig_bsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
12018             saptmp->next = sap;
12019           }
12020           sap->type = 1;
12021           sap->data = (Pointer) dup;
12022         } else {
12023           last->next = dup;
12024         }
12025         last = dup;
12026 
12027         switch (dup->data.choice) {
12028           case SEQFEAT_CDREGION :
12029             crp = (CdRegionPtr) dup->data.value.ptrvalue;
12030             if (crp != NULL) {
12031               prevcbp = NULL;
12032               for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp) {
12033                 nextcbp = cbp->next;
12034                 newloc = GetPropagatedLocation (cbp->loc, upp->update_bsp, upp->orig_bsp,
12035                                                 max_position, upp->salp);
12036                 SeqLocFree (cbp->loc);
12037                 cbp->loc = newloc;
12038                 if (cbp->loc == NULL) {
12039                   if (prevcbp != NULL) {
12040                     prevcbp->next = nextcbp;
12041                   } else {
12042                     crp->code_break = nextcbp;
12043                   }
12044                   cbp->next = NULL;
12045                   CodeBreakFree (cbp);
12046                 } else {
12047                   prevcbp = cbp;
12048                 }
12049               }
12050             }
12051             break;
12052           case SEQFEAT_RNA :
12053             rrp = (RnaRefPtr) dup->data.value.ptrvalue;
12054             if (rrp != NULL && rrp->ext.choice == 2) {
12055               trp = (tRNAPtr) rrp->ext.value.ptrvalue;
12056               if (trp != NULL && trp->anticodon != NULL) {
12057                 newloc = GetPropagatedLocation (trp->anticodon, upp->update_bsp, upp->orig_bsp,
12058                                                 max_position, upp->salp);
12059                 SeqLocFree (trp->anticodon);
12060                 trp->anticodon = newloc;
12061               }
12062             }
12063             break;
12064           default :
12065             break;
12066         }
12067         ImportFeatureProduct (dup, keepProteinIDs, top, sip, sfp->idx.entityID);
12068       }
12069     }
12070 
12071     sfp = SeqMgrGetNextFeature (upp->update_bsp, sfp, 0, 0, &context);
12072   }
12073 
12074   ReplaceBioSourceAndPubs (top, sdp);
12075 
12076   upp->newfeat_sap = sap;
12077 
12078   return TRUE;
12079 }
12080 
12081 /* This function examines the contexts for two features.
12082  * If the featdeftypes are the same and the locations are identical,
12083  * the features are considered to be duplicates.
12084  */
12085 static Boolean
AreFeaturesDuplicates(SeqMgrFeatContextPtr context1,SeqMgrFeatContextPtr context2)12086 AreFeaturesDuplicates
12087 (SeqMgrFeatContextPtr context1,
12088  SeqMgrFeatContextPtr context2)
12089 {
12090   Boolean ivalssame = FALSE;
12091   Int4    i, j;
12092 
12093   if (context1 == NULL || context2 == NULL)
12094   {
12095     return FALSE;
12096   }
12097 
12098   if (context1->left == context2->left &&
12099       context1->right == context2->right &&
12100       context1->featdeftype == context2->featdeftype)
12101   {
12102     if (context1->strand == context2->strand ||
12103         context2->strand == Seq_strand_unknown ||
12104         context1->strand == Seq_strand_unknown)
12105     {
12106       ivalssame = TRUE;
12107       if (context1->numivals != context2->numivals ||
12108           context1->ivals == NULL ||
12109           context2->ivals == NULL)
12110       {
12111         ivalssame = FALSE;
12112       }
12113       else
12114       {
12115         for (i = 0, j = 0; i < context2->numivals; i++, j += 2)
12116         {
12117           if (context1->ivals [j] != context2->ivals [j])
12118           {
12119             ivalssame = FALSE;
12120           }
12121           if (context1->ivals [j + 1] != context2->ivals [j + 1])
12122           {
12123             ivalssame = FALSE;
12124           }
12125         }
12126       }
12127     }
12128   }
12129   return ivalssame;
12130 }
12131 
12132 
ResolveDuplicateUpdateFeats(BioseqPtr bsp,UpdateOptionsPtr uop,SeqAnnotPtr newfeat_sap)12133 static void ResolveDuplicateUpdateFeats
12134 (BioseqPtr        bsp,
12135  UpdateOptionsPtr uop,
12136  SeqAnnotPtr      newfeat_sap)
12137 
12138 {
12139   SeqMgrFeatContext  context, lastcontext;
12140   SeqFeatPtr         lastsfp = NULL, sfp;
12141 
12142   if (bsp == NULL
12143       || newfeat_sap == NULL
12144       || uop == NULL
12145       || uop->submitter_opts == NULL
12146       || uop->submitter_opts->feature_import_options == NULL
12147       || uop->submitter_opts->feature_import_options->feature_import_type == eFeatureUpdateAll)
12148   {
12149     return;
12150   }
12151   SeqMgrIndexFeatures (bsp->idx.entityID, NULL);
12152 
12153   lastsfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
12154   if (lastsfp == NULL) return;
12155 
12156   MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
12157 
12158   sfp = SeqMgrGetNextFeature (bsp, lastsfp, 0, 0, &context);
12159   if (sfp == NULL) return;
12160 
12161   while (sfp != NULL)
12162   {
12163     if (context.sap != lastcontext.sap
12164         && (context.sap == newfeat_sap || lastcontext.sap == newfeat_sap)
12165         && AreFeaturesDuplicates (&context, &lastcontext))
12166     {
12167       if (uop->submitter_opts->feature_import_options->feature_import_type == eFeatureUpdateAllReplaceDups) { /* keep new */
12168         if (context.sap == newfeat_sap) {
12169           lastsfp->idx.deleteme = TRUE;
12170           MarkProductForDeletion (lastsfp->product);
12171         } else if (lastcontext.sap == newfeat_sap) {
12172           sfp->idx.deleteme = TRUE;
12173           MarkProductForDeletion (sfp->product);
12174         }
12175       } else if (uop->submitter_opts->feature_import_options->feature_import_type == eFeatureUpdateAllExceptDups) { /* keep old */
12176         if (context.sap == newfeat_sap) {
12177           sfp->idx.deleteme = TRUE;
12178           MarkProductForDeletion (sfp->product);
12179         } else if (lastcontext.sap == newfeat_sap) {
12180           lastsfp->idx.deleteme = TRUE;
12181           MarkProductForDeletion (lastsfp->product);
12182         }
12183 
12184       } else if (uop->submitter_opts->feature_import_options->feature_import_type == eFeatureUpdateAllMergeDups) { /* merge */
12185         if (context.sap == newfeat_sap) {
12186           FuseFeatures (sfp, lastsfp);
12187           lastsfp->idx.deleteme = TRUE;
12188           MarkProductForDeletion (lastsfp->product);
12189         } else if (lastcontext.sap == newfeat_sap) {
12190           FuseFeatures (lastsfp, sfp);
12191           sfp->idx.deleteme = TRUE;
12192           MarkProductForDeletion (sfp->product);
12193         }
12194       }
12195     }
12196 
12197     lastsfp = sfp;
12198     MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
12199 
12200     sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
12201   }
12202 }
12203 
12204 
12205 
12206 static void
UpdateProteinForOneUpdatedCodingRegion(SeqFeatPtr sfp,ValNodePtr transl_except_list,IndexerOptionsPtr iop,Uint2 entityID,FILE * log_fp,BoolPtr data_in_log)12207 UpdateProteinForOneUpdatedCodingRegion
12208 (SeqFeatPtr        sfp,
12209  ValNodePtr        transl_except_list,
12210  IndexerOptionsPtr iop,
12211  Uint2             entityID,
12212  FILE              *log_fp,
12213  BoolPtr           data_in_log)
12214 {
12215   SeqLocPtr     new_product;
12216   Int4          transl_except_len = 0;
12217   Boolean       fix_products = TRUE;
12218   BioseqPtr     protBsp = NULL;
12219   SeqAlignPtr   salp = NULL;
12220   BioseqPtr     newbsp = NULL;
12221   Boolean       rval;
12222 
12223   if (sfp == NULL
12224       || sfp->idx.subtype != FEATDEF_CDS
12225       || sfp->idx.deleteme)
12226   {
12227     return;
12228   }
12229 
12230   protBsp = BioseqFindFromSeqLoc (sfp->product);
12231   if (protBsp == NULL)
12232   {
12233     return;
12234   }
12235 
12236   transl_except_len = GetOriginalTranslExceptLen (sfp, transl_except_list);
12237   rval = PrepareUpdateAlignmentForProtein (sfp,
12238                                            protBsp,
12239                                            entityID,
12240                                            log_fp,
12241                                            iop == NULL ? FALSE : iop->truncate_proteins,
12242                                            iop == NULL ? FALSE : iop->extend_proteins5,
12243                                            iop == NULL ? FALSE : iop->extend_proteins3,
12244                                            iop == NULL ? FALSE : iop->correct_cds_genes,
12245                                            transl_except_len,
12246                                            data_in_log,
12247                                            &salp,
12248                                            &newbsp);
12249   if (!rval) return;
12250 
12251   if (protBsp->idx.deleteme)
12252   {
12253     fix_products = FALSE;
12254   }
12255 
12256   ReplaceOneSequence (salp, protBsp, newbsp);
12257 
12258   if (fix_products)
12259   {
12260     if (sfp->product->choice != SEQLOC_WHOLE) {
12261       new_product = SeqLocWholeNew (protBsp);
12262       if (new_product == NULL) return;
12263       SeqLocFree (sfp->product);
12264       sfp->product = new_product;
12265     }
12266     newbsp = BioseqFree (newbsp);
12267   }
12268 }
12269 
12270 static void
UpdateProteinsForUpdatedCodingRegions(BioseqPtr orig_bsp,ValNodePtr transl_except_list,IndexerOptionsPtr iop,Uint2 entityID,FILE * log_fp,BoolPtr data_in_log)12271 UpdateProteinsForUpdatedCodingRegions
12272 (BioseqPtr         orig_bsp,
12273  ValNodePtr        transl_except_list,
12274  IndexerOptionsPtr iop,
12275  Uint2             entityID,
12276  FILE              *log_fp,
12277  BoolPtr           data_in_log)
12278 {
12279   SeqFeatPtr        sfp;
12280   SeqMgrFeatContext context;
12281 
12282   sfp = SeqMgrGetNextFeature (orig_bsp, NULL, SEQFEAT_CDREGION, 0, &context);
12283   while (sfp != NULL)
12284   {
12285     UpdateProteinForOneUpdatedCodingRegion (sfp, transl_except_list, iop,
12286                                             entityID, log_fp, data_in_log);
12287     sfp = SeqMgrGetNextFeature (orig_bsp, sfp, SEQFEAT_CDREGION, 0, &context);
12288   }
12289 }
12290 
12291 static Boolean
IsSequenceUpdateChoiceAllowed(ESequenceUpdateType action,UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp,Boolean is_indexer,Boolean ignore_alignment)12292 IsSequenceUpdateChoiceAllowed
12293 (ESequenceUpdateType       action,
12294  UpdatePairPtr             upp,
12295  UpdateAlignmentLengthsPtr ualp,
12296  Boolean                   is_indexer,
12297  Boolean                   ignore_alignment)
12298 {
12299 
12300   if (upp == NULL || upp->orig_bsp == NULL || upp->update_bsp == NULL)
12301   {
12302     return FALSE;
12303   }
12304   else if (action == eSequenceUpdateNoChange)
12305   {
12306     if (ignore_alignment)
12307     {
12308       return FALSE;
12309     }
12310     else
12311     {
12312       return TRUE;
12313     }
12314   }
12315   else if (action != eSequenceUpdateNoChange
12316            && !is_indexer
12317            && (upp->orig_bsp->repr != Seq_repr_raw || upp->update_bsp->repr != Seq_repr_raw))
12318   {
12319     /* If either sequence is not raw and not indexer version, do not allow sequence update */
12320     return FALSE;
12321   }
12322   else if (action == eSequenceUpdatePatch
12323            && (upp->salp == NULL || ignore_alignment
12324              || (! RawSequencePatchOk (upp->orig_bsp, upp->update_bsp)
12325                  && !DeltaSequencePatchOk (upp->orig_bsp, upp->update_bsp))))
12326   {
12327     /* If no alignment or patch not available then disable the patch button */
12328     return FALSE;
12329   }
12330   else if (ignore_alignment
12331            && (action == eSequenceUpdateExtend3
12332                || action == eSequenceUpdateExtend5))
12333   {
12334     return TRUE;
12335   }
12336   else if (ualp == NULL)
12337   {
12338     return FALSE;
12339   }
12340   else if (action == eSequenceUpdateExtend3
12341            && (ualp->new3 < ualp->old3 || ualp->new3 == 0))
12342   {
12343     return FALSE;
12344   }
12345   else if (action == eSequenceUpdateExtend5
12346            && (ualp->new5 < ualp->old5 || ualp->new5 == 0))
12347   {
12348     return FALSE;
12349   }
12350   else
12351   {
12352     return TRUE;
12353   }
12354 }
12355 
12356 static void
ReportBadUpdateType(ESequenceUpdateType action,UpdatePairPtr upp,FILE * log_fp,BoolPtr data_in_log)12357 ReportBadUpdateType
12358 (ESequenceUpdateType action,
12359  UpdatePairPtr       upp,
12360  FILE                *log_fp,
12361  BoolPtr             data_in_log)
12362 {
12363   Char id_txt [MAX_ID_LEN];
12364 
12365   if (upp == NULL
12366       || upp->orig_bsp == NULL
12367       || log_fp == NULL
12368       || data_in_log == NULL)
12369   {
12370     return;
12371   }
12372 
12373   SeqIdWrite (SeqIdFindBest (upp->orig_bsp->id, SEQID_GENBANK), id_txt,
12374               PRINTID_REPORT, sizeof (id_txt) - 1);
12375 
12376   switch (action)
12377   {
12378     case eSequenceUpdateNoChange:
12379       /* do nothing */
12380       break;
12381     case eSequenceUpdateReplace:
12382       fprintf (log_fp, "Unable to replace sequence for %s\n", id_txt);
12383       *data_in_log = TRUE;
12384       break;
12385     case eSequenceUpdatePatch:
12386       fprintf (log_fp, "Unable to patch sequence for %s\n", id_txt);
12387       *data_in_log = TRUE;
12388       break;
12389     case eSequenceUpdateExtend5:
12390       fprintf (log_fp, "Unable to extend sequence on 5' end for %s\n", id_txt);
12391       *data_in_log = TRUE;
12392       break;
12393     case eSequenceUpdateExtend3:
12394       fprintf (log_fp, "Unable to extend sequence on 3' end for %s\n", id_txt);
12395       *data_in_log = TRUE;
12396       break;
12397     default:
12398       fprintf (log_fp, "Unknown update operation for %s\n", id_txt);
12399       *data_in_log = TRUE;
12400       break;
12401   }
12402 }
12403 
OkToTrimQualityScores(UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp)12404 static Boolean OkToTrimQualityScores (UpdatePairPtr upp, UpdateAlignmentLengthsPtr ualp)
12405 {
12406   CharPtr buf1, buf2;
12407   Boolean rval = FALSE;
12408 
12409   if (upp == NULL || upp->orig_bsp == NULL || upp->update_bsp == NULL
12410       || upp->update_bsp->length > upp->orig_bsp->length
12411       || ualp == NULL || ualp->new5 > 0 || ualp->new3 > 0 || ualp->newa != ualp->olda || ualp->newa != upp->update_bsp->length) {
12412     return FALSE;
12413   }
12414   buf1 = (CharPtr) MemNew (sizeof (Char) * (ualp->newa + 1));
12415   MemSet (buf1, 0, sizeof (Char) * (ualp->newa + 1));
12416   buf2= (CharPtr) MemNew (sizeof (Char) * (ualp->newa + 1));
12417   MemSet (buf2, 0, sizeof (Char) * (ualp->newa + 1));
12418 
12419   if (SeqPortStreamInt (upp->orig_bsp, ualp->old5, ualp->old5 + ualp->olda - 1, Seq_strand_plus, STREAM_EXPAND_GAPS, buf1, NULL) == upp->update_bsp->length
12420       && SeqPortStreamInt (upp->update_bsp, 0, upp->update_bsp->length - 1, Seq_strand_plus, STREAM_EXPAND_GAPS, buf2, NULL) == upp->update_bsp->length
12421       && StringCmp (buf1, buf2) == 0) {
12422     rval = TRUE;
12423   }
12424   buf1 = MemFree (buf1);
12425   buf2 = MemFree (buf2);
12426   return rval;
12427 }
12428 
12429 
12430 static Boolean
UpdateOrExtendOneSequenceEx(UpdatePairPtr upp,UpdateOptionsPtr uop,UpdateAlignmentLengthsPtr ualp,Uint2 entityID,FILE * log_fp,BoolPtr data_in_log,Boolean force_allow_replace_without_aln)12431 UpdateOrExtendOneSequenceEx
12432 (UpdatePairPtr             upp,
12433  UpdateOptionsPtr          uop,
12434  UpdateAlignmentLengthsPtr ualp,
12435  Uint2                     entityID,
12436  FILE                      *log_fp,
12437  BoolPtr                   data_in_log,
12438  Boolean                   force_allow_replace_without_aln)
12439 {
12440   ValNodePtr   prot_feat_list = NULL;
12441   ValNodePtr   transl_except_list = NULL;
12442   Boolean      sequence_update_successful = FALSE;
12443   Boolean      rval = FALSE;
12444   Int4         feature_update_offset;
12445   Int4         orig_seq_len;
12446   Uint2        update_entityID;
12447   Char         id_txt [128];
12448   Boolean      deleted_features = FALSE;
12449   Boolean      trim_quality_scores = FALSE;
12450   SeqFeatPtr   sfp;
12451   SeqMgrFeatContext context;
12452   Boolean           any_cds = FALSE;
12453 
12454   if (upp == NULL || upp->orig_bsp == NULL || upp->update_bsp == NULL
12455       || uop == NULL || uop->submitter_opts == NULL)
12456   {
12457     return FALSE;
12458   }
12459   upp->feature_update_successful = FALSE;
12460 
12461   update_entityID = upp->update_bsp->idx.entityID;
12462 
12463   if (!IsSequenceUpdateChoiceAllowed (uop->submitter_opts->sequence_update_type,
12464                                       upp, ualp, indexerVersion,
12465                                       uop->submitter_opts->ignore_alignment))
12466   {
12467     ReportBadUpdateType (uop->submitter_opts->sequence_update_type,
12468                          upp, log_fp, data_in_log);
12469     return FALSE;
12470   }
12471 
12472   if (uop->submitter_opts->sequence_update_type == eSequenceUpdateReplace
12473       && upp->salp == NULL && !force_allow_replace_without_aln)
12474   {
12475     SeqIdWrite (SeqIdFindBest (upp->orig_bsp->id, SEQID_GENBANK), id_txt,
12476                 PRINTID_REPORT, sizeof (id_txt) - 1);
12477 
12478     if (ANS_NO == Message (MSG_YN,
12479                            "There is no alignment for %s.  Are you sure that you want to replace this sequence?",
12480                            id_txt))
12481     {
12482       return FALSE;
12483     }
12484   }
12485 
12486   if ((sfp = SeqMgrGetNextFeature (upp->orig_bsp, NULL, SEQFEAT_CDREGION, 0, &context)) != NULL)
12487   {
12488     any_cds = TRUE;
12489   }
12490   else if ((sfp = SeqMgrGetNextFeature (upp->update_bsp, NULL, SEQFEAT_CDREGION, 0, &context)) != NULL)
12491   {
12492     any_cds = TRUE;
12493   }
12494 
12495   /* remove features */
12496   switch (uop->submitter_opts->feature_remove_type)
12497   {
12498     case eFeatureRemoveAll:
12499       deleted_features = RemoveOldFeats (upp->orig_bsp);
12500       break;
12501     case eFeatureRemoveAligned:
12502       deleted_features = RemoveFeatsInAlignedRegion (upp->orig_bsp, ualp);
12503       break;
12504     case eFeatureRemoveNotAligned:
12505       deleted_features = RemoveFeatsNotInAlignedRegion (upp->orig_bsp, ualp);
12506       break;
12507     default:
12508       break;
12509   }
12510   if (deleted_features) {
12511     DeleteMarkedObjects (upp->orig_bsp->idx.entityID, 0, NULL);
12512     SeqMgrClearFeatureIndexes (upp->orig_bsp->idx.entityID, upp->orig_bsp);
12513     SeqMgrIndexFeatures (upp->orig_bsp->idx.entityID, NULL);
12514   }
12515 
12516   if (ISA_na (upp->orig_bsp->mol) && uop->indexer_opts != NULL && uop->indexer_opts->update_proteins)
12517   {
12518     prot_feat_list = FindProductProtRefs (upp->orig_bsp);
12519     transl_except_list = FindTranslExceptCDSs (upp->orig_bsp);
12520   }
12521 
12522   /* get length of original sequence before updating */
12523   orig_seq_len = upp->orig_bsp->length;
12524 
12525   /* update sequence */
12526   switch (uop->submitter_opts->sequence_update_type)
12527   {
12528     case eSequenceUpdateReplace:
12529       trim_quality_scores = OkToTrimQualityScores (upp, ualp);
12530       ReplaceOneSequence (upp->salp, upp->orig_bsp, upp->update_bsp);
12531       sequence_update_successful = TRUE;
12532       rval = sequence_update_successful;
12533       break;
12534     case eSequenceUpdatePatch:
12535       sequence_update_successful = UpdateSequencePatch (upp, ualp);
12536       rval = sequence_update_successful;
12537       break;
12538     case eSequenceUpdateExtend5:
12539       sequence_update_successful = UpdateSequenceExtend5Prime (upp, ualp);
12540       rval = sequence_update_successful;
12541       break;
12542     case eSequenceUpdateExtend3:
12543       sequence_update_successful = UpdateSequenceExtend3Prime (upp, ualp);
12544       rval = sequence_update_successful;
12545       break;
12546     case eSequenceUpdateNoChange:
12547       rval = TRUE;
12548       break;
12549   }
12550 
12551   if (log_fp != NULL && data_in_log != NULL && upp->revcomp)
12552   {
12553      SeqIdWrite (SeqIdFindBest (upp->orig_bsp->id, SEQID_GENBANK), id_txt,
12554                  PRINTID_REPORT, sizeof (id_txt) - 1);
12555      fprintf (log_fp, "Reverse complemented %s\n", id_txt);
12556      *data_in_log = TRUE;
12557   }
12558 
12559   /* update features */
12560   if (uop->submitter_opts->feature_import_options != NULL
12561       && uop->submitter_opts->feature_import_options->feature_import_type != eFeatureUpdateNoChange)
12562   {
12563     if (! SeqMgrFeaturesAreIndexed (update_entityID))
12564       SeqMgrIndexFeatures (update_entityID, NULL);
12565 
12566     if (sequence_update_successful)
12567     {
12568       feature_update_offset = 0;
12569       if (uop->submitter_opts->sequence_update_type == eSequenceUpdateExtend3
12570           || uop->submitter_opts->sequence_update_type == eSequenceUpdatePatch)
12571       {
12572         if (upp->salp == NULL)
12573         {
12574           feature_update_offset = orig_seq_len;
12575         }
12576         else
12577         {
12578           feature_update_offset = ualp->old5 - ualp->new5;
12579         }
12580       }
12581       upp->feature_update_successful = ImportFeaturesWithOffset (upp, uop, ualp,
12582                                                             feature_update_offset);
12583       rval &= upp->feature_update_successful;
12584     }
12585     else
12586     {
12587       upp->feature_update_successful = ImportFeaturesViaAlignment (upp, uop, ualp);
12588     }
12589   }
12590 
12591   if (uop->submitter_opts->sequence_update_type == eSequenceUpdateReplace
12592       && upp->revcomp
12593       && sequence_update_successful)
12594   {
12595     ReverseComplementBioseqAndFeats (upp->orig_bsp, entityID);
12596   }
12597 
12598 
12599   if (uop->indexer_opts != NULL && uop->indexer_opts->add_cit_subs
12600       && (upp->feature_update_successful
12601           || (sequence_update_successful
12602               && ! AreSequenceResiduesIdentical(upp->orig_bsp, upp->update_bsp))))
12603 
12604   {
12605     AddCitSubToUpdatedSequence (upp->orig_bsp, entityID, kSubmitterUpdateText);
12606   }
12607 
12608   /* update proteins for coding regions on the updated sequence */
12609   if (sequence_update_successful
12610       && uop->indexer_opts != NULL
12611       && uop->indexer_opts->update_proteins
12612       && any_cds)
12613   {
12614     SeqMgrClearFeatureIndexes (entityID, upp->orig_bsp);
12615     SeqMgrIndexFeatures (entityID, NULL);
12616     UpdateProteinsForUpdatedCodingRegions (upp->orig_bsp, transl_except_list,
12617                                            uop->indexer_opts, entityID,
12618                                            log_fp, data_in_log);
12619     FixProtRefPtrs (prot_feat_list);
12620   }
12621 
12622   if (trim_quality_scores && (uop->indexer_opts == NULL || !uop->indexer_opts->update_quality_scores)) {
12623     TrimQualityScoresForSequenceUpdate (upp->orig_bsp, ualp->old5, ualp->old3, log_fp, data_in_log);
12624   } else if (uop->indexer_opts != NULL && uop->indexer_opts->update_quality_scores
12625       && uop->submitter_opts->sequence_update_type == eSequenceUpdateReplace)
12626   {
12627     ReplaceQualityScores (upp->orig_bsp, upp->update_bsp,
12628                           log_fp, data_in_log);
12629   }
12630   else if (uop->submitter_opts->sequence_update_type != eSequenceUpdateNoChange)
12631   {
12632     RemoveQualityScores (upp->orig_bsp, log_fp, data_in_log);
12633   }
12634 
12635   prot_feat_list = ValNodeFree (prot_feat_list);
12636   transl_except_list = ValNodeFree (transl_except_list);
12637 
12638   /* Note - we do not remove the update sequence here - that will happen when
12639    * the UpdateSequence form is removed.
12640    */
12641   upp->update_bsp = NULL;
12642 
12643   return rval;
12644 }
12645 
12646 
12647 static Boolean
UpdateOrExtendOneSequence(UpdatePairPtr upp,UpdateOptionsPtr uop,UpdateAlignmentLengthsPtr ualp,Uint2 entityID,FILE * log_fp,BoolPtr data_in_log)12648 UpdateOrExtendOneSequence
12649 (UpdatePairPtr             upp,
12650  UpdateOptionsPtr          uop,
12651  UpdateAlignmentLengthsPtr ualp,
12652  Uint2                     entityID,
12653  FILE                      *log_fp,
12654  BoolPtr                   data_in_log)
12655 {
12656   Boolean rval;
12657   SeqEntryPtr sep;
12658 
12659   rval = UpdateOrExtendOneSequenceEx (upp, uop, ualp, entityID, log_fp, data_in_log, FALSE);
12660 
12661   if (upp->feature_update_successful
12662       && uop->submitter_opts->feature_import_options != NULL
12663       && uop->submitter_opts->feature_import_options->feature_import_type > eFeatureUpdateNoChange
12664       && uop->submitter_opts->feature_import_options->feature_import_type != eFeatureRemoveAll)
12665   {
12666     /* resolve features unless the policy was to remove all the old ones */
12667 
12668     sep = GetTopSeqEntryForEntityID (entityID);
12669     /* need to set scope to make sure we mark the right bioseq for deletion */
12670     SeqEntrySetScope (sep);
12671     ResolveDuplicateUpdateFeats (upp->orig_bsp, uop, upp->newfeat_sap);
12672     SeqEntrySetScope (NULL);
12673     DeleteMarkedObjects (entityID, 0, NULL);
12674     SeqMgrClearFeatureIndexes (entityID, NULL);
12675   }
12676   return rval;
12677 }
12678 
12679 
12680 static void
CalculateUpdateAlignmentLengths(SeqAlignPtr salp,BioseqPtr orig_bsp,BioseqPtr update_bsp,UpdateAlignmentLengthsPtr ualp)12681 CalculateUpdateAlignmentLengths
12682 (SeqAlignPtr               salp,
12683  BioseqPtr                 orig_bsp,
12684  BioseqPtr                 update_bsp,
12685  UpdateAlignmentLengthsPtr ualp)
12686 {
12687   Int4         stopold, startold, lenold, stopnew, startnew, lennew;
12688   Int4         aln_length;
12689 
12690   if (ualp == NULL || update_bsp == NULL || orig_bsp == NULL) return;
12691 
12692   MemSet (ualp, 0, sizeof (UpdateAlignmentLengthsData));
12693 
12694   if (salp == NULL)
12695   {
12696     return;
12697   }
12698 
12699   ualp->aln_length = AlnMgr2GetAlnLength (salp, FALSE);
12700   AlnMgr2GetNthSeqRangeInSA (salp, 1, &startold, &stopold);
12701   AlnMgr2GetNthSeqRangeInSA (salp, 2, &startnew, &stopnew);
12702   lenold = orig_bsp->length;
12703   lennew = update_bsp->length;
12704 
12705   ualp->old5 = startold;
12706   ualp->old3 = lenold - stopold - 1;
12707   ualp->olda = stopold - startold + 1;
12708 
12709   ualp->new5 = startnew;
12710   ualp->new3 = lennew - stopnew - 1;
12711   ualp->newa = stopnew - startnew + 1;
12712 
12713 #if 0
12714   ualp->startmax = MAX (startold, startnew);
12715   ualp->stopmax = MAX (aln_length + lenold - stopold, aln_length + lennew - stopnew);
12716 
12717   ualp->strandold = AlnMgr2GetNthStrand (sap, 1);
12718   ualp->strandnew = AlnMgr2GetNthStrand (sap, 2);
12719 #endif
12720 
12721   /* calculate logarithmic scale for length */
12722   ualp->log10_aln_length = 1;
12723   aln_length = ualp->aln_length;
12724   while (aln_length >= 10) {
12725     aln_length /= 10;
12726     (ualp->log10_aln_length)++;
12727   }
12728 
12729   /* calculate alignment recombination lengths */
12730   ualp->recomb1 = -1;
12731   ualp->recomb2 = -1;
12732   if (ualp->new5 > ualp->old5 && ualp->new3 < ualp->old3) {
12733     ualp->recomb2 = ualp->aln_length;
12734   }
12735 
12736   /* Extend 3' */
12737 
12738   else if (ualp->new5 < ualp->old5 && ualp->new3 > ualp->old3) {
12739     ualp->recomb1 = 0;
12740   }
12741 
12742   /* Replace */
12743 
12744   else {
12745     ualp->recomb1 = 0;
12746     ualp->recomb2 = ualp->aln_length;
12747   }
12748 
12749 
12750 }
12751 
12752 /* The following group of functions is used to generate the pictures for the
12753  * alignment viewer for the update sequence dialog.
12754  */
12755 
12756 /* This function draws one rectangle for the new sequence and one rectangle for
12757  * the old sequence.  The aligned overlap is filled in with black, the unaligned
12758  * portions are drawn with outlines only.
12759  */
MakeAlignmentOverviewPicture(UpdateAlignmentLengthsPtr ualp)12760 static SegmenT MakeAlignmentOverviewPicture (UpdateAlignmentLengthsPtr ualp)
12761 
12762 {
12763   SegmenT   pict;
12764   Char      str [96];
12765   Int4      top, bottom;
12766 
12767   pict = CreatePicture ();
12768   if (ualp == NULL) return pict;
12769 
12770   top = 0;
12771   bottom = top - 10;
12772 
12773   DrawAlignBlock (pict, top, bottom, bottom, LOWER_CENTER, ualp->old5, ualp->olda, ualp->old3, ualp->aln_length);
12774 
12775   sprintf (str, "%ld", (long) ualp->aln_length);
12776   AddLabel (pict, ualp->aln_length / 2, 10, str, SMALL_TEXT, 5, MIDDLE_CENTER, 0);
12777 
12778 
12779   top = 30;
12780   bottom = top - 10;
12781 
12782   DrawAlignBlock (pict, top, bottom, top, UPPER_CENTER, ualp->new5, ualp->newa, ualp->new3, ualp->aln_length);
12783 
12784   return pict;
12785 }
12786 
12787 /* This function shows how the new sequence will be created when the sequence is
12788  * extended and the alignment is ignored.
12789  */
MakeExtensionPicture(Int4 len_old,Int4 len_new,Boolean extend5)12790 static SegmenT MakeExtensionPicture (Int4 len_old, Int4 len_new, Boolean extend5)
12791 
12792 {
12793   SegmenT   pict;
12794   Char      str [96];
12795   Int4      top, bottom, label_loc;
12796 
12797   pict = CreatePicture ();
12798 
12799   top = 0;
12800   bottom = top - 10;
12801 
12802   label_loc = -(top + bottom) / 2;
12803 
12804   if (extend5)
12805   {
12806     sprintf (str, "New (%ld)", (long) len_new);
12807     AddLabel (pict, -len_new / 2, label_loc, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
12808     AddRectangle (pict, -len_new, top, 0, bottom, NO_ARROW, FALSE, 0);
12809     sprintf (str, "Old (%ld)", (long) len_old);
12810     AddLabel (pict, len_old / 2, label_loc - 30, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
12811     AddRectangle (pict,  0, top, len_old, bottom, NO_ARROW, FALSE, 0);
12812   }
12813   else
12814   {
12815     sprintf (str, "Old (%ld)", (long) len_old);
12816     AddLabel (pict, -len_old / 2, label_loc - 30, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
12817     AddRectangle (pict, -len_old, top, 0, bottom, NO_ARROW, FALSE, 0);
12818     sprintf (str, "New (%ld)", (long) len_new);
12819     AddLabel (pict, len_new / 2, label_loc, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
12820     AddRectangle (pict,  0, top, len_new, bottom, NO_ARROW, FALSE, 0);
12821   }
12822 
12823   return pict;
12824 }
12825 
DrawUpdateAlignmentBits(SegmenT pict,Int4 top,Int4 bottom,Int4 row,Int4 pos1,Int4 pos2,SeqAlignPtr sap,ValNodePtr PNTR indels)12826 static void DrawUpdateAlignmentBits (
12827   SegmenT         pict,
12828   Int4            top,
12829   Int4            bottom,
12830   Int4            row,
12831   Int4            pos1,
12832   Int4            pos2,
12833   SeqAlignPtr     sap,
12834   ValNodePtr PNTR indels /* pointer to ValNode list of integers which are the locations
12835                           * of insertions and deletions.
12836                           */
12837 )
12838 
12839 {
12840   AlnMsg2Ptr  amp;
12841   Int4       len, start, stop, from, to;
12842   Char       str [96];
12843   Boolean    wasgap;
12844 
12845   amp = AlnMsgNew2 ();
12846   if (amp == NULL) return;
12847 
12848   amp->from_aln = 0;
12849   amp->to_aln = -1;
12850   amp->row_num = row;
12851 
12852   start = 0;
12853   stop = 0;
12854   from = 0;
12855   to = 0;
12856   wasgap = FALSE;
12857 
12858   while (AlnMgr2GetNextAlnBit (sap, amp)) {
12859     len = amp->to_row - amp->from_row + 1;
12860     stop = start + len;
12861     if (amp->type == AM_GAP) {
12862       if (wasgap) {
12863         to = stop;
12864       } else {
12865         AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
12866         wasgap = TRUE;
12867         from = start;
12868         to = stop;
12869       }
12870     } else {
12871       if (wasgap) {
12872 
12873         /* record for accurate scrolling to text view */
12874         ValNodeAddInt (indels, 0, from);
12875 
12876         AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
12877         wasgap = FALSE;
12878         from = start;
12879         to = stop;
12880       } else {
12881         to = stop;
12882       }
12883     }
12884     start += len;
12885   }
12886 
12887   if (to > from) {
12888     if (wasgap) {
12889 
12890       /* record for accurate scrolling to text view */
12891       ValNodeAddInt (indels, 0, from);
12892 
12893       AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
12894     } else {
12895       AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
12896     }
12897   }
12898 
12899   AlnMsgFree2 (amp);
12900 
12901   sprintf (str, "%ld", (long) pos1);
12902   AddLabel (pict, 0, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
12903 
12904   sprintf (str, "%ld", (long) pos2);
12905   AddLabel (pict, to, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
12906 }
12907 
DrawUpdateAlignmentDiffs(SegmenT pict,Int4 top,Int4 bottom,SeqAlignPtr salp,BioseqPtr orig_bsp,BioseqPtr update_bsp,ValNodePtr PNTR mismatches)12908 static void DrawUpdateAlignmentDiffs
12909 (SegmenT         pict,
12910  Int4            top,
12911  Int4            bottom,
12912  SeqAlignPtr     salp,
12913  BioseqPtr       orig_bsp,
12914  BioseqPtr       update_bsp,
12915  ValNodePtr PNTR mismatches)
12916 
12917 {
12918   AlnMsg2Ptr  amp1, amp2;
12919   SegmenT    seg;
12920   Int4       len1, len2, i;
12921   Int4       seg_i, seg_n, seg_start, seg_stop;
12922   CharPtr      seq1, seq2;
12923   Uint2        entityID;
12924   SeqEntryPtr  sep;
12925 
12926   if (salp == NULL || orig_bsp == NULL || update_bsp == NULL
12927       || pict == NULL || mismatches == NULL)
12928   {
12929     return;
12930   }
12931 
12932   entityID = ObjMgrGetEntityIDForPointer (orig_bsp);
12933   sep = GetTopSeqEntryForEntityID (entityID);
12934   SeqEntrySetScope (sep);
12935   seq1 = GetSequenceByBsp (orig_bsp);
12936   SeqEntrySetScope (NULL);
12937 
12938   entityID = update_bsp->idx.entityID;
12939   sep = GetTopSeqEntryForEntityID (entityID);
12940   SeqEntrySetScope (sep);
12941   seq2 = GetSequenceByBsp (update_bsp);
12942   SeqEntrySetScope (NULL);
12943 
12944   if (seq1 == NULL || seq2 == NULL)
12945   {
12946     seq1 = MemFree (seq1);
12947     seq2 = MemFree (seq2);
12948     return;
12949   }
12950   len1 = StringLen (seq1);
12951   len2 = StringLen (seq2);
12952 
12953   seg = CreateSegment (pict, 0, 0);
12954   AddAttribute (seg, COLOR_ATT, RED_COLOR, 0, 0, 0, 0);
12955 
12956   seg_n = AlnMgr2GetNumSegs(salp);
12957   for (seg_i = 1; seg_i<=seg_n; seg_i++) {
12958     AlnMgr2GetNthSegmentRange(salp, seg_i, &seg_start, &seg_stop);
12959 
12960     amp1 = AlnMsgNew2 ();
12961     amp2 = AlnMsgNew2 ();
12962     if (amp1 == NULL || amp2 == NULL) return;
12963 
12964     amp1->from_aln = seg_start;
12965     amp1->to_aln = seg_stop;
12966     amp1->row_num = 1;
12967 
12968     amp2->from_aln = seg_start;
12969     amp2->to_aln = seg_stop;
12970     amp2->row_num = 2;
12971 
12972     AlnMgr2GetNextAlnBit (salp, amp1);
12973     AlnMgr2GetNextAlnBit (salp, amp2);
12974 
12975     if (amp1->to_row - amp1->from_row == amp2->to_row - amp2->from_row &&
12976         amp1->type == AM_SEQ && amp2->type == AM_SEQ) {
12977       for (i=0; i<seg_stop-seg_start+1; i++) {
12978         if (seq1[amp1->from_row+i] != seq2[amp2->from_row+i]) {
12979 
12980           /* record for accurate scrolling to text view */
12981           ValNodeAddInt (mismatches, 0, i);
12982 
12983           AddLine (seg, seg_start+i, top, seg_start+i, bottom, FALSE, 0);
12984         }
12985       }
12986     }
12987 
12988     AlnMsgFree2 (amp1);
12989     AlnMsgFree2 (amp2);
12990   }
12991 }
12992 
12993 /* This function draws just the aligned region.
12994  */
MakeAlignmentDetailsPicture(SeqAlignPtr salp,BioseqPtr orig_bsp,BioseqPtr update_bsp,ValNodePtr PNTR indels,ValNodePtr PNTR mismatches,UpdateAlignmentLengthsPtr ualp,Boolean revcomp)12995 static SegmenT MakeAlignmentDetailsPicture
12996 (SeqAlignPtr               salp,
12997  BioseqPtr                 orig_bsp,
12998  BioseqPtr                 update_bsp,
12999  ValNodePtr PNTR           indels,
13000  ValNodePtr PNTR           mismatches,
13001  UpdateAlignmentLengthsPtr ualp,
13002  Boolean                   revcomp)
13003 
13004 {
13005   Int4     aln_length;
13006   SegmenT  pict;
13007   Int4     top, bottom;
13008 
13009   pict = CreatePicture ();
13010   if (salp == NULL || ualp == NULL || indels == NULL) return pict;
13011 
13012   aln_length = ualp->aln_length;
13013 
13014   top = 0;
13015   bottom = top - 10;
13016 
13017   DrawUpdateAlignmentBits (pict, top, bottom, 1, ualp->old5 + 1,
13018                            ualp->old5 + ualp->olda, salp, indels);
13019 
13020   top = 30;
13021   bottom = top - 10;
13022 
13023   if (revcomp) {
13024     DrawUpdateAlignmentBits (pict, top, bottom, 2, ualp->new3 + ualp->newa,
13025                              ualp->new3 + 1, salp, indels);
13026   } else {
13027     DrawUpdateAlignmentBits (pict, top, bottom, 2, ualp->new5 + 1,
13028                              ualp->new5 + ualp->newa, salp, indels);
13029   }
13030 
13031   top = 15;
13032   bottom = top - 10;
13033 
13034   DrawUpdateAlignmentDiffs (pict, top, bottom, salp, orig_bsp, update_bsp, mismatches);
13035 
13036   return pict;
13037 }
13038 
13039 
13040 
CalculateBestUpdateAlignmentViewerScale(VieweR vwr,SegmenT pict)13041 static Int4 CalculateBestUpdateAlignmentViewerScale (VieweR vwr, SegmenT pict)
13042 
13043 {
13044   BoxInfo  box;
13045   Int2     i;
13046   Int4     max, worldwid, portwid;
13047   RecT     r;
13048   Int4     scaleX, oldscaleX;
13049   Int4     wid;
13050 
13051   ObjectRect (vwr, &r);
13052   InsetRect (&r, 4, 4);
13053   wid = (Int4) (r.right - r.left + 1);
13054 
13055   SegmentBox (pict, &box);
13056   oldscaleX = (box.right - box.left + wid - 1) / wid;
13057   RecalculateSegment (pict, oldscaleX, 1);
13058   SegmentBox (pict, &box);
13059   portwid = wid * oldscaleX;
13060   worldwid = box.right - box.left + 20 * oldscaleX + 1;
13061   max = MAX (worldwid, portwid);
13062   scaleX = (max + wid - 1) / wid;
13063   i = 0;
13064   while (i < 10 && (scaleX > oldscaleX || portwid < worldwid)) {
13065     oldscaleX = scaleX;
13066     RecalculateSegment (pict, oldscaleX, 1);
13067     SegmentBox (pict, &box);
13068     portwid = wid * oldscaleX;
13069     worldwid = box.right - box.left + 20 * oldscaleX + 1;
13070     max = MAX (worldwid, portwid);
13071     scaleX = (max + wid - 1) / wid;
13072     i++;
13073   }
13074 
13075   return scaleX;
13076 }
13077 
MakeUpdateAlignmentSequenceString(SeqAlignPtr sap,Int4 aln_length,Int4 row,CharPtr seq)13078 static CharPtr MakeUpdateAlignmentSequenceString
13079 ( SeqAlignPtr sap,
13080   Int4        aln_length,
13081   Int4        row,
13082   CharPtr     seq)
13083 
13084 {
13085   CharPtr    aln;
13086   AlnMsg2Ptr  amp;
13087   Int4       len, lens, start, stop, from, to, i, j;
13088 
13089   if (sap == NULL || seq == NULL || aln_length < 1) return NULL;
13090   lens = StringLen (seq);
13091 
13092   aln = (CharPtr) MemNew (sizeof (Char) * (aln_length + 2));
13093   if (aln == NULL) return NULL;
13094   MemSet ((Pointer) aln, '-', aln_length);
13095 
13096   amp = AlnMsgNew2 ();
13097   if (amp == NULL) return aln;
13098 
13099   amp->from_aln = 0;
13100   amp->to_aln = -1;
13101   amp->row_num = row;
13102 
13103   start = 0;
13104   stop = 0;
13105   from = 0;
13106   to = 0;
13107 
13108   while (AlnMgr2GetNextAlnBit (sap, amp)) {
13109     len = amp->to_row - amp->from_row + 1;
13110     stop = start + len;
13111 
13112     if (amp->type == AM_SEQ) {
13113       for (i = start, j = amp->from_row; i < stop && j < lens; i++, j++) {
13114         aln [i] = seq [j];
13115       }
13116     }
13117     start += len;
13118   }
13119 
13120   AlnMsgFree2 (amp);
13121 
13122   return aln;
13123 }
13124 
13125 /* The alignment letters panel draws the individual letters of the sequence, showing
13126  * insertions, deletions, and mismatches.
13127  */
13128 typedef struct alignmentletterspanel
13129 {
13130   DIALOG_MESSAGE_BLOCK
13131   PaneL letters;
13132 
13133   Int4    lineheight;       /* height of lines in the letters panel */
13134   Int4    charwidth;        /* width of characters in the letters panel */
13135   Int4    maxchars;         /* maximum number of characters that can be
13136                              * displayed in the letters panel.
13137                              */
13138 
13139   UpdateAlignmentLengthsData uald; /* structure that holds the length of the alignment,
13140                                     * the lengths of the 3' and 5' overlaps, etc.
13141                                     */
13142   CharPtr            aln1;       /* holds the string representation of the alignment
13143                                   * for the original sequence
13144                                   */
13145   CharPtr            aln2;       /* holds the string representation of the alignment
13146                                   * for the update sequence
13147                                   */
13148 
13149   SeqAlignPtr        salp;       /* alignment used for update */
13150                                  /* This alignment should not be freed by this panel.
13151                                   */
13152   Boolean            revcomp;
13153 } AlignmentLettersPanelData, PNTR AlignmentLettersPanelPtr;
13154 
13155 static void
PaintAlignmentString(CharPtr aln_str,Int4 char_offset,Int4 char_width,Int4 left_pos,Int4 top_pos,Int4 right_pos,Int4 maxchars,Int4 aln_length)13156 PaintAlignmentString
13157 (CharPtr aln_str,
13158  Int4    char_offset,
13159  Int4    char_width,
13160  Int4    left_pos,
13161  Int4    top_pos,
13162  Int4    right_pos,
13163  Int4    maxchars,
13164  Int4    aln_length)
13165 {
13166   Int2 i;
13167   Int4 j;
13168   Int4 pos_offset;
13169 
13170   if (aln_str != NULL)
13171   {
13172     MoveTo (left_pos, top_pos);
13173     pos_offset = left_pos;
13174     for (i = 0, j = char_offset, pos_offset = left_pos;
13175          i < maxchars && j < aln_length && pos_offset + char_width <= right_pos;
13176          i++, j++, pos_offset += char_width) {
13177       PaintChar (aln_str [j]);
13178     }
13179   }
13180 
13181 }
13182 
13183 
UpdateAlignmentLettersPanelOnDraw(PaneL pnl)13184 static void UpdateAlignmentLettersPanelOnDraw (PaneL pnl)
13185 
13186 {
13187   Char        ch1, ch2;
13188   Int2        i, k, q, left, top, bottom, arrowwidth;
13189   size_t      len;
13190   Int4        offset, j, pos, realpos;
13191   RecT        r, x;
13192   BaR         sb;
13193   Char        str [32];
13194   AlignmentLettersPanelPtr  dlg;
13195 
13196   dlg = (AlignmentLettersPanelPtr) GetObjectExtra (pnl);
13197   if (dlg == NULL) return;
13198 
13199   ObjectRect (pnl, &r);
13200   InsetRect (&r, 4, 4);
13201 
13202   sb = GetSlateHScrollBar ((SlatE) pnl);
13203   offset = GetBarValue (sb);
13204 
13205   SelectFont (SetSmallFont ());
13206 
13207   /* draw top (new) letters */
13208 
13209   PaintAlignmentString (dlg->aln2, offset, dlg->charwidth,
13210                         r.left, r.top + 8 + 3 * dlg->lineheight,
13211                         r.right,
13212                         dlg->maxchars,
13213                         dlg->uald.aln_length);
13214 
13215   /* draw bottom (old) letters */
13216 
13217   PaintAlignmentString (dlg->aln1, offset, dlg->charwidth,
13218                         r.left, r.top + 8 + 5 * dlg->lineheight,
13219                         r.right,
13220                         dlg->maxchars,
13221                         dlg->uald.aln_length);
13222 
13223   /* draw recombination arrows */
13224 
13225   arrowwidth = MIN (6, dlg->charwidth);
13226   if (dlg->uald.recomb1 >= offset && dlg->uald.recomb1 <= offset + dlg->maxchars) {
13227     left = r.left + dlg->charwidth * (dlg->uald.recomb1 - offset);
13228     LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
13229     CopyBits (&x, leftTriFillSym);
13230   }
13231 
13232   if (dlg->uald.recomb2 >= offset && dlg->uald.recomb2 <= offset + dlg->maxchars) {
13233     left = r.left + dlg->charwidth * (dlg->uald.recomb2 - offset - 1);
13234     LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
13235     CopyBits (&x, rightTriFillSym);
13236   }
13237 
13238   if (dlg->aln1 == NULL || dlg->aln2 == NULL)
13239   {
13240   	return;
13241   }
13242   /* draw red mismatch lines */
13243 
13244   Red ();
13245   top = r.top + 8 + 4 * dlg->lineheight - Ascent ();
13246   bottom = top + dlg->lineheight - 2;
13247 
13248   for (i = 0, j = offset; i < dlg->maxchars && j < dlg->uald.aln_length; i++, j++) {
13249     ch1 = dlg->aln1 [j];
13250     ch2 = dlg->aln2 [j];
13251     if (ch1 == ch2) {
13252     } else if (ch1 == '-' || ch2 == '-') {
13253     } else {
13254       left = r.left + i * dlg->charwidth + dlg->charwidth / 2 - 1;
13255       MoveTo (left, top);
13256       LineTo (left, bottom);
13257     }
13258   }
13259   Black ();
13260 
13261   /* draw top (new) tick marks and coordinates */
13262 
13263   bottom = r.top + 8 + 3 * dlg->lineheight - Ascent () - 2;
13264   top = bottom - 5;
13265   i = 0;
13266   j = offset;
13267   pos = AlnMgr2MapSeqAlignToBioseq (dlg->salp, j, 2);
13268   while (pos < 1 && i < dlg->maxchars && j < dlg->uald.aln_length) {
13269     i++;
13270     j++;
13271     pos = AlnMgr2MapSeqAlignToBioseq (dlg->salp, j, 2);
13272   }
13273   for (; i < dlg->maxchars + dlg->uald.log10_aln_length && j < dlg->uald.aln_length; i++, j++) {
13274     ch1 = dlg->aln2 [j];
13275     if (ch1 != '-') {
13276       if (dlg->revcomp) {
13277         realpos = (dlg->uald.new5 + dlg->uald.newa + dlg->uald.new3 - pos - 1);
13278       } else {
13279         realpos = pos;
13280       }
13281       if (((realpos + 1) % 10) == 0) {
13282         left = r.left + i * dlg->charwidth + dlg->charwidth / 2 - 1;
13283         if (i < dlg->maxchars && left <= r.right - dlg->charwidth) {
13284           MoveTo (left, top);
13285           LineTo (left, bottom);
13286         }
13287         sprintf (str, "%ld", (long) (realpos + 1));
13288         len = StringLen (str);
13289         if (len <= j + 1) {
13290           k = i - len + 1;
13291           q = 0;
13292           if (k < 0) {
13293             q -= k;
13294             k = 0;
13295           }
13296           if (q < len) {
13297             left = r.left + k * dlg->charwidth;
13298             MoveTo (left, r.top + 8 + dlg->lineheight);
13299             while (k < dlg->maxchars && q < len && left <= r.right - dlg->charwidth) {
13300               PaintChar (str [q]);
13301               k++;
13302               q++;
13303               left += dlg->charwidth;
13304             }
13305           }
13306         }
13307       } else if (((realpos + 1) % 5) == 0) {
13308         left = r.left + i * dlg->charwidth + dlg->charwidth / 2 - 1;
13309         if (i < dlg->maxchars && left <= r.right - dlg->charwidth) {
13310           MoveTo (left, top + 3);
13311           LineTo (left, bottom);
13312         }
13313       }
13314       pos++;
13315     }
13316   }
13317 
13318   /* draw bottom (old) tick marks and coordinates */
13319 
13320   top = r.top + 8 + 6 * dlg->lineheight - Ascent () + 2;
13321   bottom = top + 5;
13322   i = 0;
13323   j = offset;
13324   pos = AlnMgr2MapSeqAlignToBioseq (dlg->salp, j, 1);
13325   while (pos < 1 && i < dlg->maxchars && j < dlg->uald.aln_length) {
13326     i++;
13327     j++;
13328     pos = AlnMgr2MapSeqAlignToBioseq (dlg->salp, j, 1);
13329   }
13330   for (; i < dlg->maxchars + dlg->uald.log10_aln_length && j < dlg->uald.aln_length; i++, j++) {
13331     ch1 = dlg->aln1 [j];
13332     if (ch1 != '-') {
13333       if (((pos + 1) % 10) == 0) {
13334         left = r.left + i * dlg->charwidth + dlg->charwidth / 2 - 1;
13335         if (i < dlg->maxchars && left <= r.right - dlg->charwidth) {
13336           MoveTo (left, top);
13337           LineTo (left, bottom);
13338         }
13339         sprintf (str, "%ld", (long) (pos + 1));
13340         len = StringLen (str);
13341         if (len <= j + 1) {
13342           k = i - len + 1;
13343           q = 0;
13344           if (k < 0) {
13345             q -= k;
13346             k = 0;
13347           }
13348           if (q < len) {
13349             left = r.left + k * dlg->charwidth;
13350             MoveTo (left, r.top + 8 + 7 * dlg->lineheight);
13351             while (k < dlg->maxchars && q < len && left <= r.right - dlg->charwidth) {
13352               PaintChar (str [q]);
13353               k++;
13354               q++;
13355               left += dlg->charwidth;
13356             }
13357           }
13358         }
13359       } else if (((pos + 1) % 5) == 0) {
13360         left = r.left + i * dlg->charwidth + dlg->charwidth / 2 - 1;
13361         if (i < dlg->maxchars && left <= r.right - dlg->charwidth) {
13362           MoveTo (left, top);
13363           LineTo (left, bottom - 3);
13364         }
13365       }
13366       pos++;
13367     }
13368   }
13369   SelectFont (systemFont);
13370 }
13371 
UpdateAlignmentLettersPanelOnScroll(BaR sb,SlatE slt,Int4 newval,Int4 oldval)13372 static void UpdateAlignmentLettersPanelOnScroll (
13373   BaR sb,
13374   SlatE slt,
13375   Int4 newval,
13376   Int4 oldval
13377 )
13378 
13379 {
13380   RecT                    r;
13381   AlignmentLettersPanelPtr  dlg;
13382   Int4                      scroll_distance;
13383 
13384   dlg = (AlignmentLettersPanelPtr) GetObjectExtra (slt);
13385   if (dlg == NULL) return;
13386 
13387   ObjectRect (dlg->letters, &r);
13388   InsetRect (&r, 4, 4);
13389   Select (dlg->letters);
13390   if (ABS (oldval - newval) < dlg->maxchars) {
13391     scroll_distance = (oldval - newval) * dlg->charwidth;
13392     ScrollRect (&r, scroll_distance, 0);
13393     if (scroll_distance > 0)
13394     {
13395       r.left += scroll_distance;
13396       r.right = r.left + dlg->charwidth;
13397     }
13398     else
13399     {
13400       r.right += scroll_distance;
13401       r.left = r.right - dlg->charwidth;
13402     }
13403     InvalRect (&r);
13404   } else {
13405     InsetRect (&r, -2, -2);
13406     InvalRect (&r);
13407   }
13408   Update ();
13409 }
13410 
UpdatePairToAlignmentLettersPanel(DialoG d,Pointer data)13411 static void UpdatePairToAlignmentLettersPanel (DialoG d, Pointer data)
13412 {
13413   AlignmentLettersPanelPtr  dlg;
13414   UpdatePairPtr             upp;
13415   CharPtr                   seq_orig, seq_update;
13416   BaR                       sb;
13417   RecT                      r;
13418 
13419   dlg = (AlignmentLettersPanelPtr) GetObjectExtra (d);
13420   if (dlg == NULL)
13421   {
13422     return;
13423   }
13424 
13425   dlg->aln1 = MemFree (dlg->aln1);
13426   dlg->aln2 = MemFree (dlg->aln2);
13427   dlg->salp = NULL;
13428   dlg->revcomp = FALSE;
13429   dlg->salp = NULL;
13430   MemSet (&(dlg->uald), 0, sizeof (UpdateAlignmentLengthsData));
13431 
13432   upp = (UpdatePairPtr) data;
13433   if (upp != NULL && upp->salp != NULL)
13434   {
13435     dlg->salp = upp->salp;
13436     dlg->revcomp = upp->revcomp;
13437 
13438     CalculateUpdateAlignmentLengths (upp->salp, upp->orig_bsp, upp->update_bsp, &(dlg->uald));
13439 
13440     /* create alignment string for original */
13441     seq_orig = GetSequenceByBsp (upp->orig_bsp);
13442     dlg->aln1 = MakeUpdateAlignmentSequenceString (upp->salp, dlg->uald.aln_length,
13443                                                  1, seq_orig);
13444     seq_orig = MemFree (seq_orig);
13445 
13446     /* create alignment string for update */
13447     seq_update = GetSequenceByBsp (upp->update_bsp);
13448     dlg->aln2 = MakeUpdateAlignmentSequenceString (upp->salp, dlg->uald.aln_length,
13449                                                  2, seq_update);
13450     seq_update = MemFree (seq_update);
13451 
13452     sb = GetSlateHScrollBar ((SlatE) dlg->letters);
13453     SetBarMax (sb, dlg->uald.aln_length - (Int4) dlg->maxchars);
13454     CorrectBarPage (sb, (Int4) dlg->maxchars - 1, (Int4) dlg->maxchars - 1);
13455   }
13456 
13457   ObjectRect (dlg->letters, &r);
13458   InvalRect (&r);
13459 
13460 }
13461 
AlignmentLettersPanel(GrouP parent,Int4 prompt_width,Int4 hgt)13462 static DialoG AlignmentLettersPanel (GrouP parent, Int4 prompt_width, Int4 hgt)
13463 {
13464   AlignmentLettersPanelPtr  dlg;
13465   GrouP                     p;
13466   RecT                      r;
13467 
13468   dlg = (AlignmentLettersPanelPtr) MemNew (sizeof (AlignmentLettersPanelData));
13469   if (dlg == NULL)
13470   {
13471     return NULL;
13472   }
13473 
13474   p = HiddenGroup (parent, 1, 0, NULL);
13475   SetObjectExtra (p, dlg, StdCleanupExtraProc);
13476   dlg->dialog = (DialoG) p;
13477   dlg->todialog = UpdatePairToAlignmentLettersPanel;
13478 
13479   dlg->aln1 = NULL;
13480   dlg->aln2 = NULL;
13481   dlg->salp = NULL;
13482   dlg->revcomp = FALSE;
13483   MemSet (&(dlg->uald), 0, sizeof (UpdateAlignmentLengthsData));
13484 
13485   dlg->letters = AutonomousPanel4 (p, prompt_width + Nlm_vScrollBarWidth, hgt,
13486                                    UpdateAlignmentLettersPanelOnDraw,
13487 				                           NULL, UpdateAlignmentLettersPanelOnScroll, 0, NULL, NULL);
13488   SetObjectExtra (dlg->letters, (Pointer) dlg, NULL);
13489 
13490   SelectFont (SetSmallFont ());
13491   ObjectRect (dlg->letters, &r);
13492   InsetRect (&r, 4, 4);
13493   dlg->lineheight = LineHeight ();
13494   dlg->charwidth = MaxCharWidth ();
13495   dlg->maxchars = (r.right-r.left-2+dlg->charwidth - 1) / dlg->charwidth;
13496   SelectFont (systemFont);
13497   return (DialoG) p;
13498 }
13499 
GetAlignmentLettersPanelMaxchars(DialoG d)13500 static Int4 GetAlignmentLettersPanelMaxchars (DialoG d)
13501 {
13502   AlignmentLettersPanelPtr  dlg;
13503 
13504   dlg = (AlignmentLettersPanelPtr) GetObjectExtra (d);
13505   if (dlg == NULL)
13506   {
13507     return 0;
13508   }
13509   else
13510   {
13511     return dlg->maxchars;
13512   }
13513 }
13514 
GetAlignmentLettersScrollPosition(DialoG d)13515 static Int4 GetAlignmentLettersScrollPosition (DialoG d)
13516 {
13517   AlignmentLettersPanelPtr  dlg;
13518   BaR                       sb;
13519 
13520   dlg = (AlignmentLettersPanelPtr) GetObjectExtra (d);
13521   if (dlg == NULL)
13522   {
13523     return 0;
13524   }
13525 
13526   sb = GetSlateHScrollBar ((SlatE) dlg->letters);
13527 
13528   return GetBarValue (sb);
13529 }
13530 
ScrollAlignmentLettersPanel(DialoG d,Int4 pos)13531 static void ScrollAlignmentLettersPanel (DialoG d, Int4 pos)
13532 {
13533   AlignmentLettersPanelPtr  dlg;
13534   BaR                       sb;
13535 
13536   dlg = (AlignmentLettersPanelPtr) GetObjectExtra (d);
13537   if (dlg == NULL)
13538   {
13539     return;
13540   }
13541 
13542   sb = GetSlateHScrollBar ((SlatE) dlg->letters);
13543 
13544   SetBarValue (sb, pos);
13545 }
13546 
13547 typedef struct updatetitlesdialog
13548 {
13549   DIALOG_MESSAGE_BLOCK
13550 
13551   PrompT  new_sequence_id_ppt; /* indicate which sequence is being used for the update */
13552   PrompT  new_sequence_length_ppt;
13553   PrompT  old_sequence_id_ppt; /* indicates which sequence is being updated */
13554   PrompT  old_sequence_length_ppt;
13555 
13556   BioseqPtr          orig_bsp;   /* original bioseq */
13557   BioseqPtr          update_bsp; /* update bioseq */
13558   Uint2              entityID_orig;
13559   Uint2              entityID_update;
13560   Boolean            is_indexer;
13561   Boolean            is_update;
13562 } UpdateTitlesDialogData, PNTR UpdateTitlesDialogPtr;
13563 
UpdatePairFromUpdateTitlesDialog(DialoG d)13564 static Pointer UpdatePairFromUpdateTitlesDialog (DialoG d)
13565 {
13566   UpdateTitlesDialogPtr dlg;
13567   UpdatePairPtr          upp;
13568 
13569   dlg = (UpdateTitlesDialogPtr) GetObjectExtra (d);
13570   if (dlg == NULL)
13571   {
13572     return NULL;
13573   }
13574 
13575   upp = (UpdatePairPtr) MemNew (sizeof (UpdatePairData));
13576   if (upp != NULL)
13577   {
13578     upp->orig_bsp = dlg->orig_bsp;
13579     upp->update_bsp = dlg->update_bsp;
13580     upp->revcomp = FALSE;
13581     upp->salp = NULL;
13582   }
13583 
13584   return upp;
13585 }
13586 
UpdatePairToUpdateTitlesDialog(DialoG d,Pointer data)13587 static void UpdatePairToUpdateTitlesDialog (DialoG d, Pointer data)
13588 {
13589   UpdateTitlesDialogPtr dlg;
13590   UpdatePairPtr         upp;
13591   Char                  ppt_txt [500];
13592   Char                  id_txt [MAX_ID_LEN];
13593 
13594   dlg = (UpdateTitlesDialogPtr) GetObjectExtra (d);
13595   if (dlg == NULL)
13596   {
13597     return;
13598   }
13599 
13600   dlg->orig_bsp = NULL;
13601   dlg->update_bsp = NULL;
13602 
13603   upp = (UpdatePairPtr) data;
13604 
13605   if (upp == NULL)
13606   {
13607     SafeHide (dlg->new_sequence_id_ppt);
13608     SafeHide (dlg->new_sequence_length_ppt);
13609     SafeHide (dlg->old_sequence_id_ppt);
13610     SafeHide (dlg->old_sequence_length_ppt);
13611     return;
13612   }
13613 
13614   dlg->orig_bsp = upp->orig_bsp;
13615   dlg->update_bsp = upp->update_bsp;
13616 
13617   if (upp->orig_bsp == NULL)
13618   {
13619     SafeHide (dlg->new_sequence_id_ppt);
13620     SafeHide (dlg->new_sequence_length_ppt);
13621     SafeHide (dlg->old_sequence_id_ppt);
13622     SafeHide (dlg->old_sequence_length_ppt);
13623   }
13624   /* show no update message */
13625   else if (upp->update_bsp == NULL)
13626   {
13627     SeqIdWrite (SeqIdFindBest (upp->orig_bsp->id, SEQID_GENBANK), id_txt,
13628                 PRINTID_REPORT, sizeof (id_txt) - 50);
13629     if (dlg->is_indexer)
13630     {
13631       sprintf (ppt_txt, "No update sequence for %s", id_txt);
13632       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
13633       sprintf (ppt_txt, "Length %ld", (long) upp->orig_bsp->length);
13634       SetTitle (dlg->new_sequence_length_ppt, ppt_txt);
13635     }
13636     else
13637     {
13638       sprintf (ppt_txt, "No update sequence for %s (length %ld)",
13639                id_txt, (long) upp->orig_bsp->length);
13640       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
13641     }
13642     SafeHide (dlg->old_sequence_id_ppt);
13643     SafeHide (dlg->old_sequence_length_ppt);
13644   }
13645   /* show no alignment message */
13646   else if (upp->salp == NULL && dlg->is_update)
13647   {
13648     SeqIdWrite (SeqIdFindBest (upp->orig_bsp->id, SEQID_GENBANK), id_txt,
13649                 PRINTID_REPORT, sizeof (id_txt));
13650     if (dlg->is_indexer)
13651     {
13652       sprintf (ppt_txt, "No alignment for %s", id_txt);
13653       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
13654       sprintf (ppt_txt, "Length: %ld", (long) dlg->orig_bsp->length);
13655       SetTitle (dlg->new_sequence_length_ppt, ppt_txt);
13656     }
13657     else
13658     {
13659       sprintf (ppt_txt, "No alignment for %s Length: %ld", id_txt, (long) dlg->orig_bsp->length);
13660       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
13661     }
13662     SafeHide (dlg->old_sequence_id_ppt);
13663     SafeHide (dlg->old_sequence_length_ppt);
13664   }
13665   else
13666   {
13667     /* update sequence title prompts */
13668     SeqIdWrite (SeqIdFindBest (dlg->update_bsp->id, SEQID_GENBANK), id_txt,
13669                                PRINTID_REPORT, sizeof (id_txt));
13670     if (dlg->is_indexer)
13671     {
13672       sprintf (ppt_txt, "New sequence: %s", id_txt);
13673       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
13674       sprintf (ppt_txt, "Length: %ld", (long) dlg->update_bsp->length);
13675       SetTitle (dlg->new_sequence_length_ppt, ppt_txt);
13676     }
13677     else
13678     {
13679       sprintf (ppt_txt, "New sequence: %s Length: %ld", id_txt, (long) dlg->update_bsp->length);
13680       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
13681     }
13682 
13683     SeqIdWrite (SeqIdFindBest (dlg->orig_bsp->id, SEQID_GENBANK), id_txt,
13684                                PRINTID_REPORT, sizeof (id_txt));
13685     if (dlg->is_indexer)
13686     {
13687       sprintf (ppt_txt, "Old sequence: %s", id_txt);
13688       SetTitle (dlg->old_sequence_id_ppt, ppt_txt);
13689       sprintf (ppt_txt, "Length: %ld", (long) dlg->orig_bsp->length);
13690       SetTitle (dlg->old_sequence_length_ppt, ppt_txt);
13691     }
13692     else
13693     {
13694       sprintf (ppt_txt, "Old sequence: %s Length: %ld", id_txt, (long) dlg->orig_bsp->length);
13695       SetTitle (dlg->old_sequence_id_ppt, ppt_txt);
13696     }
13697 
13698     SafeShow (dlg->new_sequence_id_ppt);
13699     SafeShow (dlg->new_sequence_length_ppt);
13700     SafeShow (dlg->old_sequence_id_ppt);
13701     SafeShow (dlg->old_sequence_length_ppt);
13702   }
13703 }
13704 
UpdateTitlesDialog(GrouP parent,Boolean is_indexer,Boolean is_update)13705 static DialoG UpdateTitlesDialog (GrouP parent, Boolean is_indexer, Boolean is_update)
13706 {
13707   UpdateTitlesDialogPtr dlg;
13708   GrouP                 p;
13709   Int4                  prompt_width = 450;
13710 
13711   dlg = (UpdateTitlesDialogPtr) MemNew (sizeof (UpdateTitlesDialogData));
13712   if (dlg == NULL)
13713   {
13714     return NULL;
13715   }
13716 
13717   p = HiddenGroup (parent, -1, 0, NULL);
13718   SetObjectExtra (p, dlg, StdCleanupExtraProc);
13719   SetGroupSpacing (p, 2, 2);
13720 
13721   dlg->dialog = (DialoG) p;
13722 
13723   dlg->todialog = UpdatePairToUpdateTitlesDialog;
13724   dlg->fromdialog = UpdatePairFromUpdateTitlesDialog;
13725 
13726   dlg->is_indexer = is_indexer;
13727   dlg->is_update = is_update;
13728 
13729   if (is_indexer)
13730   {
13731     prompt_width = 400;
13732   }
13733   else
13734   {
13735     prompt_width = 550;
13736   }
13737 
13738   dlg->new_sequence_id_ppt = StaticPrompt (p, "", prompt_width,
13739                                            dialogTextHeight, programFont, 'l');
13740   if (is_indexer)
13741   {
13742     dlg->new_sequence_length_ppt = StaticPrompt (p, "", prompt_width,
13743                                                  dialogTextHeight, programFont, 'l');
13744   }
13745   else
13746   {
13747     dlg->new_sequence_length_ppt = NULL;
13748   }
13749 
13750   dlg->old_sequence_id_ppt = StaticPrompt (p, "", prompt_width, dialogTextHeight, programFont, 'l');
13751   if (is_indexer)
13752   {
13753     dlg->old_sequence_length_ppt = StaticPrompt (p, "", prompt_width,
13754                                                  dialogTextHeight, programFont, 'l');
13755   }
13756 
13757   return (DialoG) p;
13758 }
13759 
13760 typedef struct updatepreviewdialog
13761 {
13762   DIALOG_MESSAGE_BLOCK
13763 
13764   GrouP   viewer_grp;       /* group that contains viewers and prompts
13765                              * this group is hidden when there is no alignment
13766                              */
13767   VieweR  overview;       /* shows sequence lengths/overlap */
13768   GrouP   details_grp;
13769   VieweR  details;        /* shows individual mismatches/deletions/insertions */
13770   GrouP   letters_grp;
13771   DialoG  letters_dlg;      /* shows sequence and gap characters and coordinates */
13772 
13773   SegmenT overview_picture; /* picture of sequence lengths/overlap */
13774   SegmenT details_picture;  /* picture of mismatches/deletions/insertions */
13775   Int4    details_scaleX;   /* scale at which the details picture is displayed */
13776 
13777   UpdateAlignmentLengthsData uald; /* structure that holds the length of the alignment,
13778                                     * the lengths of the 3' and 5' overlaps, etc.
13779                                     */
13780   ValNodePtr         indels;     /* ValNode structure that holds the positions
13781                                   * of insertions and deletions (in alignment
13782                                   * coordinates)
13783                                   */
13784   ValNodePtr         mismatches; /* ValNode structure that holds the positions
13785                                   * of mismatches (in alignment coordinates)
13786                                   */
13787 
13788   SeqAlignPtr        salp;       /* alignment used for update */
13789                                  /* The UpdatePreviewDialog is responsible for freeing
13790                                   * the alignment passed to it.
13791                                   */
13792   BioseqPtr          orig_bsp;   /* original bioseq */
13793   BioseqPtr          update_bsp; /* update bioseq */
13794   Uint2              entityID_orig;
13795   Uint2              entityID_update;
13796   Boolean            revcomp;
13797 
13798   Boolean            ignore_alignment;
13799   Boolean            extend5;
13800 } UpdatePreviewDialogData, PNTR UpdatePreviewDialogPtr;
13801 
13802 /* if the user clicks on the details picture, scroll to the appropriate position
13803  * in the letters panel.
13804  */
UpdateAlignmentDetailsOnClick(VieweR vwr,SegmenT pict,PoinT pt)13805 static void UpdateAlignmentDetailsOnClick (VieweR vwr, SegmenT pict, PoinT pt)
13806 
13807 {
13808   Int4                   goHere;
13809   Int4                   offset;
13810   Int4                   maxchars;
13811   Int4                   maxover2;
13812   PntInfo                pnt;
13813   UpdatePreviewDialogPtr dlg;
13814   ValNodePtr             vnp;
13815 
13816   dlg = (UpdatePreviewDialogPtr) GetViewerData (vwr);
13817   if (dlg == NULL) return;
13818 
13819   MapViewerToWorld (vwr, pt, &pnt);
13820   maxchars = GetAlignmentLettersPanelMaxchars (dlg->letters_dlg);
13821   maxover2 = maxchars / 2;
13822   if (pnt.x <= 0) {
13823     pnt.x = 0;
13824   } else if (pnt.x >= dlg->uald.aln_length) {
13825     pnt.x = dlg->uald.aln_length  - maxchars;
13826   } else if (pnt.x >= maxover2) {
13827 
13828     offset = GetAlignmentLettersScrollPosition (dlg->letters_dlg);
13829 
13830     /* look for clicks within 5 pixels of an indel start or a mismatch */
13831 
13832     goHere = -1;
13833     for (vnp = dlg->indels; vnp != NULL && goHere < 0; vnp = vnp->next) {
13834       if (ABS (pnt.x - vnp->data.intvalue) < dlg->details_scaleX * 5) {
13835         goHere = vnp->data.intvalue;
13836       }
13837     }
13838     for (vnp = dlg->mismatches; vnp != NULL && goHere < 0; vnp = vnp->next) {
13839       if (ABS (pnt.x - vnp->data.intvalue) < dlg->details_scaleX * 5) {
13840         goHere = vnp->data.intvalue;
13841       }
13842     }
13843 
13844     if (goHere >= 0) {
13845       pnt.x = goHere;
13846     } else {
13847       /* if already visible, no need to scroll */
13848       if (pnt.x - maxover2 > offset && pnt.x - maxover2 < offset + maxover2 - 5) return;
13849       if (pnt.x - maxover2 < offset && pnt.x - maxover2 > offset - maxover2 + 5) return;
13850     }
13851 
13852     /* go left 1/2 screen so desired point is in the middle */
13853 
13854     pnt.x -= maxover2;
13855   }
13856 
13857   ResetClip ();
13858   ScrollAlignmentLettersPanel (dlg->letters_dlg, pnt.x);
13859   Update ();
13860 }
13861 
UpdatePairFromUpdatePreviewDialog(DialoG d)13862 static Pointer UpdatePairFromUpdatePreviewDialog (DialoG d)
13863 {
13864   UpdatePreviewDialogPtr dlg;
13865   UpdatePairPtr          upp;
13866 
13867   dlg = (UpdatePreviewDialogPtr) GetObjectExtra (d);
13868   if (dlg == NULL)
13869   {
13870     return NULL;
13871   }
13872 
13873   upp = (UpdatePairPtr) MemNew (sizeof (UpdatePairData));
13874   if (upp != NULL)
13875   {
13876     upp->orig_bsp = dlg->orig_bsp;
13877     upp->update_bsp = dlg->update_bsp;
13878     upp->revcomp = dlg->revcomp;
13879     upp->salp = dlg->salp;
13880   }
13881 
13882   return upp;
13883 }
13884 
RedrawAlignmentPreview(DialoG d)13885 static void RedrawAlignmentPreview (DialoG d)
13886 {
13887   UpdatePreviewDialogPtr dlg;
13888   UpdatePairData         upd;
13889   Int4                   scaleX;
13890 
13891   dlg = (UpdatePreviewDialogPtr) GetObjectExtra (d);
13892   if (dlg == NULL)
13893   {
13894     return;
13895   }
13896 
13897   upd.orig_bsp = dlg->orig_bsp;
13898   upd.update_bsp = dlg->update_bsp;
13899   upd.salp = dlg->salp;
13900   upd.revcomp = dlg->revcomp;
13901 
13902   /* reverse the sequence for drawing purposes */
13903   if (upd.revcomp)
13904   {
13905     BioseqRevComp (upd.update_bsp);
13906     ReverseBioseqFeatureStrands (upd.update_bsp);
13907     SeqMgrReplaceInBioseqIndex (upd.update_bsp);
13908   }
13909 
13910   if (dlg->salp == NULL
13911       || dlg->orig_bsp == NULL
13912       || dlg->update_bsp == NULL)
13913   {
13914     dlg->overview_picture = CreatePicture ();
13915     AttachPicture (dlg->overview, dlg->overview_picture, 0, 0, UPPER_LEFT,
13916 		               1, 1, FrameVwr);
13917     dlg->details_picture = CreatePicture ();
13918     AttachPicture (dlg->details, dlg->details_picture, 0, 0, UPPER_LEFT,
13919 		               1, 1, FrameVwr);
13920     MemSet (&(dlg->uald), 0, sizeof (UpdateAlignmentLengthsData));
13921 
13922     PointerToDialog (dlg->letters_dlg, NULL);
13923 
13924     Hide (dlg->viewer_grp);
13925     /* reverse the sequence for drawing purposes */
13926     if (upd.revcomp)
13927     {
13928       BioseqRevComp (upd.update_bsp);
13929       ReverseBioseqFeatureStrands (upd.update_bsp);
13930       SeqMgrReplaceInBioseqIndex (upd.update_bsp);
13931     }
13932 
13933     return;
13934   }
13935 
13936   CalculateUpdateAlignmentLengths (dlg->salp, dlg->orig_bsp, dlg->update_bsp, &(dlg->uald));
13937 
13938   if (dlg->ignore_alignment)
13939   {
13940     dlg->overview_picture = MakeExtensionPicture (dlg->orig_bsp->length, dlg->update_bsp->length, dlg->extend5);
13941   }
13942   else
13943   {
13944     dlg->overview_picture = MakeAlignmentOverviewPicture (&(dlg->uald));
13945   }
13946 
13947   scaleX = CalculateBestUpdateAlignmentViewerScale (dlg->overview, dlg->overview_picture);
13948   AttachPicture (dlg->overview, dlg->overview_picture, 0, 0, UPPER_LEFT,
13949 		             scaleX, 1, FrameVwr);
13950 
13951   dlg->indels = ValNodeFree (dlg->indels);
13952   dlg->details_picture = MakeAlignmentDetailsPicture (dlg->salp,
13953                                                       dlg->orig_bsp,
13954                                                       dlg->update_bsp,
13955                                                       &(dlg->indels),
13956                                                       &(dlg->mismatches),
13957                                                       &(dlg->uald), dlg->revcomp);
13958   dlg->details_scaleX = CalculateBestUpdateAlignmentViewerScale (dlg->details, dlg->details_picture);
13959   AttachPicture (dlg->details, dlg->details_picture, 0, 0, UPPER_LEFT,
13960 		             dlg->details_scaleX, 1, FrameVwr);
13961   SetViewerData (dlg->details, (Pointer) dlg, NULL);
13962   SetViewerProcs (dlg->details, UpdateAlignmentDetailsOnClick, NULL, NULL, NULL);
13963 
13964   /* sort the insertions and deletions so they will be in order */
13965   dlg->indels = ValNodeSort (dlg->indels, SortVnpByInt);
13966   /* sort the matches so that they will be in order */
13967   dlg->mismatches = ValNodeSort (dlg->mismatches, SortVnpByInt);
13968 
13969   PointerToDialog (dlg->letters_dlg, &upd);
13970   Show (dlg->viewer_grp);
13971   if (dlg->ignore_alignment)
13972   {
13973     Hide (dlg->details_grp);
13974     Hide (dlg->letters_grp);
13975   }
13976   else
13977   {
13978     Show (dlg->details_grp);
13979     Show (dlg->letters_grp);
13980   }
13981 
13982   /* unreverse the sequence if it was reversed */
13983   if (upd.revcomp)
13984   {
13985     BioseqRevComp (upd.update_bsp);
13986     ReverseBioseqFeatureStrands (upd.update_bsp);
13987     SeqMgrReplaceInBioseqIndex (upd.update_bsp);
13988   }
13989 
13990 }
13991 
AlignmentToUpdatePreviewDialog(DialoG d,Pointer data)13992 static void AlignmentToUpdatePreviewDialog (DialoG d, Pointer data)
13993 {
13994   UpdatePreviewDialogPtr dlg;
13995   UpdatePairPtr          upp;
13996 
13997   dlg = (UpdatePreviewDialogPtr) GetObjectExtra (d);
13998   if (dlg == NULL)
13999   {
14000     return;
14001   }
14002 
14003   dlg->overview_picture     = DeletePicture (dlg->overview_picture);
14004   dlg->details_picture     = DeletePicture (dlg->details_picture);
14005   dlg->salp = NULL;
14006   dlg->orig_bsp = NULL;
14007   dlg->update_bsp = NULL;
14008   dlg->revcomp = FALSE;
14009   dlg->salp = SeqAlignFree (dlg->salp);
14010 
14011   upp = (UpdatePairPtr) data;
14012 
14013   if (upp != NULL)
14014   {
14015     dlg->salp = upp->salp;
14016     dlg->revcomp = upp->revcomp;
14017     dlg->orig_bsp = upp->orig_bsp;
14018     dlg->update_bsp = upp->update_bsp;
14019     if (dlg->update_bsp != NULL && BioseqFind (dlg->update_bsp->id) != dlg->update_bsp)
14020     {
14021       SeqMgrReplaceInBioseqIndex (dlg->update_bsp);
14022     }
14023   }
14024 
14025   RedrawAlignmentPreview (d);
14026 }
14027 
SetIgnoreAndExtendForPreviewPictures(DialoG d,Boolean ignore_alignment,Boolean extend5)14028 static void SetIgnoreAndExtendForPreviewPictures (DialoG d, Boolean ignore_alignment, Boolean extend5)
14029 {
14030   UpdatePreviewDialogPtr dlg;
14031 
14032   dlg = (UpdatePreviewDialogPtr) GetObjectExtra (d);
14033   if (dlg == NULL)
14034   {
14035     return;
14036   }
14037   dlg->ignore_alignment = ignore_alignment;
14038   dlg->extend5 = extend5;
14039   RedrawAlignmentPreview (d);
14040 }
14041 
CleanupPreviewDialog(GraphiC g,Pointer data)14042 static void CleanupPreviewDialog (GraphiC g, Pointer data)
14043 {
14044   UpdatePreviewDialogPtr dlg;
14045 
14046   dlg = (UpdatePreviewDialogPtr) data;
14047   if (dlg != NULL)
14048   {
14049     dlg->indels = ValNodeFree (dlg->indels);
14050     dlg->mismatches = ValNodeFree (dlg->mismatches);
14051     dlg->salp = SeqAlignFree (dlg->salp);
14052   }
14053   StdCleanupExtraProc (g, data);
14054 }
14055 
UpdatePreviewDialog(GrouP parent,Boolean is_indexer)14056 static DialoG UpdatePreviewDialog (GrouP parent, Boolean is_indexer)
14057 {
14058   UpdatePreviewDialogPtr dlg;
14059   GrouP                  p;
14060   Int4                   prompt_width = 400, hgt;
14061   GrouP                  ppt1, ppt2, ppt3;
14062 
14063   dlg = (UpdatePreviewDialogPtr) MemNew (sizeof (UpdatePreviewDialogData));
14064   if (dlg == NULL)
14065   {
14066     return NULL;
14067   }
14068 
14069   p = HiddenGroup (parent, -1, 0, NULL);
14070   SetObjectExtra (p, dlg, CleanupPreviewDialog);
14071   SetGroupSpacing (p, 2, 2);
14072 
14073   dlg->dialog = (DialoG) p;
14074 
14075   dlg->todialog = AlignmentToUpdatePreviewDialog;
14076   dlg->fromdialog = UpdatePairFromUpdatePreviewDialog;
14077 
14078   dlg->viewer_grp = HiddenGroup (p, -1, 0, NULL);
14079   SetGroupSpacing (dlg->viewer_grp, 2, 2);
14080   ppt1 = MultiLinePrompt (dlg->viewer_grp, txt1, prompt_width, programFont);
14081   dlg->overview = CreateViewer (dlg->viewer_grp, prompt_width + Nlm_vScrollBarWidth, 100,
14082 				FALSE, FALSE);
14083 
14084   dlg->details_grp = HiddenGroup (dlg->viewer_grp, -1, 0, NULL);
14085   SetGroupSpacing (dlg->details_grp, 2, 2);
14086   ppt2 = MultiLinePrompt (dlg->details_grp, txt2, prompt_width, programFont);
14087   dlg->details = CreateViewer (dlg->details_grp, prompt_width + Nlm_vScrollBarWidth, 80,
14088 			       FALSE, FALSE);
14089   AlignObjects (ALIGN_CENTER, (HANDLE) ppt2, (HANDLE) dlg->details, NULL);
14090 
14091   dlg->letters_grp = HiddenGroup (dlg->viewer_grp, -1, 0, NULL);
14092   SetGroupSpacing (dlg->letters_grp, 2, 2);
14093   ppt3 = MultiLinePrompt (dlg->letters_grp, txt3, prompt_width, programFont);
14094 
14095 #ifdef WIN_MAC
14096   hgt = 90;
14097 #else
14098   hgt = 110;
14099 #endif
14100 
14101   dlg->letters_dlg = AlignmentLettersPanel (dlg->letters_grp, prompt_width, hgt);
14102   AlignObjects (ALIGN_CENTER, (HANDLE) ppt3, (HANDLE) dlg->letters_dlg, NULL);
14103 
14104   dlg->overview_picture = NULL;
14105   dlg->details_picture = NULL;
14106   dlg->indels = NULL;
14107   dlg->mismatches = NULL;
14108   MemSet (&(dlg->uald), 0, sizeof (UpdateAlignmentLengthsData));
14109 
14110 
14111 
14112   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->overview,
14113                               (HANDLE) dlg->details_grp,
14114                               (HANDLE) dlg->letters_grp,
14115                               (HANDLE) ppt1,
14116                               NULL);
14117 
14118   return (DialoG) p;
14119 }
14120 
14121 
14122 typedef struct submitterfeatureimportoptionsdialog
14123 {
14124   DIALOG_MESSAGE_BLOCK
14125 
14126   GrouP feature_update_type;
14127 
14128   Nlm_ChangeNotifyProc change_notify;
14129   Pointer              change_userdata;
14130 } SubmitterFeatureImportOptionsDlgData, PNTR SubmitterFeatureImportOptionsDlgPtr;
14131 
14132 
SubmitterFeatureImportOptionsToDialog(DialoG d,Pointer data)14133 static void SubmitterFeatureImportOptionsToDialog (DialoG d, Pointer data)
14134 {
14135   SubmitterFeatureImportOptionsDlgPtr dlg;
14136   FeatureImportOptionsPtr f;
14137 
14138   dlg = (SubmitterFeatureImportOptionsDlgPtr) GetObjectExtra (d);
14139   if (dlg == NULL) {
14140     return;
14141   }
14142 
14143   if ((f = (FeatureImportOptionsPtr) data) == NULL) {
14144     SetValue (dlg->feature_update_type, eFeatureUpdateNoChange);
14145   } else {
14146     SetValue (dlg->feature_update_type, f->feature_import_type);
14147   }
14148 }
14149 
14150 
SubmitterFeatureImportOptionsFromDialog(DialoG d)14151 static Pointer SubmitterFeatureImportOptionsFromDialog (DialoG d)
14152 {
14153   SubmitterFeatureImportOptionsDlgPtr dlg;
14154   FeatureImportOptionsPtr f;
14155 
14156   dlg = (SubmitterFeatureImportOptionsDlgPtr) GetObjectExtra (d);
14157   if (dlg == NULL) {
14158     return NULL;
14159   }
14160 
14161   f = FeatureImportOptionsNew ();
14162   f->feature_import_type = GetValue (dlg->feature_update_type);
14163   return f;
14164 }
14165 
14166 
ChangeSubmitterFeatureImportOptionsDialogGroup(GrouP g)14167 static void ChangeSubmitterFeatureImportOptionsDialogGroup (GrouP g)
14168 {
14169   SubmitterFeatureImportOptionsDlgPtr dlg;
14170 
14171   dlg = (SubmitterFeatureImportOptionsDlgPtr) GetObjectExtra (g);
14172   if (dlg == NULL) {
14173     return;
14174   }
14175 
14176   if (dlg->change_notify != NULL) {
14177     (dlg->change_notify)(dlg->change_userdata);
14178   }
14179 }
14180 
14181 
14182 static DialoG
SubmitterFeatureImportOptionsDialog(GrouP parent,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)14183 SubmitterFeatureImportOptionsDialog
14184 (GrouP                parent,
14185  Nlm_ChangeNotifyProc change_notify,
14186  Pointer              change_userdata)
14187 {
14188   SubmitterFeatureImportOptionsDlgPtr dlg;
14189   GrouP                  p;
14190 
14191   dlg = (SubmitterFeatureImportOptionsDlgPtr) MemNew (sizeof (SubmitterFeatureImportOptionsDlgData));
14192   if (dlg == NULL)
14193   {
14194     return NULL;
14195   }
14196 
14197   p = NormalGroup (parent, 1, 0, "Import Features", programFont, NULL);
14198   SetObjectExtra (p, dlg, StdCleanupExtraProc);
14199   SetGroupSpacing (p, 10, 10);
14200 
14201   dlg->dialog = (DialoG) p;
14202   dlg->todialog = SubmitterFeatureImportOptionsToDialog;
14203   dlg->fromdialog = SubmitterFeatureImportOptionsFromDialog;
14204 
14205   dlg->change_notify = change_notify;
14206   dlg->change_userdata = change_userdata;
14207 
14208   dlg->feature_update_type = HiddenGroup (p, 0, 6, ChangeSubmitterFeatureImportOptionsDialogGroup);
14209   SetObjectExtra (dlg->feature_update_type, dlg, NULL);
14210   RadioButton (dlg->feature_update_type, "Do not import features");
14211   RadioButton (dlg->feature_update_type, "Import all except duplicates");
14212   RadioButton (dlg->feature_update_type, "Import all, merge duplicates");
14213   RadioButton (dlg->feature_update_type, "Import all, replace duplicates");
14214   RadioButton (dlg->feature_update_type, "Import all, including duplicates");
14215   SetValue (dlg->feature_update_type, eFeatureUpdateNoChange);
14216 
14217   return (DialoG) p;
14218 }
14219 
14220 
14221 typedef struct indexerfeatureimportoptionsdialog
14222 {
14223   DIALOG_MESSAGE_BLOCK
14224 
14225   ButtoN do_import_btn;
14226   DialoG feature_types;
14227   GrouP  feature_update_type;
14228 
14229   Nlm_ChangeNotifyProc change_notify;
14230   Pointer              change_userdata;
14231 } IndexerFeatureImportOptionsDlgData, PNTR IndexerFeatureImportOptionsDlgPtr;
14232 
14233 
IndexerFeatureImportOptionsToDialog(DialoG d,Pointer data)14234 static void IndexerFeatureImportOptionsToDialog (DialoG d, Pointer data)
14235 {
14236   IndexerFeatureImportOptionsDlgPtr dlg;
14237   FeatureImportOptionsPtr f;
14238 
14239   dlg = (IndexerFeatureImportOptionsDlgPtr) GetObjectExtra (d);
14240   if (dlg == NULL) {
14241     return;
14242   }
14243 
14244   if ((f = (FeatureImportOptionsPtr) data) == NULL || f->feature_import_type == eFeatureUpdateNoChange) {
14245     SetStatus (dlg->do_import_btn, FALSE);
14246     Disable (dlg->feature_types);
14247     Disable (dlg->feature_update_type);
14248   } else {
14249     SetStatus (dlg->do_import_btn, TRUE);
14250     if (f->feature_types == NULL) {
14251       SendMessageToDialog (dlg->feature_types, NUM_VIB_MSG + 1);
14252     } else {
14253       PointerToDialog (dlg->feature_types, f->feature_types);
14254     }
14255     SetValue (dlg->feature_update_type, f->feature_import_type - 1);
14256   }
14257 }
14258 
14259 
IndexerFeatureImportOptionsFromDialog(DialoG d)14260 static Pointer IndexerFeatureImportOptionsFromDialog (DialoG d)
14261 {
14262   IndexerFeatureImportOptionsDlgPtr dlg;
14263   FeatureImportOptionsPtr f = NULL;
14264 
14265   dlg = (IndexerFeatureImportOptionsDlgPtr) GetObjectExtra (d);
14266   if (dlg == NULL) {
14267     return NULL;
14268   }
14269 
14270   if (GetStatus (dlg->do_import_btn)) {
14271     f = FeatureImportOptionsNew ();
14272     f->feature_import_type = GetValue (dlg->feature_update_type) + 1;
14273     f->feature_types = DialogToPointer (dlg->feature_types);
14274     if (f->feature_types != NULL && (f->feature_types->choice == FEATDEF_ANY || f->feature_types->choice == 0)) {
14275       f->feature_types = ValNodeFree (f->feature_types);
14276     }
14277   }
14278   return f;
14279 }
14280 
14281 
ChangeIndexerFeatureImportOptionsDialogGroup(GrouP g)14282 static void ChangeIndexerFeatureImportOptionsDialogGroup (GrouP g)
14283 {
14284   IndexerFeatureImportOptionsDlgPtr dlg;
14285 
14286   dlg = (IndexerFeatureImportOptionsDlgPtr) GetObjectExtra (g);
14287   if (dlg == NULL) {
14288     return;
14289   }
14290 
14291   if (dlg->change_notify != NULL) {
14292     (dlg->change_notify)(dlg->change_userdata);
14293   }
14294 }
14295 
14296 
ChangeIndexerFeatureImportOptionsDialogBtn(ButtoN b)14297 static void ChangeIndexerFeatureImportOptionsDialogBtn (ButtoN b)
14298 {
14299   IndexerFeatureImportOptionsDlgPtr dlg;
14300   ValNodePtr tmp;
14301 
14302   dlg = (IndexerFeatureImportOptionsDlgPtr) GetObjectExtra (b);
14303   if (dlg == NULL) {
14304     return;
14305   }
14306   if (GetStatus (dlg->do_import_btn)) {
14307     Enable (dlg->feature_update_type);
14308     Enable (dlg->feature_types);
14309     tmp = DialogToPointer (dlg->feature_types);
14310     if (tmp == NULL) {
14311       SendMessageToDialog (dlg->feature_types, NUM_VIB_MSG + 1);
14312     } else {
14313       tmp = ValNodeFree (tmp);
14314     }
14315   } else {
14316     Disable (dlg->feature_update_type);
14317     Disable (dlg->feature_types);
14318   }
14319 
14320   if (dlg->change_notify != NULL) {
14321     (dlg->change_notify)(dlg->change_userdata);
14322   }
14323 }
14324 
14325 
14326 static DialoG
IndexerFeatureImportOptionsDialog(GrouP parent,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)14327 IndexerFeatureImportOptionsDialog
14328 (GrouP                parent,
14329  Nlm_ChangeNotifyProc change_notify,
14330  Pointer              change_userdata)
14331 {
14332   IndexerFeatureImportOptionsDlgPtr dlg;
14333   GrouP                  p;
14334 
14335   dlg = (IndexerFeatureImportOptionsDlgPtr) MemNew (sizeof (IndexerFeatureImportOptionsDlgData));
14336   if (dlg == NULL)
14337   {
14338     return NULL;
14339   }
14340 
14341   p = NormalGroup (parent, 3, 0, "Import Features", programFont, NULL);
14342   SetObjectExtra (p, dlg, StdCleanupExtraProc);
14343   SetGroupSpacing (p, 10, 10);
14344 
14345   dlg->dialog = (DialoG) p;
14346   dlg->todialog = IndexerFeatureImportOptionsToDialog;
14347   dlg->fromdialog = IndexerFeatureImportOptionsFromDialog;
14348 
14349   dlg->change_notify = change_notify;
14350   dlg->change_userdata = change_userdata;
14351 
14352   dlg->do_import_btn = CheckBox (p, "Import features", ChangeIndexerFeatureImportOptionsDialogBtn);
14353   SetObjectExtra (dlg->do_import_btn, dlg, NULL);
14354   dlg->feature_types = FeatureTypeDialogMulti (p, change_notify, change_userdata);
14355   SendMessageToDialog (dlg->feature_types, NUM_VIB_MSG + 1);
14356   dlg->feature_update_type = HiddenGroup (p, 0, 6, ChangeIndexerFeatureImportOptionsDialogGroup);
14357   SetObjectExtra (dlg->feature_update_type, dlg, NULL);
14358   RadioButton (dlg->feature_update_type, "Except duplicates");
14359   RadioButton (dlg->feature_update_type, "Merge duplicates");
14360   RadioButton (dlg->feature_update_type, "Replace duplicates");
14361   RadioButton (dlg->feature_update_type, "Including duplicates");
14362   SetValue (dlg->feature_update_type, 1);
14363 
14364   return (DialoG) p;
14365 }
14366 
14367 
14368 typedef struct submitterupdateoptionsdialog
14369 {
14370   DIALOG_MESSAGE_BLOCK
14371   GrouP                sequence_update_type;
14372   DialoG               feature_update_options;
14373   GrouP                feature_remove_type;
14374 
14375   ButtoN               sequence_update_btns [eSequenceUpdateExtend3];
14376 
14377   ButtoN               ignore_alignment;
14378 
14379   Boolean              do_update;
14380 
14381   Nlm_ChangeNotifyProc change_notify;
14382   Pointer              change_userdata;
14383 
14384 } SubmitterUpdateOptionsDialogData, PNTR SubmitterUpdateOptionsDialogPtr;
14385 
SubmitterUpdateOptionsToDialog(DialoG d,Pointer data)14386 static void SubmitterUpdateOptionsToDialog (DialoG d, Pointer data)
14387 {
14388   SubmitterUpdateOptionsDialogPtr dlg;
14389   SubmitterUpdateOptionsPtr       suop;
14390 
14391   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (d);
14392   if (dlg == NULL)
14393   {
14394     return;
14395   }
14396 
14397   suop = (SubmitterUpdateOptionsPtr) data;
14398   if (dlg->do_update)
14399   {
14400     if (suop == NULL)
14401     {
14402       SetValue (dlg->sequence_update_type, eSequenceUpdateNoChange);
14403       PointerToDialog (dlg->feature_update_options, NULL);
14404       SetValue (dlg->feature_remove_type, eFeatureRemoveNone);
14405       SetStatus (dlg->ignore_alignment, FALSE);
14406     }
14407     else
14408     {
14409       SetValue (dlg->sequence_update_type, suop->sequence_update_type);
14410       PointerToDialog (dlg->feature_update_options, suop->feature_import_options);
14411       SetValue (dlg->feature_remove_type, suop->feature_remove_type);
14412       SetStatus (dlg->ignore_alignment, suop->ignore_alignment);
14413     }
14414   }
14415   else
14416   {
14417   	if (suop == NULL)
14418   	{
14419   	  SetValue (dlg->sequence_update_type, 1);
14420       PointerToDialog (dlg->feature_update_options, NULL);
14421       SetValue (dlg->feature_remove_type, eFeatureRemoveNone);
14422   	}
14423   	else
14424   	{
14425   	  if (suop->sequence_update_type == eSequenceUpdateExtend3)
14426   	  {
14427         SetValue (dlg->sequence_update_type, 2);
14428   	  }
14429   	  else
14430   	  {
14431         SetValue (dlg->sequence_update_type, 1);
14432   	  }
14433 
14434       PointerToDialog (dlg->feature_update_options, suop->feature_import_options);
14435       SetValue (dlg->feature_remove_type, suop->feature_remove_type);
14436   	}
14437   }
14438 
14439   if (dlg->change_notify != NULL)
14440   {
14441     (dlg->change_notify) (dlg->change_userdata);
14442   }
14443 
14444 }
14445 
SubmitterUpdateOptionsFromDialog(DialoG d)14446 static Pointer SubmitterUpdateOptionsFromDialog (DialoG d)
14447 {
14448   SubmitterUpdateOptionsDialogPtr dlg;
14449   SubmitterUpdateOptionsPtr       suop;
14450 
14451   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (d);
14452   if (dlg == NULL)
14453   {
14454     return NULL;
14455   }
14456 
14457   suop = (SubmitterUpdateOptionsPtr) MemNew (sizeof (SubmitterUpdateOptionsData));
14458   if (suop != NULL)
14459   {
14460     if (dlg->do_update)
14461     {
14462       suop->sequence_update_type = (ESequenceUpdateType) GetValue (dlg->sequence_update_type);
14463       if (suop->sequence_update_type > eSequenceUpdateNoChange
14464           && ! Enabled (dlg->sequence_update_btns [suop->sequence_update_type - 1]))
14465       {
14466         suop->sequence_update_type = eSequenceUpdateNoChange;
14467       }
14468     }
14469     else
14470     {
14471       if (GetValue (dlg->sequence_update_type) == 2)
14472       {
14473       	suop->sequence_update_type = eSequenceUpdateExtend3;
14474       }
14475       else
14476       {
14477       	suop->sequence_update_type = eSequenceUpdateExtend5;
14478       }
14479     }
14480 
14481     suop->feature_import_options = DialogToPointer (dlg->feature_update_options);
14482     suop->feature_remove_type = (EFeatureRemoveType) GetValue (dlg->feature_remove_type);
14483 
14484     if (dlg->do_update)
14485     {
14486       if (Enabled (dlg->ignore_alignment)
14487           && (suop->sequence_update_type == eSequenceUpdateExtend5
14488               || suop->sequence_update_type == eSequenceUpdateExtend3
14489               || suop->sequence_update_type == eSequenceUpdateReplace))
14490       {
14491         suop->ignore_alignment = GetStatus (dlg->ignore_alignment);
14492       }
14493       else
14494       {
14495         suop->ignore_alignment = FALSE;
14496       }
14497     }
14498     else
14499     {
14500       suop->ignore_alignment = TRUE;
14501     }
14502   }
14503   return suop;
14504 }
14505 
DisableSubmitterImportFeatureOptions(DialoG d)14506 static void DisableSubmitterImportFeatureOptions (DialoG d)
14507 {
14508   SubmitterUpdateOptionsDialogPtr dlg;
14509 
14510   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (d);
14511   if (dlg == NULL)
14512   {
14513     return;
14514   }
14515 
14516   Disable (dlg->feature_update_options);
14517 }
14518 
EnableSubmitterImportFeatureOptions(DialoG d)14519 static void EnableSubmitterImportFeatureOptions (DialoG d)
14520 {
14521   SubmitterUpdateOptionsDialogPtr dlg;
14522 
14523   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (d);
14524   if (dlg == NULL)
14525   {
14526     return;
14527   }
14528 
14529   Enable (dlg->feature_update_options);
14530 }
14531 
DisableSubmitterRemoveFeatureOptions(DialoG d)14532 static void DisableSubmitterRemoveFeatureOptions (DialoG d)
14533 {
14534   SubmitterUpdateOptionsDialogPtr dlg;
14535 
14536   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (d);
14537   if (dlg == NULL)
14538   {
14539     return;
14540   }
14541 
14542   Disable (dlg->feature_remove_type);
14543 }
14544 
EnableSubmitterRemoveFeatureOptions(DialoG d)14545 static void EnableSubmitterRemoveFeatureOptions (DialoG d)
14546 {
14547   SubmitterUpdateOptionsDialogPtr dlg;
14548 
14549   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (d);
14550   if (dlg == NULL)
14551   {
14552     return;
14553   }
14554 
14555   Enable (dlg->feature_remove_type);
14556 }
14557 
AdjustSequenceUpdateOptionsEnabled(DialoG d,UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp,Boolean is_indexer)14558 static void AdjustSequenceUpdateOptionsEnabled
14559 (DialoG                    d,
14560  UpdatePairPtr             upp,
14561  UpdateAlignmentLengthsPtr ualp,
14562  Boolean                   is_indexer)
14563 {
14564   SubmitterUpdateOptionsDialogPtr dlg;
14565   ESequenceUpdateType             action;
14566   Boolean                         ignore_alignment;
14567   SubmitterUpdateOptionsPtr       suop;
14568 
14569   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (d);
14570   if (dlg == NULL)
14571   {
14572     return;
14573   }
14574 
14575   if (!dlg->do_update)
14576   {
14577   	Enable (dlg->sequence_update_btns [0]);
14578   	Enable (dlg->sequence_update_btns [1]);
14579   	return;
14580   }
14581 
14582   suop = DialogToPointer (d);
14583 
14584   if (upp == NULL || upp->salp == NULL)
14585   {
14586     Disable (dlg->ignore_alignment);
14587     ignore_alignment = TRUE;
14588   }
14589   else if (suop != NULL
14590           && (suop->sequence_update_type == eSequenceUpdateNoChange
14591               || suop->sequence_update_type == eSequenceUpdatePatch))
14592   {
14593     Disable (dlg->ignore_alignment);
14594     ignore_alignment = FALSE;
14595   }
14596   else
14597   {
14598 
14599     Enable (dlg->ignore_alignment);
14600     ignore_alignment = GetStatus (dlg->ignore_alignment);
14601   }
14602 
14603   for (action = eSequenceUpdateNoChange;
14604        action <= eSequenceUpdateExtend3;
14605        action++)
14606   {
14607     if (IsSequenceUpdateChoiceAllowed (action, upp, ualp, is_indexer,
14608                                        ignore_alignment))
14609     {
14610       Enable (dlg->sequence_update_btns [action - 1]);
14611     }
14612     else
14613     {
14614       Disable (dlg->sequence_update_btns [action - 1]);
14615     }
14616   }
14617 
14618 }
14619 
IgnoreAlignmentBtn(ButtoN b)14620 static void IgnoreAlignmentBtn (ButtoN b)
14621 {
14622   SubmitterUpdateOptionsDialogPtr dlg;
14623 
14624   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (b);
14625   if (dlg != NULL && dlg->change_notify != NULL)
14626   {
14627     (dlg->change_notify) (dlg->change_userdata);
14628   }
14629 }
14630 
UpdateTypeGroup(GrouP g)14631 static void UpdateTypeGroup (GrouP g)
14632 {
14633   SubmitterUpdateOptionsDialogPtr dlg;
14634 
14635   dlg = (SubmitterUpdateOptionsDialogPtr) GetObjectExtra (g);
14636   if (dlg != NULL && dlg->change_notify != NULL)
14637   {
14638     (dlg->change_notify) (dlg->change_userdata);
14639   }
14640 }
14641 
14642 static DialoG
SubmitterUpdateOptionsDialog(GrouP parent,Boolean is_indexer,Boolean do_update,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)14643 SubmitterUpdateOptionsDialog
14644 (GrouP                parent,
14645  Boolean              is_indexer,
14646  Boolean              do_update,
14647  Nlm_ChangeNotifyProc change_notify,
14648  Pointer              change_userdata)
14649 {
14650   SubmitterUpdateOptionsDialogPtr dlg;
14651   GrouP                  p, j, k, g;
14652 
14653   dlg = (SubmitterUpdateOptionsDialogPtr) MemNew (sizeof (SubmitterUpdateOptionsDialogData));
14654   if (dlg == NULL)
14655   {
14656     return NULL;
14657   }
14658 
14659   if (is_indexer)
14660   {
14661     p = HiddenGroup (parent, -1, 0, NULL);
14662   }
14663   else
14664   {
14665     p = HiddenGroup (parent, 1, 0, NULL);
14666   }
14667   SetObjectExtra (p, dlg, StdCleanupExtraProc);
14668   SetGroupSpacing (p, 10, 10);
14669 
14670   dlg->dialog = (DialoG) p;
14671   dlg->todialog = SubmitterUpdateOptionsToDialog;
14672   dlg->fromdialog = SubmitterUpdateOptionsFromDialog;
14673 
14674   dlg->change_notify = change_notify;
14675   dlg->change_userdata = change_userdata;
14676 
14677   dlg->do_update = do_update;
14678 
14679   if (dlg->do_update)
14680   {
14681     j = NormalGroup (p, -1, 0, "Sequence Update", programFont, NULL);
14682     if (is_indexer)
14683     {
14684       dlg->sequence_update_type = HiddenGroup (j, 0, 1, UpdateTypeGroup);
14685     }
14686     else
14687     {
14688       SetGroupSpacing (j, 3, 10);
14689       dlg->sequence_update_type = HiddenGroup (j, 1, 0, UpdateTypeGroup);
14690       SetGroupSpacing (dlg->sequence_update_type, 3, 2);
14691     }
14692     SetObjectExtra (dlg->sequence_update_type, dlg, NULL);
14693     dlg->sequence_update_btns [0] = RadioButton (dlg->sequence_update_type, "No change");
14694     dlg->sequence_update_btns [1] = RadioButton (dlg->sequence_update_type, "Replace");
14695     dlg->sequence_update_btns [2] = RadioButton (dlg->sequence_update_type, "Patch");
14696     dlg->sequence_update_btns [3] = RadioButton (dlg->sequence_update_type, "Extend 5'");
14697     dlg->sequence_update_btns [4] = RadioButton (dlg->sequence_update_type, "Extend 3'");
14698     SetValue (dlg->sequence_update_type, eSequenceUpdateNoChange);
14699     dlg->ignore_alignment = CheckBox (j, "Ignore alignment", IgnoreAlignmentBtn);
14700     SetObjectExtra (dlg->ignore_alignment, dlg, NULL);
14701     if (is_indexer)
14702     {
14703       AlignObjects (ALIGN_CENTER, (HANDLE) dlg->sequence_update_type,
14704                                   (HANDLE) dlg->ignore_alignment,
14705                                   NULL);
14706     }
14707     else
14708     {
14709       AlignObjects (ALIGN_LEFT, (HANDLE) dlg->sequence_update_type,
14710                                 (HANDLE) dlg->ignore_alignment,
14711                                 NULL);
14712     }
14713   }
14714   else
14715   {
14716   	j = NormalGroup (p, -1, 0, "Extend Sequence", programFont, NULL);
14717     dlg->sequence_update_type = HiddenGroup (j, 0, 1, NULL);
14718     dlg->sequence_update_btns [0] = RadioButton (dlg->sequence_update_type, "Extend 5'");
14719     dlg->sequence_update_btns [1] = RadioButton (dlg->sequence_update_type, "Extend 3'");
14720     dlg->sequence_update_btns [2] = NULL;
14721     dlg->sequence_update_btns [3] = NULL;
14722     dlg->sequence_update_btns [4] = NULL;
14723 
14724     SetValue (dlg->sequence_update_type, 1);
14725     dlg->ignore_alignment = NULL;
14726   }
14727 
14728   if (is_indexer)
14729   {
14730     k = HiddenGroup (p, 2, 0, NULL);
14731   }
14732   else
14733   {
14734     k = p;
14735   }
14736 
14737   g = NormalGroup (k, 1, 0, "Existing Features", programFont, NULL);
14738   dlg->feature_remove_type = HiddenGroup (g, 0, 6, NULL);
14739   RadioButton (dlg->feature_remove_type, "Do not remove");
14740   RadioButton (dlg->feature_remove_type, "Remove in aligned area");
14741   RadioButton (dlg->feature_remove_type, "Remove outside aligned area");
14742   RadioButton (dlg->feature_remove_type, "Remove all");
14743   SetValue (dlg->feature_remove_type, eFeatureRemoveNone);
14744 
14745   if (is_indexer) {
14746     dlg->feature_update_options = IndexerFeatureImportOptionsDialog (k, NULL, NULL);
14747   } else {
14748     dlg->feature_update_options = SubmitterFeatureImportOptionsDialog (k, NULL, NULL);
14749   }
14750 
14751   if (is_indexer)
14752   {
14753     AlignObjects (ALIGN_CENTER, (HANDLE) j,
14754                                 (HANDLE) k,
14755                                 NULL);
14756   }
14757 
14758   return (DialoG) p;
14759 }
14760 
14761 typedef struct indexeroptionsdialog
14762 {
14763   DIALOG_MESSAGE_BLOCK
14764   ButtoN keep_protein_ids;
14765   ButtoN add_cit_subs;
14766   ButtoN update_quality_scores;
14767   ButtoN update_proteins;
14768   GrouP  protein_options;
14769   ButtoN truncate_proteins;
14770   ButtoN extend_proteins3;
14771   ButtoN extend_proteins5;
14772   ButtoN correct_cds_genes;
14773 } IndexerOptionsDialogData, PNTR IndexerOptionsDialogPtr;
14774 
EnableIndexerOptions(ButtoN b)14775 static void EnableIndexerOptions (ButtoN b)
14776 {
14777   IndexerOptionsDialogPtr dlg;
14778 
14779   dlg = (IndexerOptionsDialogPtr) GetObjectExtra (b);
14780   if (dlg == NULL)
14781   {
14782     return;
14783   }
14784 
14785   if (GetStatus (dlg->update_proteins))
14786   {
14787     Enable (dlg->protein_options);
14788   }
14789   else
14790   {
14791     Disable (dlg->protein_options);
14792   }
14793 }
14794 
IndexerOptionsToDialog(DialoG d,Pointer data)14795 static void IndexerOptionsToDialog (DialoG d, Pointer data)
14796 {
14797   IndexerOptionsDialogPtr dlg;
14798   IndexerOptionsPtr       iop;
14799 
14800   dlg = (IndexerOptionsDialogPtr) GetObjectExtra (d);
14801   if (dlg == NULL)
14802   {
14803     return;
14804   }
14805 
14806   iop = (IndexerOptionsPtr) data;
14807 
14808   if (iop == NULL)
14809   {
14810     SetStatus (dlg->add_cit_subs, FALSE);
14811     SetStatus (dlg->update_quality_scores, TRUE);
14812     SafeSetStatus (dlg->update_proteins, FALSE);
14813     SafeSetStatus (dlg->truncate_proteins, FALSE);
14814     SafeSetStatus (dlg->extend_proteins3, FALSE);
14815     SafeSetStatus (dlg->extend_proteins5, FALSE);
14816     SafeSetStatus (dlg->correct_cds_genes, FALSE);
14817     SafeSetStatus (dlg->keep_protein_ids, FALSE);
14818   }
14819   else
14820   {
14821     SetStatus (dlg->add_cit_subs, iop->add_cit_subs);
14822     SetStatus (dlg->update_quality_scores, iop->update_quality_scores);
14823     SafeSetStatus (dlg->update_proteins, iop->update_proteins);
14824     SafeSetStatus (dlg->keep_protein_ids, iop->keep_protein_ids);
14825     if (iop->update_proteins)
14826     {
14827       SafeSetStatus (dlg->truncate_proteins, iop->truncate_proteins);
14828       SafeSetStatus (dlg->extend_proteins3, iop->extend_proteins3);
14829       SafeSetStatus (dlg->extend_proteins5, iop->extend_proteins5);
14830       SafeSetStatus (dlg->correct_cds_genes, iop->correct_cds_genes);
14831     }
14832     else
14833     {
14834       SafeSetStatus (dlg->truncate_proteins, FALSE);
14835       SafeSetStatus (dlg->extend_proteins3, FALSE);
14836       SafeSetStatus (dlg->extend_proteins5, FALSE);
14837       SafeSetStatus (dlg->correct_cds_genes, FALSE);
14838     }
14839   }
14840 
14841   EnableIndexerOptions (dlg->update_proteins);
14842 }
14843 
IndexerOptionsFromDialog(DialoG d)14844 static Pointer IndexerOptionsFromDialog (DialoG d)
14845 {
14846   IndexerOptionsDialogPtr dlg;
14847   IndexerOptionsPtr       iop;
14848 
14849   dlg = (IndexerOptionsDialogPtr) GetObjectExtra (d);
14850   if (dlg == NULL)
14851   {
14852     return NULL;
14853   }
14854 
14855   iop = (IndexerOptionsPtr) MemNew (sizeof (IndexerOptionsData));
14856 
14857   if (iop == NULL)
14858   {
14859     return NULL;
14860   }
14861   iop->add_cit_subs = GetStatus (dlg->add_cit_subs);
14862   iop->update_quality_scores = GetStatus (dlg->update_quality_scores);
14863   iop->keep_protein_ids = GetStatus (dlg->keep_protein_ids);
14864   if (dlg->protein_options == NULL || GetStatus (dlg->update_proteins) == FALSE)
14865   {
14866     iop->update_proteins = FALSE;
14867     iop->truncate_proteins = FALSE;
14868     iop->extend_proteins3 = FALSE;
14869     iop->extend_proteins5 = FALSE;
14870     iop->correct_cds_genes = FALSE;
14871   }
14872   else
14873   {
14874     iop->update_proteins = TRUE;
14875     iop->truncate_proteins = GetStatus (dlg->truncate_proteins);
14876     iop->extend_proteins3 = GetStatus (dlg->extend_proteins3);
14877     iop->extend_proteins5 = GetStatus (dlg->extend_proteins5);
14878     iop->correct_cds_genes = GetStatus (dlg->correct_cds_genes);
14879   }
14880   return iop;
14881 }
14882 
EnableIndexerImportFeatureOptions(DialoG d)14883 static void EnableIndexerImportFeatureOptions (DialoG d)
14884 {
14885   IndexerOptionsDialogPtr dlg;
14886 
14887   dlg = (IndexerOptionsDialogPtr) GetObjectExtra (d);
14888   if (dlg == NULL)
14889   {
14890     return;
14891   }
14892 
14893   SafeEnable (dlg->keep_protein_ids);
14894   Enable (dlg->update_proteins);
14895   EnableIndexerOptions (dlg->update_proteins);
14896 }
14897 
IndexerUpdateOptionsDialog(GrouP parent,Boolean is_nuc)14898 static DialoG IndexerUpdateOptionsDialog (GrouP parent, Boolean is_nuc)
14899 {
14900   GrouP p;
14901   IndexerOptionsDialogPtr dlg;
14902 
14903   dlg = (IndexerOptionsDialogPtr) MemNew (sizeof (IndexerOptionsDialogData));
14904   if (dlg == NULL)
14905   {
14906     return NULL;
14907   }
14908   p = HiddenGroup (parent, -1, 0, NULL);
14909   SetObjectExtra (p, dlg, StdCleanupExtraProc);
14910   SetGroupSpacing (p, 2, 2);
14911 
14912   dlg->dialog = (DialoG) p;
14913   dlg->todialog = IndexerOptionsToDialog;
14914   dlg->fromdialog = IndexerOptionsFromDialog;
14915 
14916   dlg->keep_protein_ids = CheckBox (p, "Keep protein IDs", NULL);
14917   dlg->add_cit_subs = CheckBox (p, "Add Cit-subs for Updated Sequences", NULL);
14918   dlg->update_quality_scores = CheckBox (p, "Replace Quality Scores", NULL);
14919   if (is_nuc)
14920   {
14921     dlg->update_proteins = CheckBox (p, "Update Proteins for Updated Sequences", EnableIndexerOptions);
14922     SetObjectExtra (dlg->update_proteins, dlg, NULL);
14923     dlg->protein_options = HiddenGroup (p, 1, 0, NULL);
14924     dlg->truncate_proteins = CheckBox (dlg->protein_options,
14925                                        "Truncate retranslated proteins at stops",
14926                                        NULL);
14927     dlg->extend_proteins3 = CheckBox (dlg->protein_options,
14928                                       "Extend retranslated proteins without stops",
14929                                       NULL);
14930     dlg->extend_proteins5 = CheckBox (dlg->protein_options,
14931                                       "Extend retranslated proteins without starts",
14932                                       NULL);
14933     dlg->correct_cds_genes = CheckBox (dlg->protein_options, "Correct CDS genes", NULL);
14934   }
14935   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->keep_protein_ids,
14936                 (HANDLE) dlg->add_cit_subs,
14937                 (HANDLE) dlg->update_quality_scores,
14938                 (HANDLE) dlg->update_proteins,
14939                 (HANDLE) dlg->protein_options,
14940                 NULL);
14941   EnableIndexerOptions (dlg->update_proteins);
14942   return (DialoG) p;
14943 }
14944 
14945 typedef struct updateoptionsdialog
14946 {
14947   DIALOG_MESSAGE_BLOCK
14948   DialoG submitter_opts;
14949   DialoG indexer_opts;
14950 } UpdateOptionsDialogData, PNTR UpdateOptionsDialogPtr;
14951 
UpdateOptionsToDialog(DialoG d,Pointer data)14952 static void UpdateOptionsToDialog (DialoG d, Pointer data)
14953 {
14954   UpdateOptionsDialogPtr dlg;
14955   UpdateOptionsPtr       uop;
14956 
14957   dlg = (UpdateOptionsDialogPtr) GetObjectExtra (d);
14958   if (dlg == NULL)
14959   {
14960     return;
14961   }
14962   uop = (UpdateOptionsPtr) data;
14963   if (uop == NULL)
14964   {
14965     PointerToDialog (dlg->submitter_opts, NULL);
14966     PointerToDialog (dlg->indexer_opts, NULL);
14967   }
14968   else
14969   {
14970     PointerToDialog (dlg->submitter_opts, uop->submitter_opts);
14971     PointerToDialog (dlg->indexer_opts, uop->indexer_opts);
14972   }
14973 }
14974 
UpdateOptionsFromDialog(DialoG d)14975 static Pointer UpdateOptionsFromDialog (DialoG d)
14976 {
14977   UpdateOptionsDialogPtr dlg;
14978   UpdateOptionsPtr       uop;
14979 
14980   dlg = (UpdateOptionsDialogPtr) GetObjectExtra (d);
14981   if (dlg == NULL)
14982   {
14983     return NULL;
14984   }
14985   uop = (UpdateOptionsPtr) MemNew (sizeof (UpdateOptionsData));
14986   if (uop != NULL)
14987   {
14988     uop->submitter_opts = DialogToPointer (dlg->submitter_opts);
14989     if (dlg->indexer_opts == NULL)
14990     {
14991       uop->indexer_opts = NULL;
14992     }
14993     else
14994     {
14995       uop->indexer_opts = DialogToPointer (dlg->indexer_opts);
14996     }
14997   }
14998   return uop;
14999 }
15000 
DisableImportFeatureOptions(DialoG d)15001 static void DisableImportFeatureOptions (DialoG d)
15002 {
15003   UpdateOptionsDialogPtr dlg;
15004 
15005   dlg = (UpdateOptionsDialogPtr) GetObjectExtra (d);
15006   if (dlg == NULL)
15007   {
15008     return;
15009   }
15010   DisableSubmitterImportFeatureOptions (dlg->submitter_opts);
15011 }
15012 
EnableImportFeatureOptions(DialoG d)15013 static void EnableImportFeatureOptions (DialoG d)
15014 {
15015   UpdateOptionsDialogPtr dlg;
15016 
15017   dlg = (UpdateOptionsDialogPtr) GetObjectExtra (d);
15018   if (dlg == NULL)
15019   {
15020     return;
15021   }
15022   EnableSubmitterImportFeatureOptions (dlg->submitter_opts);
15023   EnableIndexerImportFeatureOptions (dlg->indexer_opts);
15024 }
15025 
DisableRemoveFeatureOptions(DialoG d)15026 static void DisableRemoveFeatureOptions (DialoG d)
15027 {
15028   UpdateOptionsDialogPtr dlg;
15029 
15030   dlg = (UpdateOptionsDialogPtr) GetObjectExtra (d);
15031   if (dlg == NULL)
15032   {
15033     return;
15034   }
15035   DisableSubmitterRemoveFeatureOptions (dlg->submitter_opts);
15036 }
15037 
EnableRemoveFeatureOptions(DialoG d)15038 static void EnableRemoveFeatureOptions (DialoG d)
15039 {
15040   UpdateOptionsDialogPtr dlg;
15041 
15042   dlg = (UpdateOptionsDialogPtr) GetObjectExtra (d);
15043   if (dlg == NULL)
15044   {
15045     return;
15046   }
15047   EnableSubmitterRemoveFeatureOptions (dlg->submitter_opts);
15048 }
15049 
15050 static void
AdjustUpdateOptionsEnabled(DialoG d,UpdatePairPtr upp,UpdateAlignmentLengthsPtr ualp,Boolean is_indexer)15051 AdjustUpdateOptionsEnabled
15052 (DialoG                    d,
15053  UpdatePairPtr             upp,
15054  UpdateAlignmentLengthsPtr ualp,
15055  Boolean                   is_indexer)
15056 {
15057   UpdateOptionsDialogPtr dlg;
15058 
15059   dlg = (UpdateOptionsDialogPtr) GetObjectExtra (d);
15060   if (dlg == NULL)
15061   {
15062     return;
15063   }
15064 
15065   AdjustSequenceUpdateOptionsEnabled (dlg->submitter_opts, upp, ualp, is_indexer);
15066 }
15067 
15068 static DialoG
UpdateOptionsDialog(GrouP parent,Boolean is_nuc,Boolean indexer,Boolean do_update,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)15069 UpdateOptionsDialog
15070 (GrouP                parent,
15071  Boolean              is_nuc,
15072  Boolean              indexer,
15073  Boolean              do_update,
15074  Nlm_ChangeNotifyProc change_notify,
15075  Pointer              change_userdata)
15076 {
15077   UpdateOptionsDialogPtr dlg;
15078   GrouP                  p;
15079 
15080   dlg = (UpdateOptionsDialogPtr) MemNew (sizeof (UpdateOptionsDialogData));
15081   if (dlg == NULL)
15082   {
15083     return NULL;
15084   }
15085 
15086   p = HiddenGroup (parent, -1, 0, NULL);
15087   SetObjectExtra (p, dlg, StdCleanupExtraProc);
15088   SetGroupSpacing (p, 10, 10);
15089   dlg->dialog = (DialoG) p;
15090   dlg->todialog = UpdateOptionsToDialog;
15091   dlg->fromdialog = UpdateOptionsFromDialog;
15092 
15093   dlg->submitter_opts = SubmitterUpdateOptionsDialog (p, indexer, do_update, change_notify, change_userdata);
15094   if (indexer)
15095   {
15096     dlg->indexer_opts = IndexerUpdateOptionsDialog (p, is_nuc);
15097   }
15098   else
15099   {
15100     dlg->indexer_opts = NULL;
15101   }
15102 
15103   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->submitter_opts,
15104                               (HANDLE) dlg->indexer_opts,
15105                               NULL);
15106 
15107   return (DialoG) p;
15108 }
15109 
15110 typedef struct previewsequenceselectiondialog
15111 {
15112   DIALOG_MESSAGE_BLOCK
15113   DoC                      doc;
15114   Int4                     sequence_row;
15115   Nlm_ChangeNotifyProc     change_notify;
15116   Pointer                  change_userdata;
15117   ValNodePtr               sequence_list;
15118   ParData                  ParFmt;
15119   ColData                  ColFmt;
15120 
15121 } PreviewSequenceSelectionDialogData, PNTR PreviewSequenceSelectionDialogPtr;
15122 
SelectionToPreviewSequenceSelectionDialog(DialoG d,Pointer userdata)15123 static void SelectionToPreviewSequenceSelectionDialog (DialoG d, Pointer userdata)
15124 {
15125   PreviewSequenceSelectionDialogPtr dlg;
15126   SeqIdPtr                          sip;
15127   Int4                              seq_num, match_num;
15128   ValNodePtr                        vnp;
15129 
15130   dlg = (PreviewSequenceSelectionDialogPtr) GetObjectExtra (d);
15131   if (dlg == NULL) return;
15132 
15133   sip = (SeqIdPtr) userdata;
15134   if (sip == NULL)
15135   {
15136     dlg->sequence_row = -1;
15137   }
15138   else
15139   {
15140     match_num = -1;
15141     for (seq_num = 1, vnp = dlg->sequence_list;
15142          vnp != NULL && match_num < 0;
15143          seq_num++, vnp = vnp->next)
15144     {
15145       if (SeqIdComp (sip, vnp->data.ptrvalue))
15146       {
15147         match_num = seq_num;
15148       }
15149     }
15150     dlg->sequence_row = match_num;
15151   }
15152   InvalDocRows (dlg->doc, 0, 0, 0);
15153 
15154   UpdateDocument(dlg->doc, 0, 0);
15155 
15156   if (dlg->change_notify != NULL)
15157   {
15158     (dlg->change_notify) (dlg->change_userdata);
15159   }
15160 }
15161 
SelectionFromPreviewSequenceSelectionDialog(DialoG d)15162 static Pointer SelectionFromPreviewSequenceSelectionDialog (DialoG d)
15163 {
15164   PreviewSequenceSelectionDialogPtr dlg;
15165   SeqIdPtr                          sip = NULL;
15166   ValNodePtr                        vnp;
15167 
15168   dlg = (PreviewSequenceSelectionDialogPtr) GetObjectExtra (d);
15169   if (dlg != NULL && dlg->sequence_row > 0)
15170   {
15171     vnp = GetNthValNode (dlg->sequence_list, dlg->sequence_row);
15172     if (vnp != NULL)
15173     {
15174       sip = vnp->data.ptrvalue;
15175     }
15176   }
15177   return sip;
15178 }
15179 
ResetSequenceList(DialoG d,ValNodePtr sequence_list)15180 static void ResetSequenceList (DialoG d, ValNodePtr sequence_list)
15181 {
15182   PreviewSequenceSelectionDialogPtr dlg;
15183   Char                              id_txt [MAX_ID_LEN];
15184   SeqIdPtr                          sip;
15185 
15186   dlg = (PreviewSequenceSelectionDialogPtr) GetObjectExtra (d);
15187   if (dlg == NULL) return;
15188 
15189   dlg->sequence_list = ValNodeFree (dlg->sequence_list);
15190   dlg->sequence_list = sequence_list;
15191   Reset (dlg->doc);
15192 
15193   while (sequence_list != NULL)
15194   {
15195     sip = (SeqIdPtr) sequence_list->data.ptrvalue;
15196     if (sip != NULL)
15197     {
15198       /* add to sequence_selector doc */
15199       SeqIdWrite (SeqIdFindBest (sip, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
15200   	  AppendText (dlg->doc, id_txt, &(dlg->ParFmt), &(dlg->ColFmt), programFont);
15201     }
15202     sequence_list = sequence_list->next;
15203   }
15204   InvalDocRows (dlg->doc, 0, 0, 0);
15205   dlg->sequence_row = -1;
15206 }
15207 
SelectPreviewSequence(DoC d,PoinT pt)15208 static void SelectPreviewSequence (DoC d, PoinT pt)
15209 {
15210   Int2      item, row, prevrow;
15211   PreviewSequenceSelectionDialogPtr dlg;
15212 
15213   dlg = (PreviewSequenceSelectionDialogPtr) GetObjectExtra (d);
15214   if (dlg == NULL) return;
15215 
15216   MapDocPoint (d, pt, &item, &row, NULL, NULL);
15217   if (item > 0 && row > 0) {
15218     prevrow = dlg->sequence_row;
15219     dlg->sequence_row = item;
15220     if (item != prevrow)
15221     {
15222       if (prevrow != -1)
15223       {
15224         InvalDocRows (d, prevrow, 1, 1);
15225       }
15226       InvalDocRows (d, item, 1, 1);
15227       if (dlg->change_notify != NULL)
15228       {
15229         (dlg->change_notify) (dlg->change_userdata);
15230       }
15231     }
15232   }
15233 }
15234 
PreviewSequenceHighlight(DoC doc,Int2 item,Int2 row,Int2 col)15235 static Boolean PreviewSequenceHighlight (DoC doc, Int2 item, Int2 row, Int2 col)
15236 {
15237   PreviewSequenceSelectionDialogPtr dlg;
15238 
15239   dlg = (PreviewSequenceSelectionDialogPtr) GetObjectExtra (doc);
15240   if (dlg == NULL) return FALSE;
15241 
15242   if (item == dlg->sequence_row) return TRUE;
15243   return FALSE;
15244 }
15245 
CleanupPreviewSequenceSelectionDialog(GraphiC g,Pointer data)15246 static void CleanupPreviewSequenceSelectionDialog (GraphiC g, Pointer data)
15247 {
15248   PreviewSequenceSelectionDialogPtr dlg;
15249 
15250   dlg = (PreviewSequenceSelectionDialogPtr) data;
15251   if (dlg != NULL)
15252   {
15253     dlg->sequence_list = ValNodeFree (dlg->sequence_list);
15254   }
15255   StdCleanupExtraProc (g, data);
15256 }
15257 
SetPreviewSequenceSelectionByPosition(DialoG d,Int4 seq_pos)15258 static void SetPreviewSequenceSelectionByPosition (DialoG d, Int4 seq_pos)
15259 {
15260   PreviewSequenceSelectionDialogPtr dlg;
15261   Int4                              prevrow, curr_scroll, max_scroll;
15262   BaR                               sb;
15263 
15264   dlg = (PreviewSequenceSelectionDialogPtr) GetObjectExtra (d);
15265   if (dlg == NULL || seq_pos < 0)
15266   {
15267     return;
15268   }
15269 
15270   prevrow = dlg->sequence_row;
15271   dlg->sequence_row = seq_pos + 1;
15272   if (dlg->sequence_row != prevrow)
15273   {
15274     if (prevrow != -1)
15275     {
15276       InvalDocRows (dlg->doc, prevrow, 1, 1);
15277     }
15278     InvalDocRows (dlg->doc, seq_pos + 1, 1, 1);
15279     sb = GetSlateVScrollBar( (SlatE) dlg->doc);
15280     if (sb != NULL)
15281     {
15282       curr_scroll = GetBarValue (sb);
15283       max_scroll = GetBarMax (sb);
15284       if (max_scroll > seq_pos)
15285       {
15286         SetBarValue (sb, seq_pos);
15287       }
15288       else
15289       {
15290         SetBarValue (sb, max_scroll);
15291       }
15292     }
15293     if (dlg->change_notify != NULL)
15294     {
15295       (dlg->change_notify) (dlg->change_userdata);
15296     }
15297   }
15298 }
15299 
15300 static DialoG
PreviewSequenceSelectionDialog(GrouP parent,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)15301 PreviewSequenceSelectionDialog
15302 (GrouP                    parent,
15303  Nlm_ChangeNotifyProc     change_notify,
15304  Pointer                  change_userdata)
15305 {
15306   PreviewSequenceSelectionDialogPtr dlg;
15307   GrouP                             p;
15308   RecT                              r;
15309 
15310   dlg = (PreviewSequenceSelectionDialogPtr) MemNew (sizeof (PreviewSequenceSelectionDialogData));
15311   if (dlg == NULL)
15312   {
15313     return NULL;
15314   }
15315 
15316   p = HiddenGroup (parent, 1, 0, NULL);
15317   SetObjectExtra (p, dlg, CleanupPreviewSequenceSelectionDialog);
15318 
15319   dlg->dialog = (DialoG) p;
15320   dlg->todialog = SelectionToPreviewSequenceSelectionDialog;
15321   dlg->fromdialog = SelectionFromPreviewSequenceSelectionDialog;
15322   dlg->change_notify = change_notify;
15323   dlg->change_userdata = change_userdata;
15324   dlg->sequence_list = NULL;
15325 
15326   dlg->doc = DocumentPanel (p, stdCharWidth * 10, stdLineHeight * 5);
15327   SetObjectExtra (dlg->doc, dlg, NULL);
15328   SetDocProcs (dlg->doc, SelectPreviewSequence, NULL, NULL, NULL);
15329   SetDocShade (dlg->doc, NULL, NULL, PreviewSequenceHighlight, NULL);
15330 
15331   /* initialize document paragraph format */
15332   dlg->ParFmt.openSpace = FALSE;
15333   dlg->ParFmt.keepWithNext = FALSE;
15334   dlg->ParFmt.keepTogether = FALSE;
15335   dlg->ParFmt.newPage = FALSE;
15336   dlg->ParFmt.tabStops = FALSE;
15337   dlg->ParFmt.minLines = 0;
15338   dlg->ParFmt.minHeight = 0;
15339 
15340   /* initialize document column format */
15341   ObjectRect (dlg->doc, &r);
15342   InsetRect (&r, 4, 4);
15343   dlg->ColFmt.pixWidth = r.right - r.left;
15344   dlg->ColFmt.pixInset = 0;
15345   dlg->ColFmt.charWidth = 80;
15346   dlg->ColFmt.charInset = 0;
15347   dlg->ColFmt.font = NULL;
15348   dlg->ColFmt.just = 'l';
15349   dlg->ColFmt.wrap = TRUE;
15350   dlg->ColFmt.bar = FALSE;
15351   dlg->ColFmt.underline = FALSE;
15352   dlg->ColFmt.left = FALSE;
15353   dlg->ColFmt.last = TRUE;
15354 
15355 
15356   return (DialoG) p;
15357 }
15358 
15359 typedef struct unmatchedsequencedialog
15360 {
15361   DIALOG_MESSAGE_BLOCK
15362   DoC      doc;
15363   ParData  ParFmt;
15364   ColData  ColFmt;
15365   Int4     dlg_height;
15366   Int4     selected;
15367 } UnmatchedSequenceDialogData, PNTR UnmatchedSequenceDialogPtr;
15368 
ListToUnmatchedSequenceDialog(DialoG d,Pointer userdata)15369 static void ListToUnmatchedSequenceDialog (DialoG d, Pointer userdata)
15370 {
15371   UnmatchedSequenceDialogPtr dlg;
15372   ValNodePtr                 bioseq_list;
15373   BioseqPtr                  bsp;
15374   Char                       id_txt [MAX_ID_LEN];
15375 
15376   dlg = (UnmatchedSequenceDialogPtr) GetObjectExtra (d);
15377   if (dlg == NULL)
15378   {
15379     return;
15380   }
15381 
15382   Reset (dlg->doc);
15383 
15384   bioseq_list = (ValNodePtr) userdata;
15385   if (bioseq_list == NULL)
15386   {
15387     return;
15388   }
15389 
15390   while (bioseq_list != NULL)
15391   {
15392     bsp = (BioseqPtr) bioseq_list->data.ptrvalue;
15393     if (bsp != NULL)
15394     {
15395       /* add to sequence_selector doc */
15396       SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
15397   	  AppendText (dlg->doc, id_txt, &(dlg->ParFmt), &(dlg->ColFmt), programFont);
15398     }
15399     bioseq_list = bioseq_list->next;
15400   }
15401   InvalDocRows (dlg->doc, 0, 0, 0);
15402 
15403 }
15404 
15405 
15406 /* clicking on a column in the title indicates that we should sort by this column. */
ClickUnmatchedSequence(DoC d,PoinT pt)15407 static void ClickUnmatchedSequence (DoC d, PoinT pt)
15408 {
15409   UnmatchedSequenceDialogPtr dlg;
15410   Int2             item;
15411   Int2             row;
15412   Int2             col;
15413   RecT             r;
15414 
15415   MapDocPoint (d, pt, &item, &row, &col, NULL);
15416   if (item < 1) {
15417     return;
15418   }
15419   dlg = (UnmatchedSequenceDialogPtr) GetObjectExtra (d);
15420   if (dlg == NULL) return;
15421   if (dlg->selected == item) {
15422     dlg->selected = 0;
15423   } else {
15424     dlg->selected = item;
15425   }
15426   /* inval to redraw */
15427   ObjectRect (dlg->doc, &r);
15428   InvalRect (&r);
15429   Update ();
15430 }
15431 
15432 
HighlightUnmatchedSequence(DoC d,Int2 item,Int2 row,Int2 col)15433 static Boolean HighlightUnmatchedSequence (DoC d, Int2 item, Int2 row, Int2 col)
15434 
15435 {
15436   UnmatchedSequenceDialogPtr dlg;
15437 
15438   dlg = (UnmatchedSequenceDialogPtr) GetObjectExtra (d);
15439   if (dlg == NULL) return FALSE;
15440 
15441   if (item == dlg->selected) {
15442     return TRUE;
15443   } else {
15444     return FALSE;
15445   }
15446 }
15447 
15448 
15449 static DialoG
UnmatchedSequenceDialog(GrouP parent,Nlm_BtnActnProc map_btn_proc,Pointer change_userdata,Nlm_BtnActnProc connect_btn_proc)15450 UnmatchedSequenceDialog
15451 (GrouP           parent,
15452  Nlm_BtnActnProc map_btn_proc,
15453  Pointer         change_userdata,
15454  Nlm_BtnActnProc connect_btn_proc)
15455 {
15456   UnmatchedSequenceDialogPtr dlg;
15457   GrouP                      p, button_grp = NULL;
15458   RecT                       r;
15459   PrompT                     ppt = NULL;
15460   ButtoN                     b;
15461 
15462   dlg = (UnmatchedSequenceDialogPtr) MemNew (sizeof (UnmatchedSequenceDialogData));
15463   if (dlg == NULL)
15464   {
15465     return NULL;
15466   }
15467 
15468   p = HiddenGroup (parent, -1, 0, NULL);
15469   SetObjectExtra (p, dlg, StdCleanupExtraProc);
15470 
15471   dlg->dialog = (DialoG) p;
15472   dlg->todialog = ListToUnmatchedSequenceDialog;
15473 
15474   if (map_btn_proc == NULL)
15475   {
15476   	ppt = StaticPrompt (p, "No Updates", 0, 0, programFont, 'l');
15477   }
15478   else
15479   {
15480     ppt = StaticPrompt (p, "Unmatched Sequences", 0, 0, programFont, 'l');
15481   }
15482   dlg->doc = DocumentPanel (p, stdCharWidth * 10, stdLineHeight * 5);
15483   SetObjectExtra (dlg->doc, dlg, NULL);
15484   SetDocProcs (dlg->doc, ClickUnmatchedSequence, NULL, NULL, NULL);
15485   SetDocShade (dlg->doc, NULL, NULL, HighlightUnmatchedSequence, NULL);
15486   dlg->selected = 0;
15487 
15488   /* initialize document paragraph format */
15489   dlg->ParFmt.openSpace = FALSE;
15490   dlg->ParFmt.keepWithNext = FALSE;
15491   dlg->ParFmt.keepTogether = FALSE;
15492   dlg->ParFmt.newPage = FALSE;
15493   dlg->ParFmt.tabStops = FALSE;
15494   dlg->ParFmt.minLines = 0;
15495   dlg->ParFmt.minHeight = 0;
15496 
15497   /* initialize document column format */
15498   ObjectRect (dlg->doc, &r);
15499   dlg->dlg_height = r.bottom - r.top;
15500   InsetRect (&r, 4, 4);
15501   dlg->ColFmt.pixWidth = r.right - r.left;
15502   dlg->ColFmt.pixInset = 0;
15503   dlg->ColFmt.charWidth = 80;
15504   dlg->ColFmt.charInset = 0;
15505   dlg->ColFmt.font = NULL;
15506   dlg->ColFmt.just = 'l';
15507   dlg->ColFmt.wrap = TRUE;
15508   dlg->ColFmt.bar = FALSE;
15509   dlg->ColFmt.underline = FALSE;
15510   dlg->ColFmt.left = FALSE;
15511   dlg->ColFmt.last = TRUE;
15512 
15513 
15514   if (map_btn_proc != NULL || connect_btn_proc != NULL)
15515   {
15516     button_grp = HiddenGroup (p, 2, 0, NULL);
15517     SetGroupSpacing (button_grp, 10, 10);
15518 
15519     if (map_btn_proc != NULL)
15520     {
15521       /* add button for loading map */
15522       b = PushButton (button_grp, "Load Map", map_btn_proc);
15523       SetObjectExtra (b, change_userdata, NULL);
15524     }
15525     if (connect_btn_proc != NULL)
15526     {
15527       /* add button for loading map */
15528       b = PushButton (button_grp, "Map Selected", connect_btn_proc);
15529       SetObjectExtra (b, change_userdata, NULL);
15530     }
15531 
15532     ObjectRect (b, &r);
15533     dlg->dlg_height += 10 + r.bottom - r.top;
15534   }
15535 
15536   AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) dlg->doc, (HANDLE) button_grp, NULL);
15537 
15538   return (DialoG) p;
15539 }
15540 
15541 
GetUnmatchedSequenceDialogSelection(DialoG d)15542 static Int4 GetUnmatchedSequenceDialogSelection (DialoG d)
15543 {
15544   UnmatchedSequenceDialogPtr dlg;
15545 
15546   dlg = (UnmatchedSequenceDialogPtr) GetObjectExtra (d);
15547   if (dlg == NULL) return -1;
15548 
15549   return dlg->selected - 1;
15550 }
15551 
15552 
15553 static void
ChangePreviewSequenceSelectionDialogHeights(DialoG orig_sel,DialoG unmatched,DialoG no_updates,ButtoN remove_identical_btn,Boolean has_identical,WindoW match_win,Boolean show_unmatched,Boolean show_no_updates)15554 ChangePreviewSequenceSelectionDialogHeights
15555 (DialoG orig_sel,
15556  DialoG unmatched,
15557  DialoG no_updates,
15558  ButtoN remove_identical_btn,
15559  Boolean has_identical,
15560  WindoW match_win,
15561  Boolean show_unmatched,
15562  Boolean show_no_updates)
15563 {
15564   PreviewSequenceSelectionDialogPtr orig_sel_dlg;
15565   UnmatchedSequenceDialogPtr        unmatched_dlg, no_updates_dlg;
15566   RecT                              pictures_r, unmatched_r, list_r;
15567   RecT                              no_updates_r, rem_ident_r;
15568   Int4                              no_updates_height;
15569   BaR                               sb;
15570   Int4                              updates_list_bottom;
15571   Int4                              spacing = 0, rem_ident_height = 0;
15572 
15573   orig_sel_dlg = (PreviewSequenceSelectionDialogPtr) GetObjectExtra (orig_sel);
15574   unmatched_dlg = (UnmatchedSequenceDialogPtr) GetObjectExtra (unmatched);
15575   no_updates_dlg = (UnmatchedSequenceDialogPtr) GetObjectExtra (no_updates);
15576   if (orig_sel_dlg == NULL || unmatched_dlg == NULL
15577       || no_updates_dlg == NULL)
15578   {
15579     return;
15580   }
15581 
15582   ObjectRect (orig_sel_dlg->doc, &list_r);
15583   ObjectRect (unmatched_dlg->doc, &unmatched_r);
15584   ObjectRect (no_updates_dlg->doc, &no_updates_r);
15585   if (match_win == NULL)
15586   {
15587     pictures_r.top = list_r.top;
15588     pictures_r.left = list_r.right;
15589     pictures_r.right = list_r.right;
15590     pictures_r.bottom = no_updates_r.bottom;
15591   }
15592   else
15593   {
15594     ObjectRect (match_win, &pictures_r);
15595   }
15596 
15597   if (remove_identical_btn != NULL && has_identical)
15598   {
15599     ObjectRect (remove_identical_btn, &rem_ident_r);
15600     rem_ident_height = rem_ident_r.bottom - rem_ident_r.top;
15601     spacing = 5;
15602   }
15603 
15604   /* updates list is on top,
15605    * followed by remove_identical_btn,
15606    * followed by unmatched list,
15607    * followed by no updates list */
15608   updates_list_bottom = pictures_r.bottom;
15609 
15610   if (show_no_updates)
15611   {
15612     /* align no updates list with bottom of preview pictures */
15613     no_updates_height = no_updates_r.bottom - no_updates_r.top;
15614     no_updates_r.bottom = updates_list_bottom;
15615     no_updates_r.top = no_updates_r.bottom - no_updates_height;
15616     sb = GetSlateVScrollBar( (SlatE) no_updates_dlg->doc);
15617     if (sb != NULL)
15618     {
15619       /* because the doc has a vertical scroll bar and the set position subtracts the
15620        * width of the scroll bar before positioning the list, must add the width of
15621        * the scroll bar to the rightt.
15622        */
15623       no_updates_r.right += Nlm_vScrollBarWidth;
15624     }
15625     SetPosition (no_updates, &no_updates_r);
15626     updates_list_bottom -= (no_updates_dlg->dlg_height + 10);
15627     Show (no_updates);
15628   }
15629   else
15630   {
15631   	Hide (no_updates);
15632   }
15633 
15634   if (show_unmatched)
15635   {
15636     /* align unmatched list with bottom of updates list or preview pictures */
15637     unmatched_r.bottom = updates_list_bottom ;
15638     unmatched_r.top = unmatched_r.bottom - unmatched_dlg->dlg_height;
15639 
15640     sb = GetSlateVScrollBar( (SlatE) unmatched_dlg->doc);
15641     if (sb != NULL)
15642     {
15643       /* because the doc has a vertical scroll bar and the set position subtracts the
15644        * width of the scroll bar before positioning the list, must add the width of
15645        * the scroll bar to the rightt.
15646        */
15647       unmatched_r.right += Nlm_vScrollBarWidth;
15648     }
15649     SetPosition (unmatched, &unmatched_r);
15650     updates_list_bottom -= (unmatched_dlg->dlg_height + 10);
15651     Show (unmatched);
15652   }
15653   else
15654   {
15655   	Hide (unmatched);
15656   }
15657 
15658   /* set position of sequence list - align top with pictures,
15659    * align bottom with top of unmatched (if shown) or
15660    * bottom of pictures
15661    */
15662   list_r.top = pictures_r.top;
15663   list_r.bottom = updates_list_bottom - spacing - rem_ident_height;
15664 
15665   sb = GetSlateVScrollBar( (SlatE) orig_sel_dlg->doc);
15666   if (sb != NULL)
15667   {
15668     /* because the doc has a vertical scroll bar and the set position subtracts the
15669      * width of the scroll bar before positioning the list, must add the width of
15670      * the scroll bar to the rightt.
15671      */
15672     list_r.right += Nlm_vScrollBarWidth;
15673   }
15674   SetPosition (orig_sel_dlg->doc, &list_r);
15675 
15676   if (remove_identical_btn != NULL)
15677   {
15678     if (has_identical)
15679     {
15680       /* set position of remove identical btn */
15681       rem_ident_r.top = updates_list_bottom - rem_ident_height;
15682       rem_ident_r.bottom = rem_ident_r.top + rem_ident_height;
15683       SetPosition (remove_identical_btn, &rem_ident_r);
15684       Show (remove_identical_btn);
15685     }
15686     else
15687     {
15688       /* hide button */
15689       SafeHide (remove_identical_btn);
15690     }
15691   }
15692 }
15693 
15694 typedef struct multisequenceupdatepreviewdialog
15695 {
15696   DIALOG_MESSAGE_BLOCK
15697 
15698   DialoG               update_list_dlg;
15699   DialoG               preview_dlg;
15700   DialoG               unmatched_list_dlg;
15701   DialoG               no_updates_list_dlg;
15702   DialoG               extend_preview_dlg;
15703   ButtoN               remove_identical_btn;
15704   WindoW               match_win;
15705   ValNodePtr           orig_bioseq_list;
15706   ValNodePtr           update_bioseq_list;
15707   Boolean              is_na;
15708   Nlm_ChangeNotifyProc change_notify;
15709   Pointer              change_userdata;
15710 
15711 } MultiSequenceUpdatePreviewDialogData, PNTR MultiSequenceUpdatePreviewDialogPtr;
15712 
15713 
15714 typedef struct multisequenceupdate
15715 {
15716   ValNodePtr  orig_bioseq_list;
15717   ValNodePtr  update_bioseq_list;
15718   ValNodePtr  unmatched_updates_list;
15719   ValNodePtr  no_updates_list;
15720 } MultiSequenceUpdateData, PNTR MultiSequenceUpdatePtr;
15721 
SelectSequenceForUpdatePreview(Pointer userdata)15722 static void SelectSequenceForUpdatePreview (Pointer userdata)
15723 {
15724   MultiSequenceUpdatePreviewDialogPtr dlg;
15725   UpdatePairData                      upd;
15726   ValNodePtr                          update_vnp;
15727   SeqIdPtr                            sip;
15728   Int4                                orig_pos = -1;
15729 
15730   dlg = (MultiSequenceUpdatePreviewDialogPtr) userdata;
15731   if (dlg == NULL)
15732   {
15733     return;
15734   }
15735 
15736   sip = (SeqIdPtr) DialogToPointer (dlg->dialog);
15737 
15738   upd.orig_bsp = FindBioseqInList (dlg->orig_bioseq_list, sip, &orig_pos);
15739 
15740   update_vnp = GetNthValNode (dlg->update_bioseq_list, orig_pos + 1);
15741   if (update_vnp != NULL)
15742   {
15743     upd.update_bsp = update_vnp->data.ptrvalue;
15744   }
15745   else
15746   {
15747     upd.update_bsp = NULL;
15748   }
15749 
15750   SeqMgrReplaceInBioseqIndex (upd.orig_bsp);
15751 
15752   upd.revcomp = FALSE;
15753   upd.salp = Sqn_AlignForSequenceUpdate (upd.orig_bsp, upd.update_bsp, &(upd.revcomp));
15754 
15755   if (upd.revcomp)
15756   {
15757     BioseqRevComp (upd.update_bsp);
15758     ReverseBioseqFeatureStrands (upd.update_bsp);
15759     SeqMgrReplaceInBioseqIndex (upd.update_bsp);
15760   }
15761 
15762   PointerToDialog (dlg->preview_dlg, &upd);
15763   PointerToDialog (dlg->extend_preview_dlg, &upd);
15764 
15765   SeqMgrReplaceInBioseqIndex (upd.orig_bsp);
15766 
15767   if (dlg->change_notify != NULL)
15768   {
15769     (dlg->change_notify) (dlg->change_userdata);
15770   }
15771 }
15772 
SeqIdListFromBioseqList(ValNodePtr bioseq_list)15773 static ValNodePtr SeqIdListFromBioseqList (ValNodePtr bioseq_list)
15774 {
15775   ValNodePtr sip_list = NULL;
15776   Int4       seq_num = 0;
15777   BioseqPtr  bsp;
15778 
15779   while (bioseq_list != NULL)
15780   {
15781     if (bioseq_list->data.ptrvalue == NULL)
15782     {
15783       ValNodeAddPointer (&sip_list, seq_num, NULL);
15784     }
15785     else
15786     {
15787       bsp = (BioseqPtr) bioseq_list->data.ptrvalue;
15788       ValNodeAddPointer (&sip_list, seq_num, bsp->id);
15789     }
15790     seq_num++;
15791     bioseq_list = bioseq_list->next;
15792   }
15793   return sip_list;
15794 }
15795 
HasIdenticalUpdates(ValNodePtr orig_list,ValNodePtr update_list)15796 static Boolean HasIdenticalUpdates
15797 (ValNodePtr orig_list,
15798  ValNodePtr update_list)
15799 {
15800   BioseqPtr  orig_bsp, update_bsp;
15801 
15802   while (orig_list != NULL && update_list != NULL)
15803   {
15804     orig_bsp = orig_list->data.ptrvalue;
15805     update_bsp = update_list->data.ptrvalue;
15806 
15807     if (orig_bsp != NULL && update_bsp != NULL
15808         && AreSequenceResiduesIdentical (orig_bsp, update_bsp))
15809     {
15810       return TRUE;
15811     }
15812 
15813     orig_list = orig_list->next;
15814     update_list = update_list->next;
15815   }
15816 
15817   return FALSE;
15818 }
15819 
DataToMultiSequenceUpdatePreview(DialoG d,Pointer data)15820 static void DataToMultiSequenceUpdatePreview (DialoG d, Pointer data)
15821 {
15822   MultiSequenceUpdatePreviewDialogPtr dlg;
15823   MultiSequenceUpdatePtr              msup;
15824   BioseqPtr                           first_bsp;
15825   ValNodePtr                          unmatched_updates_list = NULL;
15826   ValNodePtr                          no_updates_list = NULL;
15827   Boolean                             has_identical = FALSE;
15828 
15829   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
15830   if (dlg == NULL)
15831   {
15832     return;
15833   }
15834 
15835   msup = (MultiSequenceUpdatePtr) data;
15836   if (msup == NULL)
15837   {
15838     dlg->orig_bioseq_list = NULL;
15839     dlg->update_bioseq_list = NULL;
15840   }
15841   else
15842   {
15843     dlg->orig_bioseq_list = msup->orig_bioseq_list;
15844     dlg->update_bioseq_list = msup->update_bioseq_list;
15845     unmatched_updates_list = msup->unmatched_updates_list;
15846     no_updates_list = msup->no_updates_list;
15847   }
15848 
15849   ResetSequenceList (dlg->update_list_dlg, SeqIdListFromBioseqList(dlg->orig_bioseq_list));
15850   PointerToDialog (dlg->unmatched_list_dlg, unmatched_updates_list);
15851   PointerToDialog (dlg->no_updates_list_dlg, no_updates_list);
15852 
15853   if (dlg->remove_identical_btn != NULL)
15854   {
15855     has_identical = HasIdenticalUpdates (dlg->orig_bioseq_list, dlg->update_bioseq_list);
15856   }
15857 
15858   ChangePreviewSequenceSelectionDialogHeights (dlg->update_list_dlg,
15859                                                dlg->unmatched_list_dlg,
15860                                                dlg->no_updates_list_dlg,
15861                                                dlg->remove_identical_btn,
15862                                                has_identical,
15863                                                dlg->match_win,
15864                                                (unmatched_updates_list != NULL),
15865                                                (no_updates_list != NULL));
15866 
15867   /* select first sequence */
15868   if (dlg->orig_bioseq_list != NULL && dlg->orig_bioseq_list->data.ptrvalue != NULL)
15869   {
15870     first_bsp = (BioseqPtr) dlg->orig_bioseq_list->data.ptrvalue;
15871 
15872     PointerToDialog (dlg->update_list_dlg, first_bsp->id);
15873     SelectSequenceForUpdatePreview (dlg);
15874   }
15875   else
15876   {
15877     if (dlg->change_notify != NULL)
15878     {
15879       (dlg->change_notify) (dlg->change_userdata);
15880     }
15881   }
15882 }
15883 
15884 /* returns SeqID currently selected in preview list */
SelectionFromMultiSequenceUpdatePreview(DialoG d)15885 static Pointer SelectionFromMultiSequenceUpdatePreview (DialoG d)
15886 {
15887   MultiSequenceUpdatePreviewDialogPtr dlg;
15888   ValNodePtr                          orig_vnp, update_vnp;
15889   BioseqPtr                           orig_bsp;
15890   SeqIdPtr                            return_sip = NULL;
15891 
15892   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
15893   if (dlg == NULL)
15894   {
15895     return NULL;
15896   }
15897 
15898   if (dlg->update_list_dlg == NULL)
15899   {
15900     for (orig_vnp = dlg->orig_bioseq_list, update_vnp = dlg->update_bioseq_list;
15901          orig_vnp != NULL && update_vnp != NULL && return_sip == NULL;
15902          orig_vnp = orig_vnp->next, update_vnp = update_vnp->next)
15903     {
15904       if (orig_vnp->data.ptrvalue == NULL || update_vnp->data.ptrvalue == NULL)
15905       {
15906         continue;
15907       }
15908       orig_bsp = (BioseqPtr) orig_vnp->data.ptrvalue;
15909       return_sip = SeqIdDup (orig_bsp->id);
15910     }
15911   }
15912   else
15913   {
15914     return_sip = DialogToPointer (dlg->update_list_dlg);
15915   }
15916   return return_sip;
15917 }
15918 
SelectUpdatePreviewSequenceByPosition(DialoG d,Int4 seq_pos)15919 static void SelectUpdatePreviewSequenceByPosition (DialoG d, Int4 seq_pos)
15920 {
15921   MultiSequenceUpdatePreviewDialogPtr dlg;
15922 
15923   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
15924   if (dlg == NULL)
15925   {
15926     return;
15927   }
15928 
15929   SetPreviewSequenceSelectionByPosition (dlg->update_list_dlg, seq_pos);
15930 }
15931 
GetCurrentUpdatePair(DialoG d)15932 static UpdatePairPtr GetCurrentUpdatePair (DialoG d)
15933 {
15934   MultiSequenceUpdatePreviewDialogPtr dlg;
15935 
15936   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
15937   if (dlg == NULL)
15938   {
15939     return NULL;
15940   }
15941 
15942   return (UpdatePairPtr) DialogToPointer (dlg->preview_dlg);
15943 }
15944 
AddExtendDialogToMultiSequenceUpdatePreview(DialoG msup,DialoG ext)15945 static void AddExtendDialogToMultiSequenceUpdatePreview (DialoG msup, DialoG ext)
15946 {
15947   MultiSequenceUpdatePreviewDialogPtr dlg;
15948 
15949   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (msup);
15950   if (dlg != NULL)
15951   {
15952     dlg->extend_preview_dlg = ext;
15953   }
15954 }
15955 
15956 static void RemoveIdenticalUpdates (ButtoN b);
15957 
SetMultiSequenceUpdatePreviewMatchWindow(DialoG d,WindoW w)15958 static void SetMultiSequenceUpdatePreviewMatchWindow (DialoG d, WindoW w)
15959 {
15960   MultiSequenceUpdatePreviewDialogPtr dlg;
15961 
15962   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
15963   if (dlg != NULL)
15964   {
15965     dlg->match_win = w;
15966   }
15967 }
15968 
SetIgnoreAndExtendForMultiSequencePreview(DialoG d,Boolean ignore_alignment,Boolean extend5)15969 static void SetIgnoreAndExtendForMultiSequencePreview (DialoG d, Boolean ignore_alignment, Boolean extend5)
15970 {
15971   MultiSequenceUpdatePreviewDialogPtr dlg;
15972 
15973   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
15974   if (dlg != NULL)
15975   {
15976     SetIgnoreAndExtendForPreviewPictures (dlg->preview_dlg, ignore_alignment, extend5);
15977   }
15978 }
15979 
15980 static DialoG
MultiSequenceUpdatePreview(GrouP parent,Boolean is_na,Boolean do_update,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata,Nlm_BtnActnProc map_btn_proc,Nlm_BtnActnProc connect_btn_proc,Boolean is_indexer)15981 MultiSequenceUpdatePreview
15982 (GrouP                parent,
15983  Boolean              is_na,
15984  Boolean              do_update,
15985  Nlm_ChangeNotifyProc change_notify,
15986  Pointer              change_userdata,
15987  Nlm_BtnActnProc      map_btn_proc,
15988  Nlm_BtnActnProc      connect_btn_proc,
15989  Boolean              is_indexer)
15990 {
15991   MultiSequenceUpdatePreviewDialogPtr dlg;
15992   GrouP                               p, k;
15993 
15994   dlg = (MultiSequenceUpdatePreviewDialogPtr) MemNew (sizeof (MultiSequenceUpdatePreviewDialogData));
15995   if (dlg == NULL)
15996   {
15997     return NULL;
15998   }
15999 
16000   if (do_update)
16001   {
16002     p = HiddenGroup (parent, 0, 1, NULL);
16003   }
16004   else
16005   {
16006     p = HiddenGroup (parent, -1, 0, NULL);
16007   }
16008   SetObjectExtra (p, dlg, StdCleanupExtraProc);
16009   SetGroupSpacing (p, 10, 10);
16010 
16011   dlg->dialog = (DialoG) p;
16012   dlg->todialog = DataToMultiSequenceUpdatePreview;
16013   dlg->fromdialog = SelectionFromMultiSequenceUpdatePreview;
16014 
16015   dlg->is_na = is_na;
16016 
16017   dlg->change_notify = change_notify;
16018   dlg->change_userdata = change_userdata;
16019 
16020   if (is_indexer)
16021   {
16022     k = HiddenGroup (p, 0, 4, NULL);
16023     /* note - the ValNodeSelectionDialog will free the seq_id list when done */
16024     dlg->update_list_dlg = PreviewSequenceSelectionDialog (k, SelectSequenceForUpdatePreview,
16025                                                            dlg);
16026     if (do_update && is_indexer)
16027     {
16028       dlg->remove_identical_btn = PushButton (k, "Remove Identical Updates", RemoveIdenticalUpdates);
16029       SetObjectExtra (dlg->remove_identical_btn, change_userdata, NULL);
16030     }
16031 
16032     dlg->unmatched_list_dlg = UnmatchedSequenceDialog (k, map_btn_proc, change_userdata, connect_btn_proc);
16033 
16034     dlg->no_updates_list_dlg = UnmatchedSequenceDialog (k, NULL, NULL, NULL);
16035   }
16036 
16037   dlg->extend_preview_dlg = NULL;
16038   if (do_update)
16039   {
16040     dlg->preview_dlg = UpdatePreviewDialog (p, is_indexer);
16041     dlg->match_win = (WindoW) dlg->preview_dlg;
16042   }
16043   else
16044   {
16045     dlg->preview_dlg = NULL;
16046     dlg->match_win = NULL;
16047   }
16048 
16049   return (DialoG) p;
16050 }
16051 
16052 
GetMultiSequenceUpdatePreviewUnmatchedSelection(DialoG d)16053 static Int4 GetMultiSequenceUpdatePreviewUnmatchedSelection (DialoG d)
16054 {
16055   MultiSequenceUpdatePreviewDialogPtr dlg;
16056 
16057   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
16058   if (dlg != NULL)
16059   {
16060     return GetUnmatchedSequenceDialogSelection (dlg->unmatched_list_dlg);
16061   } else {
16062     return -1;
16063   }
16064 }
16065 
16066 
GetMultiSequenceUpdatePreviewNoUpdateSelection(DialoG d)16067 static Int4 GetMultiSequenceUpdatePreviewNoUpdateSelection (DialoG d)
16068 {
16069   MultiSequenceUpdatePreviewDialogPtr dlg;
16070 
16071   dlg = (MultiSequenceUpdatePreviewDialogPtr) GetObjectExtra (d);
16072   if (dlg != NULL)
16073   {
16074     return GetUnmatchedSequenceDialogSelection (dlg->no_updates_list_dlg);
16075   } else {
16076     return -1;
16077   }
16078 }
16079 
16080 
ExtractSequencesWithoutUpdates(ValNodePtr PNTR orig_bioseq_list,ValNodePtr PNTR update_bioseq_list)16081 static ValNodePtr ExtractSequencesWithoutUpdates (ValNodePtr PNTR orig_bioseq_list, ValNodePtr PNTR update_bioseq_list)
16082 {
16083   ValNodePtr orig_prev = NULL, update_prev = NULL;
16084   ValNodePtr orig_next = NULL, update_next = NULL;
16085   ValNodePtr orig_vnp, update_vnp;
16086   ValNodePtr no_update_list = NULL;
16087   Int4       seq_num;
16088 
16089   if (orig_bioseq_list == NULL || update_bioseq_list == NULL
16090       || *orig_bioseq_list == NULL || *update_bioseq_list == NULL)
16091   {
16092     return NULL;
16093   }
16094 
16095   orig_vnp = *orig_bioseq_list;
16096   update_vnp = *update_bioseq_list;
16097 
16098   while (orig_vnp != NULL && update_vnp != NULL)
16099   {
16100     orig_next = orig_vnp->next;
16101     update_next = update_vnp->next;
16102     if (orig_vnp->data.ptrvalue == NULL || update_vnp->data.ptrvalue == NULL)
16103     {
16104       if (orig_prev == NULL || update_prev == NULL)
16105       {
16106         *orig_bioseq_list = orig_vnp->next;
16107         *update_bioseq_list = update_vnp->next;
16108       }
16109       else
16110       {
16111         orig_prev->next = orig_vnp->next;
16112         update_prev->next = update_vnp->next;
16113       }
16114       orig_vnp->next = NULL;
16115       update_vnp->next = NULL;
16116       if (orig_vnp->data.ptrvalue == NULL)
16117       {
16118         ValNodeFree (orig_vnp);
16119       }
16120       else
16121       {
16122       	ValNodeLink (&no_update_list, orig_vnp);
16123       }
16124 
16125       ValNodeFree (update_vnp);
16126     }
16127     else
16128     {
16129       orig_prev = orig_vnp;
16130       update_prev = update_vnp;
16131     }
16132 
16133     orig_vnp = orig_next;
16134     update_vnp = update_next;
16135   }
16136 
16137   for (orig_vnp = *orig_bioseq_list, update_vnp = *update_bioseq_list, seq_num = 0;
16138        orig_vnp != NULL && update_vnp != NULL;
16139        orig_vnp = orig_vnp->next, update_vnp = update_vnp->next, seq_num++)
16140   {
16141     orig_vnp->choice = seq_num;
16142     update_vnp->choice = seq_num;
16143   }
16144   return no_update_list;
16145 }
16146 
ReadASNUpdateSequences(FILE * fp,BoolPtr chars_stripped)16147 static SeqEntryPtr ReadASNUpdateSequences (FILE *fp, BoolPtr chars_stripped)
16148 {
16149   Pointer      dataptr;
16150   Uint2        datatype;
16151   SeqEntryPtr  sep = NULL;
16152   SeqSubmitPtr ssp;
16153 
16154   /* Read in one sequence from the file */
16155   dataptr = ReadAsnFastaOrFlatFileEx (fp, &datatype, NULL, FALSE, FALSE,
16156 		                   	                  TRUE, FALSE, chars_stripped);
16157 
16158   if (NULL == dataptr)
16159   {
16160     return NULL;
16161   }
16162 
16163   /* Convert the file data to a SeqEntry */
16164 
16165   if (datatype == OBJ_SEQENTRY)
16166     sep = (SeqEntryPtr) dataptr;
16167   else if (datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET)
16168     sep = SeqMgrGetSeqEntryForData (dataptr);
16169   else if (datatype == OBJ_SEQSUB)
16170   {
16171     ssp = (SeqSubmitPtr) dataptr;
16172     if (ssp != NULL && ssp->datatype == 1)
16173     {
16174       sep = (SeqEntryPtr) ssp->data;
16175     }
16176   }
16177   return sep;
16178 }
16179 
16180 
ListIds(SeqEntryPtr sep_list)16181 static ValNodePtr ListIds (SeqEntryPtr sep_list)
16182 {
16183   BioseqPtr    bsp;
16184   BioseqSetPtr bssp;
16185   SeqEntryPtr  s;
16186   SeqIdPtr     sip;
16187   Char         id_txt[PATH_MAX];
16188   ValNodePtr   list = NULL;
16189 
16190   while (sep_list != NULL) {
16191     if (IS_Bioseq(sep_list) && (bsp = (BioseqPtr) sep_list->data.ptrvalue) != NULL) {
16192       for (sip = bsp->id; sip != NULL; sip = sip->next) {
16193         SeqIdWrite (sip, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
16194         ValNodeAddPointer (&list, 0, StringSave(id_txt));
16195       }
16196     } else if (IS_Bioseq_set(sep_list) || (bssp = (BioseqSetPtr) sep_list->data.ptrvalue) == NULL) {
16197       for (s = bssp->seq_set; s != NULL; s = s->next) {
16198         ValNodeLink (&list, ListIds(s));
16199       }
16200     }
16201     sep_list = sep_list->next;
16202   }
16203   return list;
16204 }
16205 
16206 
HasDuplicateIds(SeqEntryPtr sep_list)16207 static Boolean HasDuplicateIds (SeqEntryPtr sep_list)
16208 {
16209   ValNodePtr list;
16210   Int4 num_before, num_after;
16211 
16212   list = ListIds(sep_list);
16213   num_before = ValNodeLen (list);
16214   list = ValNodeSort (list, SortVnpByString);
16215   ValNodeUnique(&list, SortVnpByString, ValNodeFreeData);
16216   num_after = ValNodeLen (list);
16217   list = ValNodeFreeData (list);
16218   if (num_after != num_before) {
16219     return TRUE;
16220   } else {
16221     return FALSE;
16222   }
16223 }
16224 
16225 
ReadUpdateSequences(Boolean is_na,Boolean from_clipboard)16226 static SeqEntryPtr ReadUpdateSequences (Boolean is_na, Boolean from_clipboard)
16227 {
16228   FILE          *fp;
16229   Char          path [PATH_MAX];
16230   SeqEntryPtr   sep_list;
16231   ValNodePtr    err_msg_list = NULL;
16232   BioseqSetPtr  top_bssp;
16233   BioseqPtr     bsp;
16234   Uint2         entityID;
16235   Boolean       chars_stripped = FALSE;
16236   CharPtr       str;
16237 
16238   if (from_clipboard) {
16239     if (!Nlm_ClipboardHasString()) {
16240       Message (MSG_ERROR, "Clipboard is empty!");
16241       return NULL;
16242     }
16243     TmpNam (path);
16244     fp = FileOpen (path, "w");
16245     str = ClipboardToString();
16246     fprintf (fp, "%s", str);
16247     FileClose (fp);
16248     str = MemFree (str);
16249   } else if (! GetInputFileName (path, sizeof (path),"","TEXT")) {
16250     return NULL;
16251   }
16252   fp = FileOpen (path, "r");
16253   if (fp == NULL)
16254   {
16255     Message (MSG_ERROR, "Unable to open %s", path);
16256     return NULL;
16257   }
16258   sep_list = ImportSequencesFromFileEx (fp, NULL, is_na, TRUE, NULL, &err_msg_list, &chars_stripped, TRUE);
16259   ValNodeFreeData (err_msg_list);
16260   FileClose (fp);
16261   if (HasDuplicateIds(sep_list)) {
16262     Message (MSG_ERROR, "Non-unique sequence IDs in update sequences!");
16263     return NULL;
16264   }
16265 
16266   AddUniqueUpdateSequenceIDs (sep_list);
16267 
16268   if (sep_list == NULL)
16269   {
16270     fp = FileOpen (path, "r");
16271     sep_list = ReadASNUpdateSequences (fp, &chars_stripped);
16272     FileClose (fp);
16273     if (from_clipboard) {
16274         FileRemove (path);
16275     }
16276 
16277     if (sep_list == NULL)
16278     {
16279       Message (MSG_ERROR, "Unable to read sequences from %s, please check formatting", path);
16280       return NULL;
16281     }
16282     else if (chars_stripped)
16283     {
16284       if (ANS_CANCEL == Message (MSG_OKC, "Illegal characters will be stripped from your sequence data.  Do you want to continue?"))
16285       {
16286         sep_list = SeqEntryFree (sep_list);
16287         return NULL;
16288       }
16289     }
16290 
16291     if (sep_list->choice == 1)
16292     {
16293       bsp = (BioseqPtr) sep_list->data.ptrvalue;
16294       entityID = ObjMgrGetEntityIDForPointer (bsp);
16295     }
16296     else
16297     {
16298       top_bssp = (BioseqSetPtr) sep_list->data.ptrvalue;
16299       entityID = ObjMgrGetEntityIDForPointer (top_bssp);
16300     }
16301     AddUniqueUpdateSequenceIDs (sep_list);
16302   }
16303   else if (sep_list != NULL)
16304   {
16305     if (from_clipboard) {
16306       FileRemove (path);
16307     }
16308     if (chars_stripped)
16309     {
16310       if (ANS_CANCEL == Message (MSG_OKC, "Illegal characters will be stripped from your sequence data.  Do you want to continue?"))
16311       {
16312         sep_list = SeqEntryFree (sep_list);
16313         return NULL;
16314       }
16315     }
16316     top_bssp = BioseqSetNew ();
16317     top_bssp->_class = BioseqseqSet_class_genbank;
16318     top_bssp->seq_set = sep_list;
16319     sep_list = SeqEntryNew ();
16320     sep_list->choice = 2;
16321     sep_list->data.ptrvalue = top_bssp;
16322     entityID = ObjMgrGetEntityIDForPointer (top_bssp);
16323   }
16324 
16325   AssignIDsInEntityEx (entityID, 0, NULL, NULL);
16326   SeqMgrIndexFeatures (entityID, NULL);
16327 
16328   return sep_list;
16329 }
16330 
16331 typedef struct updatemultisequenceform
16332 {
16333   FORM_MESSAGE_BLOCK
16334   DialoG     update_preview;
16335   DialoG     options_dialog;
16336   DialoG     titles_dlg;
16337   ButtoN     update_this;
16338   ButtoN     skip_this;
16339   ValNodePtr orig_bioseq_list;
16340   ValNodePtr update_bioseq_list;
16341   ValNodePtr unmatched_updates_list;
16342   ValNodePtr no_updates_list;
16343   Boolean    is_na;
16344   LogInfoPtr lip;
16345   Int4       num_successful;
16346   Int4       num_failed;
16347   Int4       num_skipped;
16348   Char       undo_file [PATH_MAX];
16349   ValNodePtr update_entityID_list;  /* This list is used to remove sequences and sets loaded for update */
16350 } UpdateMultiSequenceFormData, PNTR UpdateMultiSequenceFormPtr;
16351 
16352 
DoTestUpdateOneSequence(ButtoN b)16353 static void DoTestUpdateOneSequence (ButtoN b)
16354 {
16355   UpdateMultiSequenceFormPtr usfp;
16356   SeqIdPtr              sip;
16357   Char                  id_txt [MAX_ID_LEN];
16358   Int4                  orig_pos;
16359   ValNodePtr            orig_vnp, update_vnp;
16360   MultiSequenceUpdateData  msud;
16361   Boolean                  update_successful = FALSE;
16362   UpdateAlignmentLengthsData uald;
16363   UpdateOptionsPtr           uop;
16364   UpdatePairData             upd;
16365   Uint2                      update_entityID = 0;
16366   BioseqPtr                  update_bsp = NULL;
16367 
16368   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (b);
16369   if (usfp == NULL)
16370   {
16371     return;
16372   }
16373 
16374   sip = DialogToPointer (usfp->update_preview);
16375   if (sip == NULL)
16376   {
16377     Message (MSG_ERROR, "No sequence selected!");
16378     return;
16379   }
16380 
16381   uop = DialogToPointer (usfp->options_dialog);
16382   if (uop == NULL || !AreSubmitterOptsValid(uop->submitter_opts))
16383   {
16384     Message (MSG_ERROR, "Invalid options selected!");
16385     uop = UpdateOptionsFree (uop);
16386     return;
16387   }
16388 
16389 
16390   WatchCursor ();
16391   Update ();
16392 
16393   SeqIdWrite (sip, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
16394 
16395   upd.orig_bsp = FindBioseqInList (usfp->orig_bioseq_list, sip, &orig_pos);
16396   if (upd.orig_bsp != NULL)
16397   {
16398     upd.update_bsp = NULL;
16399     update_vnp = GetNthValNode (usfp->update_bioseq_list, orig_pos + 1);
16400     if (update_vnp != NULL)
16401     {
16402       upd.update_bsp = update_vnp->data.ptrvalue;
16403       update_entityID = upd.update_bsp->idx.entityID;
16404       update_bsp = upd.update_bsp;
16405     }
16406 
16407     /* if we are going to ignore the alignment, don't calculate it */
16408     if (uop->submitter_opts->ignore_alignment)
16409     {
16410       upd.revcomp = FALSE;
16411       upd.salp = NULL;
16412     }
16413     else
16414     {
16415       upd.revcomp = FALSE;
16416       upd.salp = Sqn_AlignForSequenceUpdate (upd.orig_bsp, upd.update_bsp, &(upd.revcomp));
16417     }
16418 
16419     CalculateUpdateAlignmentLengths (upd.salp, upd.orig_bsp, upd.update_bsp, &uald);
16420     update_successful = UpdateOrExtendOneSequence (&upd, uop, &uald,
16421                                                    usfp->input_entityID,
16422                                                    usfp->lip == NULL ? NULL : usfp->lip->fp,
16423                                                    usfp->lip == NULL ? NULL : &(usfp->lip->data_in_log));
16424 	  upd.salp = SeqAlignFree (upd.salp);
16425   }
16426   uop = UpdateOptionsFree (uop);
16427 
16428   if (update_successful)
16429   {
16430     /* remove sequence and its pair from list */
16431     orig_vnp = ExtractNthValNode (&(usfp->orig_bioseq_list), orig_pos);
16432     orig_vnp = ValNodeFree (orig_vnp);
16433     update_vnp = ExtractNthValNode (&(usfp->update_bioseq_list), orig_pos);
16434     update_vnp = ValNodeFree (update_vnp);
16435 
16436     /* don't delete update sequence until update dialog closes */
16437 
16438     /* renumber valnode lists */
16439     for (orig_vnp = usfp->orig_bioseq_list; orig_vnp != NULL; orig_vnp = orig_vnp->next)
16440     {
16441       if (orig_vnp->choice > orig_pos)
16442       {
16443         orig_vnp->choice --;
16444       }
16445     }
16446     for (update_vnp = usfp->update_bioseq_list; update_vnp != NULL; update_vnp = update_vnp->next)
16447     {
16448       if (update_vnp->choice > orig_pos)
16449       {
16450         update_vnp->choice --;
16451       }
16452     }
16453 
16454     /* only update the preview if we have any sequences left to update
16455      * otherwise we get a flash of a strange result
16456      */
16457     if (usfp->orig_bioseq_list != NULL)
16458     {
16459       msud.orig_bioseq_list = usfp->orig_bioseq_list;
16460       msud.update_bioseq_list = usfp->update_bioseq_list;
16461       msud.unmatched_updates_list = usfp->unmatched_updates_list;
16462       msud.no_updates_list = usfp->no_updates_list;
16463       PointerToDialog (usfp->update_preview, &msud);
16464 
16465       /* maintain list position */
16466       if (orig_pos >= ValNodeLen (msud.orig_bioseq_list))
16467       {
16468         orig_pos--;
16469       }
16470       SelectUpdatePreviewSequenceByPosition (usfp->update_preview, orig_pos);
16471     }
16472     usfp->num_successful ++;
16473   }
16474 
16475   SeqMgrClearFeatureIndexes (usfp->input_entityID, NULL);
16476   ObjMgrSetDirtyFlag (usfp->input_entityID, TRUE);
16477   ObjMgrSendMsg (OM_MSG_UPDATE, usfp->input_entityID, 0, 0);
16478 
16479   /* close window after updating the last sequence */
16480   if (usfp->orig_bioseq_list == NULL)
16481   {
16482     Remove (usfp->form);
16483   }
16484   ArrowCursor ();
16485   Update ();
16486 }
16487 
DoNotTestUpdateOneSequence(ButtoN b)16488 static void DoNotTestUpdateOneSequence (ButtoN b)
16489 {
16490   UpdateMultiSequenceFormPtr usfp;
16491   SeqIdPtr              sip;
16492   Char                  id_txt [MAX_ID_LEN];
16493   BioseqPtr                bsp, update_bsp;
16494   Int4                     orig_pos;
16495   ValNodePtr               orig_vnp, update_vnp;
16496   MultiSequenceUpdateData  msud;
16497   Uint2                    update_entityID;
16498 
16499   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (b);
16500   if (usfp == NULL)
16501   {
16502     return;
16503   }
16504 
16505   sip = DialogToPointer (usfp->update_preview);
16506   if (sip == NULL)
16507   {
16508     Message (MSG_ERROR, "No sequence selected!");
16509     return;
16510   }
16511 
16512   SeqIdWrite (SeqIdFindBest (sip, 0), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
16513   if (usfp->lip != NULL && usfp->lip->fp != NULL)
16514   {
16515     fprintf (usfp->lip->fp, "Skipped %s\n", id_txt);
16516     usfp->lip->data_in_log = TRUE;
16517   }
16518 
16519   usfp->num_skipped++;
16520   bsp = FindBioseqInList (usfp->orig_bioseq_list, sip, &orig_pos);
16521   if (bsp != NULL)
16522   {
16523     /* remove sequence and its pair from list */
16524     orig_vnp = ExtractNthValNode (&(usfp->orig_bioseq_list), orig_pos);
16525     orig_vnp = ValNodeFree (orig_vnp);
16526     update_vnp = ExtractNthValNode (&(usfp->update_bioseq_list), orig_pos);
16527 
16528     /* remove update sequence from Desktop */
16529     if (update_vnp != NULL && update_vnp->data.ptrvalue != NULL)
16530     {
16531       update_bsp = (BioseqPtr) update_vnp->data.ptrvalue;
16532       update_bsp->idx.deleteme = TRUE;
16533       update_entityID = update_bsp->idx.entityID;
16534       DeleteMarkedObjects (update_entityID, 0, NULL);
16535     }
16536 
16537     update_vnp = ValNodeFree (update_vnp);
16538     /* renumber valnode lists */
16539     for (orig_vnp = usfp->orig_bioseq_list; orig_vnp != NULL; orig_vnp = orig_vnp->next)
16540     {
16541       if (orig_vnp->choice > orig_pos)
16542       {
16543         orig_vnp->choice --;
16544       }
16545     }
16546     for (update_vnp = usfp->update_bioseq_list; update_vnp != NULL; update_vnp = update_vnp->next)
16547     {
16548       if (update_vnp->choice > orig_pos)
16549       {
16550         update_vnp->choice --;
16551       }
16552     }
16553     msud.orig_bioseq_list = usfp->orig_bioseq_list;
16554     msud.update_bioseq_list = usfp->update_bioseq_list;
16555     msud.unmatched_updates_list = usfp->unmatched_updates_list;
16556     msud.no_updates_list = usfp->no_updates_list;
16557     PointerToDialog (usfp->update_preview, &msud);
16558     /* maintain list position */
16559     if (orig_pos >= ValNodeLen (msud.orig_bioseq_list))
16560     {
16561       orig_pos--;
16562     }
16563     SelectUpdatePreviewSequenceByPosition (usfp->update_preview, orig_pos);
16564 
16565   }
16566   /* close window after skipping the last sequence */
16567   if (usfp->orig_bioseq_list == NULL)
16568   {
16569     Remove (usfp->form);
16570   }
16571 }
16572 
16573 
GetUpdatesWithoutAlignments(ValNodePtr orig_bioseq_list,ValNodePtr update_bioseq_list)16574 static ValNodePtr GetUpdatesWithoutAlignments (ValNodePtr orig_bioseq_list, ValNodePtr update_bioseq_list)
16575 {
16576   ValNodePtr  orig_vnp, update_vnp;
16577   BioseqPtr   orig_bsp, update_bsp;
16578   Boolean     revcomp;
16579   SeqAlignPtr salp;
16580   ValNodePtr  no_aln_list = NULL;
16581   Char        id_txt [MAX_ID_LEN];
16582 
16583   for (orig_vnp = orig_bioseq_list, update_vnp = update_bioseq_list;
16584        orig_vnp != NULL && update_vnp != NULL;
16585        orig_vnp = orig_vnp->next, update_vnp = update_vnp->next)
16586   {
16587     if (orig_vnp->data.ptrvalue == NULL
16588         || update_vnp->data.ptrvalue == NULL)
16589     {
16590       continue;
16591     }
16592     orig_bsp = (BioseqPtr)(orig_vnp->data.ptrvalue);
16593     update_bsp = (BioseqPtr) (update_vnp->data.ptrvalue);
16594     revcomp = FALSE;
16595     salp = Sqn_AlignForSequenceUpdate (orig_bsp, update_bsp, &revcomp);
16596     if (salp == NULL) {
16597       SeqIdWrite (SeqIdFindBest (orig_bsp->id, SEQID_GENBANK), id_txt,
16598                 PRINTID_REPORT, sizeof (id_txt) - 1);
16599       ValNodeAddPointer (&no_aln_list, 0, StringSave (id_txt));
16600     }
16601     if (revcomp) {
16602       BioseqRevComp (update_bsp);
16603       ReverseBioseqFeatureStrands (update_bsp);
16604       SeqMgrReplaceInBioseqIndex (update_bsp);
16605     }
16606     salp = SeqAlignFree (salp);
16607   }
16608   return no_aln_list;
16609 }
16610 
16611 
16612 typedef struct featureupdateinfo {
16613   BioseqPtr orig_bsp;
16614   BioseqPtr update_bsp;
16615 } FeatureUpdateInfoData, PNTR FeatureUpdateInfoPtr;
16616 
16617 
FeatureUpdateNew(BioseqPtr orig_bsp,BioseqPtr update_bsp)16618 static FeatureUpdateInfoPtr FeatureUpdateNew (BioseqPtr orig_bsp, BioseqPtr update_bsp)
16619 {
16620   FeatureUpdateInfoPtr f;
16621 
16622   f = (FeatureUpdateInfoPtr) MemNew (sizeof (FeatureUpdateInfoData));
16623   f->orig_bsp = orig_bsp;
16624   f->update_bsp = update_bsp;
16625   return f;
16626 }
16627 
16628 
16629 typedef struct resolveduplicatefeats {
16630   BioseqPtr orig_bsp;
16631   SeqAnnotPtr newfeat_sap;
16632 } ResolveDuplicateFeatsData, PNTR ResolveDuplicateFeatsPtr;
16633 
16634 
ResolveDuplicateFeatsNew(BioseqPtr bsp,SeqAnnotPtr sap)16635 static ResolveDuplicateFeatsPtr ResolveDuplicateFeatsNew (BioseqPtr bsp, SeqAnnotPtr sap)
16636 {
16637   ResolveDuplicateFeatsPtr r;
16638 
16639   r = (ResolveDuplicateFeatsPtr) MemNew (sizeof (ResolveDuplicateFeatsData));
16640   r->orig_bsp = bsp;
16641   r->newfeat_sap = sap;
16642   return r;
16643 }
16644 
16645 
UpdateAllSequences(ButtoN b)16646 static void UpdateAllSequences (ButtoN b)
16647 {
16648   UpdateMultiSequenceFormPtr usfp;
16649   ValNodePtr                 orig_vnp, update_vnp;
16650   Char                       id_txt [MAX_ID_LEN];
16651   UpdatePairData             upd;
16652   Boolean                    update_successful;
16653   UpdateOptionsPtr           uop;
16654   UpdateAlignmentLengthsData uald;
16655   BioseqPtr                  update_bsp = NULL;
16656   Uint2                      update_entityID = 0;
16657   ValNodePtr                 no_aln_list;
16658   CharPtr                    msg;
16659   ValNodeBlock               dupfeats;
16660   ValNodePtr                 vnp;
16661   ResolveDuplicateFeatsPtr   r;
16662   SeqEntryPtr                sep;
16663 
16664   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (b);
16665   if (usfp == NULL)
16666   {
16667     return;
16668   }
16669 
16670   WatchCursor ();
16671   Update ();
16672 
16673   /* Get Update Options */
16674   uop = DialogToPointer (usfp->options_dialog);
16675 
16676   /* check for update pairs without alignments */
16677   if (uop != NULL && uop->submitter_opts != NULL
16678       && !uop->submitter_opts->ignore_alignment
16679       && uop->submitter_opts->sequence_update_type == eSequenceUpdateReplace)
16680   {
16681     no_aln_list = GetUpdatesWithoutAlignments (usfp->orig_bioseq_list, usfp->update_bioseq_list);
16682     if (no_aln_list != NULL)
16683     {
16684   	  msg = CreateListMessage ("Sequence",
16685   	                           no_aln_list->next == NULL
16686   	                              ? " has no alignment with its update sequence.  Are you sure you want to do the replacement?"
16687   	                              : " have no alignments with their update sequences.  Are you sure you want to do the replacements?",
16688   	                              no_aln_list);
16689   	  no_aln_list = ValNodeFreeData (no_aln_list);
16690       if (ANS_NO == Message (MSG_YN, msg))
16691       {
16692         msg = MemFree (msg);
16693         ArrowCursor();
16694         Update();
16695         return;
16696       }
16697     }
16698   }
16699 
16700   InitValNodeBlock (&dupfeats, NULL);
16701 
16702   for (orig_vnp = usfp->orig_bioseq_list, update_vnp = usfp->update_bioseq_list;
16703        orig_vnp != NULL && update_vnp != NULL;
16704        orig_vnp = orig_vnp->next, update_vnp = update_vnp->next)
16705   {
16706     if (orig_vnp->data.ptrvalue == NULL
16707         || update_vnp->data.ptrvalue == NULL)
16708     {
16709       continue;
16710     }
16711     upd.orig_bsp = (BioseqPtr)(orig_vnp->data.ptrvalue);
16712     upd.update_bsp = (BioseqPtr) (update_vnp->data.ptrvalue);
16713 
16714     /* if we are going to ignore the alignment, don't calculate it */
16715     if ( uop != NULL && uop->submitter_opts != NULL && uop->submitter_opts->ignore_alignment)
16716     {
16717       upd.revcomp = FALSE;
16718       upd.salp = NULL;
16719     }
16720     else
16721     {
16722       upd.revcomp = FALSE;
16723       upd.salp = Sqn_AlignForSequenceUpdate (upd.orig_bsp, upd.update_bsp, &(upd.revcomp));
16724     }
16725     CalculateUpdateAlignmentLengths (upd.salp, upd.orig_bsp, upd.update_bsp, &uald);
16726     update_successful = UpdateOrExtendOneSequenceEx (&upd, uop, &uald,
16727                                                    usfp->input_entityID,
16728                                                    usfp->lip == NULL ? NULL : usfp->lip->fp,
16729                                                    usfp->lip == NULL ? NULL : &(usfp->lip->data_in_log),
16730                                                    TRUE);
16731     if (upd.feature_update_successful) {
16732       ValNodeAddPointerToEnd (&dupfeats, 0, ResolveDuplicateFeatsNew ((BioseqPtr)(orig_vnp->data.ptrvalue), upd.newfeat_sap));
16733     }
16734     upd.salp = SeqAlignFree (upd.salp);
16735 
16736     SeqIdWrite (upd.orig_bsp->id, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
16737     if (usfp->lip != NULL && usfp->lip->fp != NULL && ! update_successful)
16738     {
16739       fprintf (usfp->lip->fp, "Failed to update %s\n", id_txt);
16740       usfp->lip->data_in_log = TRUE;
16741     }
16742     if (update_successful)
16743     {
16744       usfp->num_successful++;
16745       /* remove update sequence from list */
16746       update_vnp->data.ptrvalue = NULL;
16747     }
16748     else
16749     {
16750       usfp->num_failed++;
16751     }
16752 
16753   }
16754 
16755   if (dupfeats.head != NULL && uop != NULL && uop->submitter_opts != NULL
16756       && uop->submitter_opts->feature_import_options != NULL
16757       && uop->submitter_opts->feature_import_options->feature_import_type > eFeatureUpdateNoChange
16758       && uop->submitter_opts->feature_import_options->feature_import_type != eFeatureRemoveAll)
16759   {
16760     /* resolve features unless the policy was to remove all the old ones */
16761 
16762     sep = GetTopSeqEntryForEntityID (usfp->input_entityID);
16763     /* need to set scope to make sure we mark the right bioseq for deletion */
16764     SeqEntrySetScope (sep);
16765     for (vnp = dupfeats.head; vnp != NULL; vnp = vnp->next)
16766     {
16767       r = (ResolveDuplicateFeatsPtr) vnp->data.ptrvalue;
16768       ResolveDuplicateUpdateFeats (r->orig_bsp, uop, r->newfeat_sap);
16769     }
16770     SeqEntrySetScope (NULL);
16771     DeleteMarkedObjects (usfp->input_entityID, 0, NULL);
16772   }
16773 
16774   uop = UpdateOptionsFree (uop);
16775 
16776   SeqMgrClearFeatureIndexes (usfp->input_entityID, NULL);
16777   ObjMgrSetDirtyFlag (usfp->input_entityID, TRUE);
16778   ObjMgrSendMsg (OM_MSG_UPDATE, usfp->input_entityID, 0, 0);
16779 
16780   /* close window */
16781   if (usfp->num_failed == 0)
16782   {
16783     /* launch log viewer */
16784     CloseLog (usfp->lip);
16785     Remove (usfp->form);
16786   }
16787   ArrowCursor ();
16788   Update ();
16789 }
16790 
UpdateSequenceSelectionChange(Pointer userdata)16791 static void UpdateSequenceSelectionChange (Pointer userdata)
16792 {
16793   UpdateMultiSequenceFormPtr usfp;
16794   SeqIdPtr                   sip;
16795   BioseqPtr                  orig_bsp;
16796   Int4                       orig_pos;
16797   ValNodePtr                 update_vnp;
16798   UpdatePairPtr              upp;
16799   UpdateAlignmentLengthsData uald;
16800   Boolean                    is_indexer = indexerVersion;
16801   UpdateOptionsPtr           uop;
16802 
16803   usfp = (UpdateMultiSequenceFormPtr) userdata;
16804   if (usfp == NULL)
16805   {
16806     return;
16807   }
16808 
16809   sip = (SeqIdPtr) DialogToPointer (usfp->update_preview);
16810   if (sip == NULL)
16811   {
16812     Disable (usfp->update_this);
16813     Disable (usfp->skip_this);
16814     upp = NULL;
16815   }
16816   else
16817   {
16818     orig_bsp = FindBioseqInList (usfp->orig_bioseq_list, sip, &orig_pos);
16819     if (orig_bsp == NULL)
16820     {
16821       Disable (usfp->update_this);
16822       Disable (usfp->skip_this);
16823     }
16824     else
16825     {
16826       update_vnp = GetNthValNode (usfp->update_bioseq_list, orig_pos + 1);
16827       if (update_vnp == NULL || update_vnp->data.ptrvalue == NULL)
16828       {
16829         Disable (usfp->update_this);
16830         Enable (usfp->skip_this);
16831       }
16832       else
16833       {
16834         Enable (usfp->update_this);
16835         Enable (usfp->skip_this);
16836       }
16837     }
16838     upp = GetCurrentUpdatePair (usfp->update_preview);
16839   }
16840 
16841   if (upp != NULL)
16842   CalculateUpdateAlignmentLengths (upp->salp,
16843                                    upp->orig_bsp,
16844                                    upp->update_bsp,
16845                                    &uald);
16846   AdjustUpdateOptionsEnabled (usfp->options_dialog, upp, &uald, is_indexer);
16847 
16848   PointerToDialog (usfp->titles_dlg, upp);
16849 
16850   uop = (UpdateOptionsPtr) DialogToPointer (usfp->options_dialog);
16851   if (uop != NULL && uop->submitter_opts != NULL)
16852   {
16853     if (uop->submitter_opts->ignore_alignment)
16854     {
16855       if (uop->submitter_opts->sequence_update_type == eSequenceUpdateExtend5)
16856       {
16857         SetIgnoreAndExtendForMultiSequencePreview (usfp->update_preview, TRUE, TRUE);
16858       }
16859       else if (uop->submitter_opts->sequence_update_type == eSequenceUpdateExtend3)
16860       {
16861         SetIgnoreAndExtendForMultiSequencePreview (usfp->update_preview, TRUE, FALSE);
16862       }
16863       else
16864       {
16865         SetIgnoreAndExtendForMultiSequencePreview (usfp->update_preview, FALSE, FALSE);
16866       }
16867     }
16868     else
16869     {
16870       SetIgnoreAndExtendForMultiSequencePreview (usfp->update_preview, FALSE, FALSE);
16871     }
16872   }
16873   else
16874   {
16875     SetIgnoreAndExtendForMultiSequencePreview (usfp->update_preview, FALSE, FALSE);
16876   }
16877   uop = UpdateOptionsFree (uop);
16878 }
16879 
BioseqHasFeatures(BioseqPtr bsp)16880 static Boolean BioseqHasFeatures (BioseqPtr bsp)
16881 {
16882   SeqFeatPtr        sfp;
16883   SeqMgrFeatContext context;
16884   Uint2             entityID;
16885 
16886   if (bsp == NULL)
16887   {
16888     return FALSE;
16889   }
16890 
16891   entityID = bsp->idx.entityID;
16892   if (entityID == 0)
16893   {
16894     entityID = ObjMgrGetEntityIDForPointer (bsp);
16895   }
16896   if (! SeqMgrFeaturesAreIndexed (entityID))
16897   {
16898     SeqMgrIndexFeatures (entityID, NULL);
16899   }
16900 
16901   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
16902   if (sfp == NULL)
16903   {
16904     return FALSE;
16905   }
16906   else
16907   {
16908     return TRUE;
16909   }
16910 }
16911 
BioseqListHasFeatures(ValNodePtr bioseq_list)16912 static Boolean BioseqListHasFeatures (ValNodePtr bioseq_list)
16913 {
16914   Boolean has_features = FALSE;
16915 
16916   while (bioseq_list != NULL && !has_features)
16917   {
16918     has_features = BioseqHasFeatures (bioseq_list->data.ptrvalue);
16919     bioseq_list = bioseq_list->next;
16920   }
16921   return has_features;
16922 }
16923 
16924 
EntityIDAlreadyInList(Uint2 entityID,ValNodePtr entityIDList)16925 extern Boolean EntityIDAlreadyInList (Uint2 entityID, ValNodePtr entityIDList)
16926 {
16927   while (entityIDList != NULL) {
16928     if ((Uint2)(entityIDList->data.intvalue) == entityID) {
16929       return TRUE;
16930     }
16931   }
16932   return FALSE;
16933 }
16934 
16935 
DestroyByEntityID(Uint2 entityID)16936 static void DestroyByEntityID (Uint2 entityID)
16937 {
16938   SeqEntryPtr sep;
16939   BioseqPtr   bsp;
16940   BioseqSetPtr bssp;
16941   SeqSubmitPtr    ssp;
16942 
16943   sep = GetTopSeqEntryForEntityID (entityID);
16944   if (sep == NULL || sep->data.ptrvalue == NULL) {
16945     return;
16946   }
16947   if (IS_Bioseq(sep)) {
16948     bsp = (BioseqPtr) sep->data.ptrvalue;
16949     if (bsp->idx.parentptr != NULL && bsp->idx.parenttype == OBJ_SEQSUB) {
16950       ssp = (SeqSubmitPtr) bsp->idx.parentptr;
16951       ssp->idx.deleteme = TRUE;
16952     } else {
16953       bsp->idx.deleteme = TRUE;
16954     }
16955   } else if (IS_Bioseq_set (sep)) {
16956     bssp = (BioseqSetPtr) sep->data.ptrvalue;
16957     if (bssp->idx.parentptr != NULL && bssp->idx.parenttype == OBJ_SEQSUB) {
16958       ssp = (SeqSubmitPtr) bssp->idx.parentptr;
16959       ssp->idx.deleteme = TRUE;
16960     } else {
16961       bssp->idx.deleteme = TRUE;
16962     }
16963   }
16964   AssignIDsInEntityEx (entityID, 0, NULL, NULL);
16965   DeleteMarkedObjects (entityID, 0, NULL);
16966   Update();
16967 }
16968 
16969 
16970 
CleanupUpdateMultiSequence(GraphiC g,Pointer data)16971 static void CleanupUpdateMultiSequence (GraphiC g, Pointer data)
16972 {
16973   UpdateMultiSequenceFormPtr usfp;
16974   ValNodePtr                 vnp;
16975   Uint2                      update_entityID;
16976   ValNodePtr                 entityIDList = NULL;
16977   Boolean                    reopen_desktop = FALSE;
16978 
16979   usfp = (UpdateMultiSequenceFormPtr) data;
16980   if (usfp != NULL)
16981   {
16982     /* report successes, skips, and failures */
16983     if (usfp->num_successful > 0)
16984     {
16985       if (usfp->num_skipped > 0)
16986       {
16987         if (usfp->num_failed > 0)
16988         {
16989           Message (MSG_OK, "%d succeeded, %d failed, %d skipped",
16990                            usfp->num_successful,
16991                            usfp->num_failed,
16992                            usfp->num_skipped);
16993         }
16994         else
16995         {
16996           Message (MSG_OK, "%d succeeded, %d skipped",
16997                            usfp->num_successful,
16998                            usfp->num_skipped);
16999         }
17000       }
17001       else if (usfp->num_failed > 0)
17002       {
17003         Message (MSG_OK, "%d succeeded, %d failed",
17004                          usfp->num_successful,
17005                          usfp->num_failed);
17006       }
17007       else
17008       {
17009         Message (MSG_OK, "%d succeeded",
17010                          usfp->num_successful);
17011       }
17012     }
17013     else
17014     {
17015       if (usfp->num_skipped > 0)
17016       {
17017         if (usfp->num_failed > 0)
17018         {
17019           Message (MSG_OK, "%d failed, %d skipped",
17020                            usfp->num_failed,
17021                            usfp->num_skipped);
17022         }
17023         else
17024         {
17025           Message (MSG_OK, "%d skipped",
17026                            usfp->num_skipped);
17027         }
17028       }
17029       else if (usfp->num_failed > 0)
17030       {
17031         Message (MSG_OK, "%d failed",
17032                          usfp->num_failed);
17033       }
17034     }
17035 
17036     /* we don't need to free the data for the original bioseq list */
17037     usfp->orig_bioseq_list = ValNodeFree (usfp->orig_bioseq_list);
17038 
17039     if (usfp->update_entityID_list != NULL)
17040     {
17041       if (IsVSeqMgrOpen()) {
17042         VSeqMgrDelete();
17043         reopen_desktop = TRUE;
17044       }
17045       for (vnp = usfp->update_entityID_list; vnp != NULL; vnp = vnp->next)
17046       {
17047         update_entityID = (Uint2) vnp->data.intvalue;
17048         DestroyByEntityID (update_entityID);
17049       }
17050       if (reopen_desktop) {
17051         VSeqMgrShow();
17052       }
17053     }
17054     usfp->update_entityID_list = ValNodeFree (usfp->update_entityID_list);
17055 
17056     CloseLog (usfp->lip);
17057     usfp->lip = FreeLog (usfp->lip);
17058 
17059     FileRemove (usfp->undo_file);
17060 
17061   }
17062 
17063   StdCleanupExtraProc (g, data);
17064 }
17065 
LoadUpdateSequenceMapFile(UpdateMultiSequenceFormPtr usfp)17066 static void LoadUpdateSequenceMapFile (UpdateMultiSequenceFormPtr usfp)
17067 {
17068   Char                       path [PATH_MAX];
17069   ReadBufferData             rbd;
17070   CharPtr                    line, ptr;
17071   SeqIdPtr                   sip_1, sip_2, sip_orig, sip_update;
17072   BioseqPtr                  bsp_orig, bsp_update;
17073   Int4                       orig_position, update_position;
17074   ValNodePtr                 update_vnp;
17075   MultiSequenceUpdateData    msud;
17076 
17077   if (usfp == NULL)
17078   {
17079     return;
17080   }
17081 
17082   if (! GetInputFileName (path, sizeof (path),"","TEXT"))
17083     return;
17084 
17085   rbd.fp = FileOpen (path, "r");
17086   if (rbd.fp == NULL)
17087   {
17088     Message (MSG_ERROR, "Unable to open %s", path);
17089     return;
17090   }
17091 
17092   rbd.current_data = NULL;
17093   line = AbstractReadFunction (&rbd);
17094   while (line != NULL)
17095   {
17096     ptr = line;
17097     /* skip over initial white space if any*/
17098     ptr += StringSpn (ptr, " \t");
17099     /* skip over first sequence ID */
17100     ptr += StringCSpn (ptr, "\t ");
17101     if (*ptr != 0 && ptr != line)
17102     {
17103       /* truncate string after first ID */
17104       *ptr = '\0';
17105       ptr++;
17106       /* skip over any white space before second ID */
17107       ptr += StringSpn (ptr, "\t ");
17108       /* truncate trailing white space */
17109       while (*(ptr + StringLen (ptr) - 1) == ' ' || *(ptr + StringLen (ptr) - 1) == '\t')
17110       {
17111         *(ptr + StringLen (ptr) - 1) = 0;
17112       }
17113 
17114       sip_1 = MakeSeqID (line);
17115       sip_2 = MakeSeqID (ptr);
17116 
17117       /* try to determine which is original and which is update */
17118       bsp_orig = FindBioseqInList (usfp->no_updates_list, sip_1, &orig_position);
17119       bsp_update = FindBioseqInList (usfp->unmatched_updates_list, sip_2, &update_position);
17120       if (bsp_orig == NULL && bsp_update == NULL)
17121       {
17122         bsp_orig = FindBioseqInList (usfp->no_updates_list, sip_2, &orig_position);
17123         bsp_update = FindBioseqInList (usfp->unmatched_updates_list, sip_1, &update_position);
17124         sip_orig = sip_2;
17125         sip_update = sip_1;
17126       }
17127       else
17128       {
17129         sip_orig = sip_1;
17130         sip_update = sip_2;
17131       }
17132 
17133       if (bsp_orig != NULL && bsp_update != NULL)
17134       {
17135         /* remove Bioseq from no update list and add to list of originals */
17136         update_vnp = ExtractNthValNode (&(usfp->no_updates_list), orig_position);
17137         ValNodeLink (&(usfp->orig_bioseq_list), update_vnp);
17138         /* remove Bioseq from unmatched list and add to list of updates */
17139         update_vnp = ExtractNthValNode (&(usfp->unmatched_updates_list), update_position);
17140         ValNodeLink (&(usfp->update_bioseq_list), update_vnp);
17141       }
17142       sip_orig = SeqIdFree (sip_orig);
17143       sip_update = SeqIdFree (sip_update);
17144     }
17145     line = MemFree (line);
17146   	line = AbstractReadFunction (&rbd);
17147   }
17148   FileClose (rbd.fp);
17149 
17150   msud.orig_bioseq_list = usfp->orig_bioseq_list;
17151   msud.update_bioseq_list = usfp->update_bioseq_list;
17152   msud.unmatched_updates_list = usfp->unmatched_updates_list;
17153   msud.no_updates_list = usfp->no_updates_list;
17154   PointerToDialog (usfp->update_preview, &msud);
17155 }
17156 
17157 static void
ReportIdenticalUpdateSequences(ValNodePtr orig_list,ValNodePtr update_list)17158 ReportIdenticalUpdateSequences
17159 (ValNodePtr orig_list,
17160  ValNodePtr update_list)
17161 {
17162   Char       id_str [128];
17163   BioseqPtr  orig_bsp, update_bsp;
17164   LogInfoPtr lip;
17165   Int4       num_identical = 0, num_total = 0;
17166 
17167   lip = OpenLog ("Sequences Identical to Updates");
17168   if (lip == NULL)
17169   {
17170     return;
17171   }
17172   WatchCursor ();
17173   Update ();
17174   while (orig_list != NULL && update_list != NULL)
17175   {
17176     orig_bsp = orig_list->data.ptrvalue;
17177     update_bsp = update_list->data.ptrvalue;
17178 
17179     if (orig_bsp != NULL)
17180     {
17181       num_total++;
17182     }
17183 
17184     if (orig_bsp != NULL && update_bsp != NULL
17185         && AreSequenceResiduesIdentical (orig_bsp, update_bsp))
17186     {
17187       SeqIdWrite (SeqIdFindBest (orig_bsp->id, SEQID_GENBANK), id_str, PRINTID_REPORT, sizeof (id_str) - 1);
17188       fprintf (lip->fp, "%s\n", id_str);
17189       lip->data_in_log = TRUE;
17190       num_identical++;
17191     }
17192 
17193     orig_list = orig_list->next;
17194     update_list = update_list->next;
17195   }
17196 
17197   if (num_identical == 1)
17198   {
17199     Message (MSG_OK, "One sequence out of %d is identical to its update sequence.", num_total);
17200   }
17201   else if (num_identical > 1)
17202   {
17203     Message (MSG_OK, "%d sequences out of %d are identical to their update sequences.", num_identical, num_total);
17204   }
17205   CloseLog (lip);
17206   lip = FreeLog (lip);
17207   ArrowCursor ();
17208   Update ();
17209 }
17210 
RemoveIdenticalUpdates(ButtoN b)17211 static void RemoveIdenticalUpdates (ButtoN b)
17212 {
17213   UpdateMultiSequenceFormPtr usfp;
17214   SeqIdPtr                   sip;
17215   Int4                       orig_pos = 0, rem_pos = 0;
17216   ValNodePtr                 orig_list, update_list;
17217   ValNodePtr                 prev_orig_list = NULL, prev_update_list = NULL;
17218   ValNodePtr                 next_orig_list = NULL, next_update_list = NULL;
17219   Uint2                      update_entityID = 0;
17220   MultiSequenceUpdateData    msud;
17221   BioseqPtr                  orig_bsp, update_bsp;
17222 
17223   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (b);
17224   if (usfp == NULL)
17225   {
17226     return;
17227   }
17228 
17229   sip = (SeqIdPtr) DialogToPointer (usfp->update_preview);
17230 
17231   FindBioseqInList (usfp->orig_bioseq_list, sip, &orig_pos);
17232 
17233 
17234   orig_list = usfp->orig_bioseq_list;
17235   update_list = usfp->update_bioseq_list;
17236 
17237   while (orig_list != NULL && update_list != NULL)
17238   {
17239     next_orig_list = orig_list->next;
17240     next_update_list = update_list->next;
17241     orig_bsp = orig_list->data.ptrvalue;
17242     update_bsp = update_list->data.ptrvalue;
17243 
17244     if (orig_bsp != NULL && update_bsp != NULL
17245         && AreSequenceResiduesIdentical (orig_bsp, update_bsp))
17246     {
17247       /* remove pair from list */
17248       if (prev_orig_list == NULL)
17249       {
17250         usfp->orig_bioseq_list = orig_list->next;
17251       }
17252       else
17253       {
17254         prev_orig_list->next = orig_list->next;
17255       }
17256       if (prev_update_list == NULL)
17257       {
17258         usfp->update_bioseq_list = update_list->next;
17259       }
17260       else
17261       {
17262         prev_update_list->next = update_list->next;
17263       }
17264 
17265       orig_list->next = NULL;
17266       orig_list = ValNodeFree (orig_list);
17267       update_list->next = NULL;
17268       update_list = ValNodeFree (update_list);
17269       if (rem_pos < orig_pos)
17270       {
17271         orig_pos --;
17272       }
17273     }
17274     else
17275     {
17276       prev_orig_list = orig_list;
17277       prev_update_list = update_list;
17278       rem_pos++;
17279     }
17280 
17281     orig_list = next_orig_list;
17282     update_list = next_update_list;
17283   }
17284 
17285   msud.orig_bioseq_list = usfp->orig_bioseq_list;
17286   msud.update_bioseq_list = usfp->update_bioseq_list;
17287   msud.unmatched_updates_list = usfp->unmatched_updates_list;
17288   msud.no_updates_list = usfp->no_updates_list;
17289   PointerToDialog (usfp->update_preview, &msud);
17290 
17291   /* maintain list position */
17292   if (orig_pos >= ValNodeLen (msud.orig_bioseq_list))
17293   {
17294     orig_pos--;
17295   }
17296   SelectUpdatePreviewSequenceByPosition (usfp->update_preview, orig_pos);
17297 
17298   /* close window after skipping the last sequence */
17299   if (usfp->orig_bioseq_list == NULL)
17300   {
17301     Message (MSG_OK, "All sequences were identical!");
17302     Remove (usfp->form);
17303   }
17304 
17305 
17306   Update ();
17307 }
17308 
LoadUpdateSequenceMapFileBtn(ButtoN b)17309 static void LoadUpdateSequenceMapFileBtn (ButtoN b)
17310 {
17311   UpdateMultiSequenceFormPtr usfp;
17312 
17313   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (b);
17314   if (usfp == NULL) {
17315     return;
17316   }
17317   LoadUpdateSequenceMapFile (usfp);
17318   ReportIdenticalUpdateSequences (usfp->orig_bioseq_list, usfp->update_bioseq_list);
17319   if (BioseqListHasFeatures (usfp->update_bioseq_list)) {
17320     EnableImportFeatureOptions(usfp->options_dialog);
17321   } else {
17322     DisableImportFeatureOptions (usfp->options_dialog);
17323   }
17324   if (BioseqListHasFeatures (usfp->orig_bioseq_list)) {
17325     EnableRemoveFeatureOptions (usfp->options_dialog);
17326   } else {
17327     DisableRemoveFeatureOptions (usfp->options_dialog);
17328   }
17329 }
17330 
17331 
ConnectSelectedUpdateSequencesBtn(ButtoN b)17332 static void ConnectSelectedUpdateSequencesBtn (ButtoN b)
17333 {
17334   UpdateMultiSequenceFormPtr usfp;
17335   Int4 pos1;
17336   Int4 pos2;
17337   ValNodePtr update_vnp;
17338   MultiSequenceUpdateData    msud;
17339 
17340   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (b);
17341   if (usfp == NULL) {
17342     return;
17343   }
17344 
17345   pos1 = GetMultiSequenceUpdatePreviewUnmatchedSelection (usfp->update_preview);
17346   pos2 = GetMultiSequenceUpdatePreviewNoUpdateSelection (usfp->update_preview);
17347 
17348   if (pos1 < 0 || pos2  < 0) {
17349     return;
17350   }
17351 
17352   /* remap */
17353   /* remove Bioseq from no update list and add to list of originals */
17354   update_vnp = ExtractNthValNode (&(usfp->no_updates_list), pos2);
17355   if (update_vnp == NULL) {
17356     return;
17357   }
17358   ValNodeLink (&(usfp->orig_bioseq_list), update_vnp);
17359   /* remove Bioseq from unmatched list and add to list of updates */
17360   update_vnp = ExtractNthValNode (&(usfp->unmatched_updates_list), pos1);
17361   ValNodeLink (&(usfp->update_bioseq_list), update_vnp);
17362   /* update preview */
17363   msud.orig_bioseq_list = usfp->orig_bioseq_list;
17364   msud.update_bioseq_list = usfp->update_bioseq_list;
17365   msud.unmatched_updates_list = usfp->unmatched_updates_list;
17366   msud.no_updates_list = usfp->no_updates_list;
17367   PointerToDialog (usfp->update_preview, &msud);
17368 
17369   ReportIdenticalUpdateSequences (usfp->orig_bioseq_list, usfp->update_bioseq_list);
17370   if (BioseqListHasFeatures (usfp->update_bioseq_list)) {
17371     EnableImportFeatureOptions(usfp->options_dialog);
17372   } else {
17373     DisableImportFeatureOptions (usfp->options_dialog);
17374   }
17375   if (BioseqListHasFeatures (usfp->orig_bioseq_list)) {
17376     EnableRemoveFeatureOptions (usfp->options_dialog);
17377   } else {
17378     DisableRemoveFeatureOptions (usfp->options_dialog);
17379   }
17380 }
17381 
17382 
UndoUpdates(ButtoN b)17383 static void UndoUpdates (ButtoN b)
17384 {
17385   UpdateMultiSequenceFormPtr usfp;
17386   Uint2                      new_entityID;
17387 
17388   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (b);
17389   if (usfp == NULL)
17390   {
17391     return;
17392   }
17393   WatchCursor ();
17394   Update ();
17395 
17396   new_entityID = RestoreEntityIDFromFile (usfp->undo_file, usfp->input_entityID);
17397   if (new_entityID != 0) {
17398     usfp->input_entityID = new_entityID;
17399     ObjMgrSetDirtyFlag (usfp->input_entityID, TRUE);
17400     ObjMgrSendMsg (OM_MSG_UPDATE, usfp->input_entityID, 0, 0);
17401   }
17402 
17403   usfp->num_successful = 0;
17404   usfp->num_failed = 0;
17405   usfp->num_skipped = 0;
17406   usfp->lip = FreeLog (usfp->lip);
17407 
17408   Remove (usfp->form);
17409   ArrowCursor ();
17410   Update ();
17411 }
17412 
ExportUnmatchedUpdates(IteM i)17413 static void ExportUnmatchedUpdates (IteM i)
17414 {
17415   UpdateMultiSequenceFormPtr usfp;
17416   FILE                       *fp;
17417   Char                       path[PATH_MAX];
17418   ValNodePtr                 vnp;
17419   Char                       id_txt[128];
17420   BioseqPtr                  bsp;
17421 
17422   usfp = (UpdateMultiSequenceFormPtr) GetObjectExtra (i);
17423   if (usfp == NULL) {
17424     return;
17425   }
17426 
17427   if (! GetOutputFileName (path, sizeof (path), "")) return;
17428   fp = FileOpen (path, "w");
17429   if (fp == NULL)
17430   {
17431     Message (MSG_ERROR, "Unable to open %s", path);
17432     return;
17433   }
17434   fprintf (fp, "Unmatched update sequences\n");
17435   for (vnp = usfp->unmatched_updates_list; vnp != NULL; vnp = vnp->next) {
17436     bsp = (BioseqPtr) vnp->data.ptrvalue;
17437     if (bsp != NULL) {
17438       SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
17439       fprintf (fp, "%s\n", id_txt);
17440     }
17441   }
17442 
17443   fprintf (fp, "Sequences in record with no updates\n");
17444   for (vnp = usfp->no_updates_list; vnp != NULL; vnp = vnp->next) {
17445     bsp = (BioseqPtr) vnp->data.ptrvalue;
17446     if (bsp != NULL) {
17447       SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
17448       fprintf (fp, "%s\n", id_txt);
17449     }
17450   }
17451   FileClose (fp);
17452 
17453 }
17454 
TestUpdateSequenceSetBaseForm(BaseFormPtr bfp,Boolean is_indexer,Boolean do_update,Boolean from_clipboard)17455 NLM_EXTERN void TestUpdateSequenceSetBaseForm (BaseFormPtr bfp, Boolean is_indexer, Boolean do_update, Boolean from_clipboard)
17456 {
17457   WindoW                     w;
17458   CharPtr                    title;
17459   GrouP                      h, k, ext_grp;
17460   BioseqPtr                  orig_bsp, update_bsp;
17461   SeqEntryPtr                sep;
17462   SeqEntryPtr                update_list;
17463   GrouP                      c;
17464   ButtoN                     b;
17465   Boolean                    is_na;
17466   Int4                       num_orig = 0, num_update = 0;
17467   UpdateMultiSequenceFormPtr usfp;
17468   MultiSequenceUpdateData    msud;
17469   UpdateOptionsPtr           uop;
17470   DialoG                     ext_dlg;
17471   MenU                       file_menu;
17472   IteM                       localItem;
17473   ValNodePtr                 vnp;
17474   SeqEntryPtr                orig_scope;
17475 
17476   if (bfp == NULL) return;
17477 
17478   /* for test purposes, need to load sequence and update sequence */
17479   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
17480   if (sep == NULL)
17481     return;
17482 
17483   if (ShowDeltaReport (sep)) {
17484     if (Message (MSG_YN, "This set contains delta sequences.  If you update a delta sequence with a raw sequence, the delta sequence will be converted to raw.  Do you want to continue?")
17485         != ANS_YES) {
17486         return;
17487     }
17488   }
17489 
17490 
17491   orig_bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID,
17492 			   bfp->input_itemtype);
17493   if (orig_bsp == NULL)
17494   {
17495     is_na = TRUE;
17496   }
17497   else
17498   {
17499     is_na = ISA_na (orig_bsp->mol);
17500   }
17501 
17502   /* Read in the update data from a file */
17503   /* for now, just handling FASTA */
17504   update_list = ReadUpdateSequences (is_na, from_clipboard);
17505   if (update_list == NULL)
17506   {
17507     return;
17508   }
17509 
17510   usfp = (UpdateMultiSequenceFormPtr) MemNew (sizeof (UpdateMultiSequenceFormData));
17511   if (usfp == NULL)
17512   {
17513     return;
17514   }
17515   usfp->input_entityID = bfp->input_entityID;
17516   usfp->is_na = is_na;
17517   usfp->orig_bioseq_list = NULL;
17518   usfp->update_bioseq_list = NULL;
17519   usfp->update_entityID_list = NULL;
17520 
17521 
17522   usfp->num_successful = 0;
17523   usfp->num_failed = 0;
17524   usfp->num_skipped = 0;
17525 
17526   usfp->lip = OpenLog ("Update Sequence Log");
17527 
17528   /* save the current SeqEntry to a file, so we can restore it if we need to */
17529   TmpNam (usfp->undo_file);
17530   write_out_put(sep, usfp->undo_file, FALSE);
17531 
17532   ListBioseqsInSeqEntry (sep, usfp->is_na, &num_orig, &usfp->orig_bioseq_list);
17533   ListBioseqsInSeqEntry (update_list, usfp->is_na, &num_update, &usfp->update_bioseq_list);
17534 
17535   /* add update sequence entity IDs */
17536   for (vnp = usfp->update_bioseq_list; vnp != NULL; vnp = vnp->next)
17537   {
17538     if (vnp->data.ptrvalue != NULL)
17539     {
17540       update_bsp = (BioseqPtr) vnp->data.ptrvalue;
17541       if (!EntityIDAlreadyInList(update_bsp->idx.entityID, usfp->update_entityID_list)) {
17542         ValNodeAddInt (&(usfp->update_entityID_list), 0, update_bsp->idx.entityID);
17543       }
17544     }
17545   }
17546 
17547   orig_scope = SeqEntrySetScope (sep);
17548   usfp->unmatched_updates_list = ShuffleUpdateBioseqListWithIndex (&usfp->update_bioseq_list,
17549                                                           usfp->orig_bioseq_list);
17550   SeqEntrySetScope (orig_scope);
17551 
17552   usfp->no_updates_list = ExtractSequencesWithoutUpdates (&usfp->orig_bioseq_list, &usfp->update_bioseq_list);
17553   if (!is_indexer)
17554   {
17555     if (usfp->unmatched_updates_list != NULL)
17556     {
17557       if (ANS_YES == Message (MSG_YN, "Some sequences in your update file are not present in the record to be updated.  Would you like to load a tab-delimited file to map the update files to the record files?"))
17558       {
17559         LoadUpdateSequenceMapFile (usfp);
17560       }
17561     }
17562     RemoveSequencesWithoutUpdates (&usfp->orig_bioseq_list, &usfp->update_bioseq_list);
17563     usfp->no_updates_list = ValNodeFree (usfp->no_updates_list);
17564   }
17565 
17566   ReplaceCollidingUpdateIDs (usfp->update_bioseq_list, usfp->orig_bioseq_list);
17567 
17568   /* Create window */
17569 
17570   if (do_update) {
17571     title = "Update Sequence";
17572   } else {
17573     title = "Extend Sequence";
17574   }
17575   w = MovableModalWindow (-50, -33, -10, -10, title, NULL);
17576 
17577   if (w == NULL)
17578     return;
17579 
17580   SetObjectExtra (w, usfp, CleanupUpdateMultiSequence);
17581   usfp->form = (ForM) w;
17582 
17583   if (is_indexer) {
17584     file_menu = PulldownMenu (w, "File");
17585     localItem = CommandItem (file_menu, "Export Unmatched", ExportUnmatchedUpdates);
17586     SetObjectExtra (localItem, usfp, NULL);
17587   }
17588 
17589   h = HiddenGroup (w, -1, 0, NULL);
17590   SetGroupSpacing (h, 10, 10);
17591 
17592   usfp->titles_dlg = UpdateTitlesDialog (h, is_indexer, do_update);
17593 
17594   k = HiddenGroup (h, 2, 0, NULL);
17595   SetGroupSpacing (k, 10, 10);
17596 
17597   usfp->update_preview = MultiSequenceUpdatePreview (k, usfp->is_na, do_update,
17598                                                      UpdateSequenceSelectionChange,
17599                                                      usfp,
17600                                                      LoadUpdateSequenceMapFileBtn,
17601                                                      ConnectSelectedUpdateSequencesBtn,
17602                                                      is_indexer);
17603 
17604   if (! do_update)
17605   {
17606     ext_grp = HiddenGroup (k, -1, 0, NULL);
17607 
17608     ext_dlg = UpdateTitlesDialog (ext_grp, is_indexer, FALSE);
17609     AddExtendDialogToMultiSequenceUpdatePreview (usfp->update_preview, ext_dlg);
17610                                                  ;
17611 
17612     usfp->options_dialog = UpdateOptionsDialog (ext_grp, usfp->is_na, is_indexer, do_update,
17613                                                 UpdateSequenceSelectionChange, usfp);
17614     AlignObjects (ALIGN_CENTER, (HANDLE) ext_dlg, (HANDLE) usfp->options_dialog, NULL);
17615     SetMultiSequenceUpdatePreviewMatchWindow (usfp->update_preview, (WindoW) ext_grp);
17616   }
17617   else
17618   {
17619     usfp->options_dialog = UpdateOptionsDialog (k, usfp->is_na, is_indexer, do_update,
17620                                                 UpdateSequenceSelectionChange, usfp);
17621   }
17622 
17623 
17624   c = HiddenGroup (h, 6, 0, NULL);
17625   SetGroupSpacing (c, 10, 10);
17626   usfp->update_this = PushButton (c, "Update This Sequence", DoTestUpdateOneSequence);
17627   SetObjectExtra (usfp->update_this, usfp, NULL);
17628   usfp->skip_this = PushButton (c, "Skip This Sequence", DoNotTestUpdateOneSequence);
17629   SetObjectExtra (usfp->skip_this, usfp, NULL);
17630   b = PushButton (c, "Update All Sequences", UpdateAllSequences);
17631   SetObjectExtra (b, usfp, NULL);
17632 
17633   b = PushButton (c, "Stop Updating", StdCancelButtonProc);
17634 
17635   b = PushButton (c, "Cancel", UndoUpdates);
17636   SetObjectExtra (b, usfp, NULL);
17637 
17638   AlignObjects (ALIGN_CENTER, (HANDLE) usfp->titles_dlg, (HANDLE) k, (HANDLE) c, NULL);
17639 
17640   msud.orig_bioseq_list = usfp->orig_bioseq_list;
17641   msud.update_bioseq_list = usfp->update_bioseq_list;
17642   msud.unmatched_updates_list = usfp->unmatched_updates_list;
17643   msud.no_updates_list = usfp->no_updates_list;
17644   PointerToDialog (usfp->update_preview, &msud);
17645 
17646   if (!BioseqListHasFeatures (usfp->update_bioseq_list))
17647   {
17648     DisableImportFeatureOptions (usfp->options_dialog);
17649   }
17650 
17651   if (BioseqListHasFeatures (usfp->orig_bioseq_list)) {
17652     EnableRemoveFeatureOptions (usfp->options_dialog);
17653   } else {
17654     DisableRemoveFeatureOptions (usfp->options_dialog);
17655   }
17656 
17657   uop = DialogToPointer (usfp->options_dialog);
17658   uop->submitter_opts->sequence_update_type = eSequenceUpdateReplace;
17659   PointerToDialog (usfp->options_dialog, uop);
17660   uop = UpdateOptionsFree (uop);
17661 
17662   Show (w);
17663   Update ();
17664   ReportIdenticalUpdateSequences (usfp->orig_bioseq_list, usfp->update_bioseq_list);
17665 }
17666 
TestUpdateSequenceSet(IteM i,Boolean is_indexer,Boolean do_update,Boolean from_clipboard)17667 static void TestUpdateSequenceSet (IteM i, Boolean is_indexer, Boolean do_update, Boolean from_clipboard)
17668 {
17669   BaseFormPtr                bfp;
17670 
17671 #ifdef WIN_MAC
17672   bfp = currentFormDataPtr;
17673 #else
17674   bfp = GetObjectExtra (i);
17675 #endif
17676   TestUpdateSequenceSetBaseForm (bfp, is_indexer, do_update, from_clipboard);
17677 }
17678 
TestUpdateSequenceSetSubmitter(IteM i)17679 extern void TestUpdateSequenceSetSubmitter (IteM i)
17680 {
17681   TestUpdateSequenceSet (i, FALSE, TRUE, FALSE);
17682 }
17683 
TestExtendSequenceSetSubmitter(IteM i)17684 extern void TestExtendSequenceSetSubmitter (IteM i)
17685 {
17686   TestUpdateSequenceSet (i, FALSE, FALSE, FALSE);
17687 }
17688 
TestUpdateSequenceSetIndexer(IteM i)17689 extern void TestUpdateSequenceSetIndexer (IteM i)
17690 {
17691   TestUpdateSequenceSet (i, TRUE, TRUE, FALSE);
17692 }
17693 
TestUpdateSequenceSetClipboardIndexer(IteM i)17694 extern void TestUpdateSequenceSetClipboardIndexer (IteM i)
17695 {
17696   TestUpdateSequenceSet (i, TRUE, TRUE, TRUE);
17697 }
17698 
TestExtendSequenceSetIndexer(IteM i)17699 extern void TestExtendSequenceSetIndexer (IteM i)
17700 {
17701   TestUpdateSequenceSet (i, TRUE, FALSE, FALSE);
17702 }
17703 
17704 typedef struct singlesequenceupdateform
17705 {
17706   FORM_MESSAGE_BLOCK
17707   DialoG     preview_dlg;
17708   DialoG     options_dlg;
17709   DialoG     titles_dlg;
17710   Boolean    is_na;
17711   LogInfoPtr lip;
17712   UpdatePairData update_pair;
17713   SeqEntryPtr    update_list;
17714   Uint2          update_entity_ID;
17715 } SingleSequenceUpdateFormData, PNTR SingleSequenceUpdateFormPtr;
17716 
17717 
CleanupSingleSequenceUpdateForm(GraphiC g,Pointer data)17718 static void CleanupSingleSequenceUpdateForm (GraphiC g, Pointer data)
17719 {
17720   SingleSequenceUpdateFormPtr ssufp;
17721   Boolean reopen_desktop = FALSE;
17722 
17723   ssufp = (SingleSequenceUpdateFormPtr) data;
17724   if (ssufp != NULL)
17725   {
17726     CloseLog (ssufp->lip);
17727     ssufp->lip = FreeLog (ssufp->lip);
17728 
17729     if (IsVSeqMgrOpen()) {
17730       VSeqMgrDelete();
17731       reopen_desktop = TRUE;
17732     }
17733     DestroyByEntityID (ssufp->update_entity_ID);
17734     if (reopen_desktop) {
17735       VSeqMgrShow();
17736     }
17737   }
17738   StdCleanupExtraProc (g, data);
17739 }
17740 
17741 
DoUpdateSingleSequence(ButtoN b)17742 static void DoUpdateSingleSequence (ButtoN b)
17743 {
17744   SingleSequenceUpdateFormPtr ssufp;
17745   Char                        id_txt [MAX_ID_LEN];
17746   UpdateAlignmentLengthsData  uald;
17747   UpdateOptionsPtr            uop;
17748   Boolean                     update_successful = FALSE;
17749 
17750   ssufp = (SingleSequenceUpdateFormPtr) GetObjectExtra (b);
17751 
17752   WatchCursor ();
17753   Update ();
17754 
17755   if (ssufp == NULL || ssufp->update_pair.orig_bsp == NULL)
17756   {
17757     return;
17758   }
17759 
17760   uop = DialogToPointer (ssufp->options_dlg);
17761   if (uop == NULL || !AreSubmitterOptsValid(uop->submitter_opts))
17762   {
17763     Message (MSG_ERROR, "Invalid options selected!");
17764     uop = UpdateOptionsFree (uop);
17765     return;
17766   }
17767 
17768   /* if we are going to ignore the alignment, remove it */
17769   if (uop->submitter_opts->ignore_alignment)
17770   {
17771     ssufp->update_pair.salp = NULL;
17772     ssufp->update_pair.revcomp = FALSE;
17773   }
17774   else
17775   {
17776     /* reverse the sequence prior to the update if necessary */
17777     if (ssufp->update_pair.revcomp)
17778     {
17779       BioseqRevComp (ssufp->update_pair.update_bsp);
17780       ReverseBioseqFeatureStrands (ssufp->update_pair.update_bsp);
17781       SeqMgrReplaceInBioseqIndex (ssufp->update_pair.update_bsp);
17782     }
17783   }
17784 
17785   CalculateUpdateAlignmentLengths (ssufp->update_pair.salp,
17786                                    ssufp->update_pair.orig_bsp,
17787                                    ssufp->update_pair.update_bsp,
17788                                    &uald);
17789 
17790   update_successful = UpdateOrExtendOneSequence (&(ssufp->update_pair),
17791                                                  uop,
17792                                                  &uald,
17793                                                  ssufp->input_entityID,
17794                                                  ssufp->lip->fp, &(ssufp->lip->data_in_log));
17795 
17796   if (!update_successful && ssufp->lip != NULL && ssufp->lip->fp != NULL)
17797   {
17798     SeqIdWrite (ssufp->update_pair.orig_bsp->id, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
17799     fprintf (ssufp->lip->fp, "Failed to update %s\n", id_txt);
17800     ssufp->lip->data_in_log = TRUE;
17801   }
17802   uop = UpdateOptionsFree (uop);
17803 
17804 
17805   SeqMgrClearFeatureIndexes (ssufp->input_entityID, NULL);
17806   ObjMgrSetDirtyFlag (ssufp->input_entityID, TRUE);
17807   ObjMgrSendMsg (OM_MSG_UPDATE, ssufp->input_entityID, 0, 0);
17808 
17809   Remove (ssufp->form);
17810   ArrowCursor ();
17811   Update ();
17812 }
17813 
UpdateSingleSequenceOptions(Pointer userdata)17814 static void UpdateSingleSequenceOptions (Pointer userdata)
17815 {
17816   SingleSequenceUpdateFormPtr ssufp;
17817   UpdateAlignmentLengthsData  uald;
17818   Boolean                     is_indexer = indexerVersion;
17819   UpdateOptionsPtr            uop;
17820 
17821   ssufp = (SingleSequenceUpdateFormPtr) userdata;
17822   if (ssufp == NULL)
17823   {
17824     return;
17825   }
17826 
17827   CalculateUpdateAlignmentLengths (ssufp->update_pair.salp,
17828                                    ssufp->update_pair.orig_bsp,
17829                                    ssufp->update_pair.update_bsp,
17830                                    &uald);
17831 
17832   AdjustUpdateOptionsEnabled (ssufp->options_dlg, &(ssufp->update_pair), &uald, is_indexer);
17833   uop = (UpdateOptionsPtr) DialogToPointer (ssufp->options_dlg);
17834   if (uop != NULL && uop->submitter_opts != NULL)
17835   {
17836     if (uop->submitter_opts->ignore_alignment)
17837     {
17838       if (uop->submitter_opts->sequence_update_type == eSequenceUpdateExtend5)
17839       {
17840         SetIgnoreAndExtendForPreviewPictures (ssufp->preview_dlg, TRUE, TRUE);
17841       }
17842       else if (uop->submitter_opts->sequence_update_type == eSequenceUpdateExtend3)
17843       {
17844         SetIgnoreAndExtendForPreviewPictures (ssufp->preview_dlg, TRUE, FALSE);
17845       }
17846       else
17847       {
17848         SetIgnoreAndExtendForPreviewPictures (ssufp->preview_dlg, FALSE, FALSE);
17849       }
17850     }
17851     else
17852     {
17853       SetIgnoreAndExtendForPreviewPictures (ssufp->preview_dlg, FALSE, FALSE);
17854     }
17855   }
17856   else
17857   {
17858     SetIgnoreAndExtendForPreviewPictures (ssufp->preview_dlg, FALSE, FALSE);
17859   }
17860   uop = UpdateOptionsFree (uop);
17861 }
17862 
17863 
17864 static void
UpdateSingleSequence(BioseqPtr orig_bsp,SeqEntryPtr update_list,Boolean is_indexer,Boolean do_update,Boolean update_is_download,Uint2 entityID)17865 UpdateSingleSequence
17866 (BioseqPtr   orig_bsp,
17867  SeqEntryPtr update_list,
17868  Boolean     is_indexer,
17869  Boolean     do_update,
17870  Boolean     update_is_download,
17871  Uint2       entityID)
17872 {
17873   WindoW             w;
17874   CharPtr            title;
17875   GrouP              h, k;
17876   GrouP              c;
17877   ButtoN             b;
17878   Boolean            is_na;
17879   Int4               num_update = 0;
17880   SingleSequenceUpdateFormPtr ssufp;
17881   ValNodePtr                  orig_bioseq_list = NULL, update_bioseq_list = NULL;
17882   UpdateAlignmentLengthsData  uald;
17883   UpdateOptionsPtr            uop;
17884 
17885   if (orig_bsp == NULL || update_list == NULL)
17886   {
17887     return;
17888   }
17889 
17890   is_na = ISA_na (orig_bsp->mol);
17891 
17892   ssufp = (SingleSequenceUpdateFormPtr) MemNew (sizeof (SingleSequenceUpdateFormData));
17893   if (ssufp == NULL)
17894   {
17895     return;
17896   }
17897   ssufp->is_na = is_na;
17898   ssufp->lip = OpenLog ("Update Sequence Log");
17899 
17900   ssufp->update_pair.orig_bsp = orig_bsp;
17901 
17902   ssufp->update_list = update_list;
17903 
17904   ValNodeAddPointer (&orig_bioseq_list, 0, orig_bsp);
17905   ListBioseqsInSeqEntry (update_list, ssufp->is_na, &num_update, &update_bioseq_list);
17906 
17907   ReplaceCollidingUpdateIDs (update_bioseq_list, orig_bioseq_list);
17908 
17909   ssufp->update_pair.update_bsp = update_bioseq_list->data.ptrvalue;
17910   update_bioseq_list = ValNodeFree (update_bioseq_list);
17911 
17912   if (ssufp->update_pair.update_bsp != NULL)
17913   {
17914     ssufp->update_entity_ID = ssufp->update_pair.update_bsp->idx.entityID;
17915   }
17916 
17917   if (ssufp->update_pair.orig_bsp != NULL && ssufp->update_pair.orig_bsp->repr == Seq_repr_delta
17918       && ssufp->update_pair.update_bsp != NULL && ssufp->update_pair.update_bsp->repr != Seq_repr_delta) {
17919     if (Message (MSG_YN, "You are about to update a delta sequence with a raw sequence, which will convert the delta sequence to raw.  Do you want to continue?")
17920         != ANS_YES) {
17921         ssufp = MemFree (ssufp);
17922         return;
17923     }
17924   }
17925 
17926   if (AreSequenceResiduesIdentical (ssufp->update_pair.orig_bsp,
17927                                     ssufp->update_pair.update_bsp))
17928   {
17929     Message (MSG_OK, "Sequence is identical to update sequence!");
17930   }
17931 
17932   /* Create window */
17933 
17934   if (do_update) {
17935     title = "Update Sequence";
17936   } else {
17937     title = "Extend Sequence";
17938   }
17939   w = FixedWindow (-50, -33, -10, -10, title, NULL);
17940 
17941   if (w == NULL)
17942     return;
17943 
17944   SetObjectExtra (w, ssufp, CleanupSingleSequenceUpdateForm);
17945   ssufp->form = (ForM) w;
17946   ssufp->input_entityID = entityID;
17947 
17948   h = HiddenGroup (w, -1, 0, NULL);
17949   SetGroupSpacing (h, 10, 10);
17950 
17951   ssufp->titles_dlg = UpdateTitlesDialog (h, is_indexer, do_update);
17952 
17953   k = HiddenGroup (h, 2, 0, NULL);
17954 
17955   SetGroupSpacing (k, 10, 10);
17956   if (do_update)
17957   {
17958     ssufp->preview_dlg = UpdatePreviewDialog (k, is_indexer);
17959   }
17960 
17961   ssufp->update_pair.revcomp = FALSE;
17962   ssufp->update_pair.salp = Sqn_AlignForSequenceUpdate (ssufp->update_pair.orig_bsp,
17963                                                     ssufp->update_pair.update_bsp,
17964                                                     &(ssufp->update_pair.revcomp));
17965 
17966   if (ssufp->update_pair.revcomp)
17967   {
17968     BioseqRevComp (ssufp->update_pair.update_bsp);
17969     ReverseBioseqFeatureStrands (ssufp->update_pair.update_bsp);
17970     SeqMgrReplaceInBioseqIndex (ssufp->update_pair.update_bsp);
17971   }
17972 
17973   ssufp->options_dlg = UpdateOptionsDialog (k, ssufp->is_na, is_indexer, do_update,
17974                                             UpdateSingleSequenceOptions, ssufp);
17975   PointerToDialog (ssufp->preview_dlg, &(ssufp->update_pair));
17976   PointerToDialog (ssufp->titles_dlg, &(ssufp->update_pair));
17977 
17978   c = HiddenGroup (h, 4, 0, NULL);
17979   SetGroupSpacing (c, 10, 10);
17980   b = PushButton (c, "Update Sequence", DoUpdateSingleSequence);
17981   SetObjectExtra (b, ssufp, NULL);
17982   b = PushButton (c, "Cancel", StdCancelButtonProc);
17983 
17984   AlignObjects (ALIGN_CENTER, (HANDLE) ssufp->titles_dlg, (HANDLE) k, (HANDLE) c, NULL);
17985 
17986   if (BioseqHasFeatures (ssufp->update_pair.update_bsp)) {
17987     EnableImportFeatureOptions(ssufp->options_dlg);
17988     uop = DialogToPointer (ssufp->options_dlg);
17989     /* for public version only, if there are features, default to
17990      * import all except duplicates
17991      */
17992     if (!is_indexer) {
17993       if (uop->submitter_opts->feature_import_options == NULL) {
17994         uop->submitter_opts->feature_import_options = FeatureImportOptionsNew ();
17995       }
17996       uop->submitter_opts->feature_import_options->feature_import_type = eFeatureUpdateAllExceptDups;
17997       uop->submitter_opts->feature_import_options->feature_types = ValNodeFree (uop->submitter_opts->feature_import_options->feature_types);
17998       PointerToDialog (ssufp->options_dlg, uop);
17999       uop = UpdateOptionsFree (uop);
18000     }
18001   } else {
18002     DisableImportFeatureOptions (ssufp->options_dlg);
18003   }
18004 
18005   if (BioseqHasFeatures (ssufp->update_pair.orig_bsp)) {
18006     EnableRemoveFeatureOptions (ssufp->options_dlg);
18007   } else {
18008     DisableRemoveFeatureOptions (ssufp->options_dlg);
18009   }
18010 
18011   CalculateUpdateAlignmentLengths (ssufp->update_pair.salp,
18012                                    ssufp->update_pair.orig_bsp,
18013                                    ssufp->update_pair.update_bsp,
18014                                    &uald);
18015   AdjustUpdateOptionsEnabled (ssufp->options_dlg, &(ssufp->update_pair), &uald, is_indexer);
18016 
18017   uop = DialogToPointer (ssufp->options_dlg);
18018   if (is_indexer)
18019   {
18020     if (update_is_download && ssufp->update_pair.salp != NULL)
18021     {
18022       uop->submitter_opts->sequence_update_type = eSequenceUpdateNoChange;
18023     }
18024     else
18025     {
18026       uop->submitter_opts->sequence_update_type = eSequenceUpdateReplace;
18027     }
18028   }
18029   else
18030   {
18031     if (ssufp->update_pair.salp == NULL)
18032     {
18033       /* no alignment - default is to replace */
18034       uop->submitter_opts->sequence_update_type = eSequenceUpdateReplace;
18035     }
18036     else if (uald.new5 > uald.old5 && uald.new3 < uald.old3)
18037     {
18038       /* new 5' end is bigger, new 3' end is smaller,
18039        * default is extend 5' */
18040       uop->submitter_opts->sequence_update_type = eSequenceUpdateExtend5;
18041     }
18042     else if (uald.new5 < uald.old5 && uald.new3 > uald.old3)
18043     {
18044       /* new 3' end is bigger, new 5' end is smaller,
18045        * default is extend 3' */
18046       uop->submitter_opts->sequence_update_type = eSequenceUpdateExtend3;
18047     }
18048     else
18049     {
18050       uop->submitter_opts->sequence_update_type = eSequenceUpdateReplace;
18051     }
18052   }
18053   PointerToDialog (ssufp->options_dlg, uop);
18054   uop = UpdateOptionsFree (uop);
18055 
18056   Show (w);
18057   Update ();
18058 }
18059 
TestUpdateSequenceBaseForm(BaseFormPtr bfp,Boolean is_indexer,Boolean do_update,Boolean from_clipboard)18060 NLM_EXTERN void TestUpdateSequenceBaseForm (BaseFormPtr bfp, Boolean is_indexer, Boolean do_update, Boolean from_clipboard)
18061 {
18062   BioseqPtr          orig_bsp;
18063   SeqEntryPtr        sep;
18064   SeqEntryPtr        update_list;
18065   Boolean            is_na;
18066 
18067   if (bfp == NULL) return;
18068 
18069   /* for test purposes, need to load sequence and update sequence */
18070   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
18071   if (sep == NULL)
18072     return;
18073   orig_bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID,
18074 			   bfp->input_itemtype);
18075   if (orig_bsp == NULL)
18076     return;
18077 
18078   is_na = ISA_na (orig_bsp->mol);
18079 
18080   /* Read in the update data from a file */
18081   update_list = ReadUpdateSequences (is_na, from_clipboard);
18082   if (update_list == NULL)
18083   {
18084     return;
18085   }
18086 
18087   UpdateSingleSequence (orig_bsp, update_list, is_indexer, do_update, FALSE, bfp->input_entityID);
18088 }
18089 
18090 
TestUpdateSequence(IteM i,Boolean is_indexer,Boolean do_update,Boolean from_clipboard)18091 static void TestUpdateSequence (IteM i, Boolean is_indexer, Boolean do_update, Boolean from_clipboard)
18092 {
18093   BaseFormPtr        bfp;
18094 
18095 #ifdef WIN_MAC
18096   bfp = currentFormDataPtr;
18097 #else
18098   bfp = GetObjectExtra (i);
18099 #endif
18100   if (bfp == NULL) return;
18101   TestUpdateSequenceBaseForm (bfp, is_indexer, do_update, from_clipboard);
18102 }
18103 
18104 
TestUpdateSequenceIndexer(IteM i)18105 extern void TestUpdateSequenceIndexer (IteM i)
18106 {
18107   TestUpdateSequence (i, TRUE, TRUE, FALSE);
18108 }
18109 
TestUpdateSequenceClipboardIndexer(IteM i)18110 extern void TestUpdateSequenceClipboardIndexer (IteM i)
18111 {
18112   TestUpdateSequence (i, TRUE, TRUE, TRUE);
18113 }
18114 
18115 
TestExtendSequenceIndexer(IteM i)18116 extern void TestExtendSequenceIndexer (IteM i)
18117 {
18118   TestUpdateSequence (i, TRUE, FALSE, FALSE);
18119 }
18120 
TestUpdateSequenceSubmitter(IteM i)18121 extern void TestUpdateSequenceSubmitter (IteM i)
18122 {
18123   TestUpdateSequence (i, FALSE, TRUE, FALSE);
18124 }
18125 
TestExtendSequenceSubmitter(IteM i)18126 extern void TestExtendSequenceSubmitter (IteM i)
18127 {
18128   TestUpdateSequence (i, FALSE, FALSE, FALSE);
18129 }
18130 
18131 typedef struct seqentrydownload
18132 {
18133   FORM_MESSAGE_BLOCK
18134   GrouP           accntype;
18135   TexT            accession;
18136   ButtoN          accept;
18137 } SeqEntryDownloadData, PNTR SeqEntryDownloadPtr;
18138 
TypeAccessionProc(TexT t)18139 static void TypeAccessionProc (TexT t)
18140 
18141 {
18142   Boolean       alldigits;
18143   Char          ch;
18144   SeqEntryDownloadPtr sedp;
18145   CharPtr       ptr;
18146   Char          str [32];
18147 
18148   sedp = (SeqEntryDownloadPtr) GetObjectExtra (t);
18149   if (sedp == NULL) return;
18150   GetTitle (t, str, sizeof (str));
18151   if (StringHasNoText (str)) {
18152     SafeDisable (sedp->accept);
18153   } else {
18154     SafeEnable (sedp->accept);
18155     TrimSpacesAroundString (str);
18156     alldigits = TRUE;
18157     ptr = str;
18158     ch = *ptr;
18159     while (ch != '\0') {
18160       if (! IS_DIGIT (ch)) {
18161         alldigits = FALSE;
18162       }
18163       ptr++;
18164       ch = *ptr;
18165     }
18166     if (alldigits) {
18167       SafeSetValue (sedp->accntype, 2);
18168     } else {
18169       SafeSetValue (sedp->accntype, 1);
18170     }
18171   }
18172 }
18173 
18174 
SetContainsID(BioseqSetPtr bssp,SeqIdPtr sip)18175 static Boolean SetContainsID (BioseqSetPtr bssp, SeqIdPtr sip)
18176 {
18177   SeqEntryPtr sep;
18178   Boolean     rval = FALSE;
18179   BioseqPtr   bsp;
18180 
18181   if (bssp == NULL) return FALSE;
18182 
18183   for (sep = bssp->seq_set; sep != NULL && !rval; sep = sep->next) {
18184     if (IS_Bioseq (sep)) {
18185       bsp = (BioseqPtr) sep->data.ptrvalue;
18186       rval = SeqIdIn (sip, bsp->id);
18187     } else if (IS_Bioseq_set (sep)) {
18188       rval = SetContainsID ((BioseqSetPtr) sep->data.ptrvalue, sip);
18189     }
18190   }
18191   return rval;
18192 }
18193 
DeleteAllButRequestedSequenceAndItsProteins(BioseqSetPtr bssp,SeqIdPtr sip)18194 static void DeleteAllButRequestedSequenceAndItsProteins (BioseqSetPtr bssp, SeqIdPtr sip)
18195 {
18196   SeqEntryPtr sep;
18197   BioseqPtr   bsp;
18198 
18199   if (bssp == NULL) return;
18200 
18201   if (SetContainsID (bssp, sip)) {
18202     if (bssp->_class != BioseqseqSet_class_nuc_prot && bssp->_class != BioseqseqSet_class_segset) {
18203       /* delete all subsets that don't contain ID */
18204       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
18205         if (IS_Bioseq(sep)) {
18206           bsp = (BioseqPtr) sep->data.ptrvalue;
18207           if (bsp != NULL && !SeqIdIn (sip, bsp->id)) {
18208             bsp->idx.deleteme = TRUE;
18209           }
18210         } else if (IS_Bioseq_set (sep)) {
18211           DeleteAllButRequestedSequenceAndItsProteins ((BioseqSetPtr) sep->data.ptrvalue, sip);
18212         }
18213       }
18214     }
18215   } else {
18216     bssp->idx.deleteme = TRUE;
18217   }
18218 }
18219 
DownloadUpdateSequence(void)18220 static SeqEntryPtr DownloadUpdateSequence (void)
18221 {
18222   GrouP                 c;
18223   SeqEntryDownloadData  sedd;
18224   GrouP                 g;
18225   WindoW                w;
18226   ModalAcceptCancelData acd;
18227   ButtoN                b;
18228   SeqEntryPtr           fetched_sep = NULL;
18229   Char                  str [32];
18230   SeqIdPtr              sip;
18231   Uint2                 entityID;
18232   BioseqPtr             bsp;
18233   BioseqSetPtr          bssp;
18234 
18235   w = MovableModalWindow (-50, -33, -10, -10, "Download From Entrez", NULL);
18236   SetObjectExtra (w, &sedd, NULL);
18237   sedd.form = (ForM) w;
18238   SetGroupSpacing (w, 10, 10);
18239 
18240   g = HiddenGroup (w, -3, 0, NULL);
18241   StaticPrompt (g, "Type", 0, stdLineHeight, programFont, 'l');
18242   sedd.accntype = HiddenGroup (g, 4, 0, NULL);
18243   RadioButton (sedd.accntype, "Accession");
18244   RadioButton (sedd.accntype, "GI");
18245   SetValue (sedd.accntype, 1);
18246   sedd.accession = DialogText (g, "", 6, TypeAccessionProc);
18247   SetObjectExtra (sedd.accession, &sedd, NULL);
18248 
18249   c = HiddenGroup (w, 4, 0, NULL);
18250   SetGroupSpacing (c, 10, 2);
18251   sedd.accept = DefaultButton (c, "Retrieve", ModalAcceptButton);
18252   SetObjectExtra (sedd.accept, &acd, NULL);
18253   Disable (sedd.accept);
18254   b = PushButton (c, "Cancel", ModalCancelButton);
18255   SetObjectExtra (b, &acd, NULL);
18256 
18257   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
18258   RealizeWindow (w);
18259 
18260   Select (sedd.accession);
18261   Show (w);
18262   Select (w);
18263   Update ();
18264 
18265   acd.accepted = FALSE;
18266   acd.cancelled = FALSE;
18267   while (!acd.accepted && ! acd.cancelled)
18268   {
18269     ProcessExternalEvent ();
18270     Update ();
18271   }
18272   ProcessAnEvent ();
18273 
18274   if (acd.accepted)
18275   {
18276     Hide (w);
18277     WatchCursor ();
18278     Update ();
18279 
18280     GetTitle (sedd.accession, str, sizeof (str));
18281     if (!StringHasNoText (str))
18282     {
18283       sip = SeqIdFromPubSeqString (str);
18284       fetched_sep = PubSeqSynchronousQueryId (sip, 0, /* -1 */ 0);
18285       ArrowCursor ();
18286       Update ();
18287       if (fetched_sep == NULL)
18288       {
18289         Message (MSG_OK, "Unable to find this record in the database.");
18290       }
18291       else
18292       {
18293         if (IS_Bioseq (fetched_sep))
18294         {
18295           bsp = (BioseqPtr) fetched_sep->data.ptrvalue;
18296           entityID = ObjMgrGetEntityIDForPointer (bsp);
18297         }
18298         else
18299         {
18300           bssp = (BioseqSetPtr) fetched_sep->data.ptrvalue;
18301           entityID = ObjMgrGetEntityIDForPointer (bssp);
18302           AssignIDsInEntityEx (entityID, 0, NULL, NULL);
18303           DeleteAllButRequestedSequenceAndItsProteins (bssp, sip);
18304           if (bssp->idx.deleteme) {
18305             fetched_sep = NULL;
18306           }
18307           DeleteMarkedObjects (0, OBJ_BIOSEQSET, bssp);
18308         }
18309       }
18310       sip = SeqIdFree (sip);
18311     }
18312   }
18313   Remove (w);
18314   return fetched_sep;
18315 }
18316 
18317 
UpdateSequenceViaDownload(IteM i,Boolean is_indexer)18318 static void UpdateSequenceViaDownload (IteM i, Boolean is_indexer)
18319 {
18320   BaseFormPtr bfp;
18321   SeqEntryPtr sep;
18322   BioseqPtr   orig_bsp;
18323   Boolean     is_na;
18324   SeqEntryPtr update_sep;
18325 
18326 #ifdef WIN_MAC
18327   bfp = currentFormDataPtr;
18328 #else
18329   bfp = GetObjectExtra (i);
18330 #endif
18331   if (bfp == NULL) return;
18332 
18333   /* for test purposes, need to load sequence and update sequence */
18334   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
18335   if (sep == NULL)
18336     return;
18337   orig_bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID,
18338 			   bfp->input_itemtype);
18339   if (orig_bsp == NULL)
18340     return;
18341 
18342   is_na = ISA_na (orig_bsp->mol);
18343 
18344   update_sep = DownloadUpdateSequence ();
18345   if (update_sep == NULL)
18346   {
18347     return;
18348   }
18349 
18350   UpdateSingleSequence (orig_bsp, update_sep, is_indexer, TRUE, TRUE, bfp->input_entityID);
18351 }
18352 
UpdateSequenceViaDownloadIndexer(IteM i)18353 extern void UpdateSequenceViaDownloadIndexer (IteM i)
18354 {
18355   UpdateSequenceViaDownload (i, TRUE);
18356 }
18357 
UpdateSequenceViaDownloadSubmitter(IteM i)18358 extern void UpdateSequenceViaDownloadSubmitter (IteM i)
18359 {
18360   UpdateSequenceViaDownload (i, FALSE);
18361 }
18362 
18363