|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/sequin/sequin9.c |
source navigation diff markup identifier search freetext search file search |
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.480 $
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
66 /*-------------------*/
67 /* Defined Constants */
68 /*-------------------*/
69
70 #define MAX_ID_LEN 41
71 #define FASTA_READ_OK 0
72 #define FASTA_READ_ERROR -1
73 #define FASTA_READ_DONE 1
74
75 #define CONVERTPUBS_NOT_SET 0
76 #define CONVERTPUBS_YES 1
77 #define CONVERTPUBS_NO 2
78
79 /* constants for update sequence */
80 #define UPDATE_CHOICE_NOT_SET 0
81 #define UPDATE_SEQUENCE_ONLY 1
82 #define UPDATE_FEATURES_ONLY 2
83 #define UPDATE_SEQUENCE_AND_FEATURES 3
84
85 #define UPDATE_REPLACE 1
86 #define UPDATE_EXTEND5 2
87 #define UPDATE_EXTEND3 3
88 #define UPDATE_PATCH 4
89
90 enum update_dup_feat_type
91 {
92 UPDATE_FEAT_DUP_NOT_SET = 0,
93 UPDATE_FEAT_DUP_USE_NEW,
94 UPDATE_FEAT_DUP_USE_OLD,
95 UPDATE_FEAT_DUP_USE_BOTH,
96 UPDATE_FEAT_DUP_MERGE,
97 UPDATE_FEAT_DUP_REPLACE
98 };
99
100
101 /*-----------------*/
102 /* Data Structures */
103 /*-----------------*/
104
105 typedef struct {
106 Char newId[MAX_ID_LEN];
107 BioseqPtr matchingBsp;
108 } UpdateData, PNTR UpdateDataPtr;
109
110 typedef struct upsdata {
111 FORM_MESSAGE_BLOCK
112 ButtoN accept;
113 ButtoN acceptAll;
114 CharPtr aln1;
115 CharPtr aln2;
116 Int4 aln_length;
117 Int2 charwidth;
118 Int2 convertPubs;
119 VieweR details;
120 Boolean diffOrgs;
121 SegmenT dtpict;
122 FILE *fp;
123 ValNodePtr indels;
124 Boolean isSet;
125 ButtoN keepProteinIDs;
126 PaneL letters;
127 Int2 lineheight;
128 Int4 log10_aln_length;
129 Int2 maxchars;
130 ValNodePtr mismatches;
131 Int4 new3;
132 Int4 new5;
133 Int4 newa;
134 BioseqPtr newbsp;
135 ButtoN replace_all;
136 GrouP nobm;
137 Int4 old3;
138 Int4 old5;
139 Int4 olda;
140 BioseqPtr oldbsp;
141 VieweR overview;
142 SegmenT ovpict;
143 Int4 recomb1;
144 Int4 recomb2;
145 Boolean revcomp;
146 GrouP rmc;
147 SeqAlignPtr salp;
148 Int4 scaleX;
149 CharPtr seq1;
150 CharPtr seq2;
151 GrouP sfb;
152 Int4 startmax;
153 Int4 stopmax;
154 Uint1 strandnew;
155 Uint1 strandold;
156 Boolean useGUI;
157 Boolean do_update;
158 ButtoN add_cit_subs;
159 ButtoN update_proteins;
160 Boolean suppress_continue_msg;
161 Boolean suppress_instant_refresh;
162 ButtoN update_quality_scores_btn;
163 FILE *log_fp;
164 Char log_path [PATH_MAX];
165 Boolean data_in_log;
166 ButtoN truncate_proteins_btn;
167 ButtoN extend_proteins5_btn;
168 ButtoN extend_proteins3_btn;
169 ButtoN correct_cds_genes_btn;
170 Boolean truncate_proteins;
171 Boolean extend_proteins5;
172 Boolean extend_proteins3;
173 Boolean correct_cds_genes;
174 ValNodePtr transl_except_list;
175 Int2 rmcval; /* This is the choice selected from the
176 * rmc radio button group.
177 * We store it so that we can use it in
178 * Accept All.
179 */
180
181 SeqEntryPtr seqsubsep; /* when we are updating from a Sequin record
182 * that contains a set, store the set here.
183 */
184 Int4 seqsubpos; /* when we are updating from a Sequin record
185 * that contains a set, store the number of
186 * Bioseqs already processed here.
187 */
188
189 Int2 no_aln_choice; /* what to do when updating a set and no
190 * alignment is found.
191 */
192
193 ValNodePtr affected_variation_features; /* list of variation features
194 * affected by this update.
195 * by "affected" we mean that
196 * an insertion, deletion,
197 * or replacement takes place
198 * either inside the variation
199 * location, or immediately
200 * to the left or right of the
201 * location.
202 */
203 } UpsData, PNTR UpsDataPtr;
204
205 /*---------------------*/
206 /* Function prototypes */
207 /*---------------------*/
208
209 static Int2 UpdateNextBioseqInFastaSet (UpsDataPtr udp);
210 static void FreeUdpFields (UpsDataPtr udp);
211 static void TruncateCDS (SeqFeatPtr sfp, Uint1 frame, BioseqPtr pbsp);
212
213 extern void SubmitToNCBI (IteM i);
214 extern void QuitProc (void);
215 extern void NewFeaturePropagate (IteM i);
216 extern void FixCdsAfterPropagate (IteM i);
217 extern void MakeRedundantGPSwithProp (IteM i);
218 extern void MakeRedundantGPSnoProp (IteM i);
219 extern void MakeRedundantGPSjustXref (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 */
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 */
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
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
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
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
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
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 static void SimpleVecScreenCommon (IteM i, CharPtr database)
750
751 {
752 BaseFormPtr bfp;
753 BioseqPtr bsp;
754 Char date [32];
755 DatePtr dp;
756 Int4 max;
757 Char path [PATH_MAX];
758 CharPtr pathplusone;
759 Char quote [4];
760 SeqEntryPtr sep;
761 VsData vsd;
762
763 #ifdef WIN_MAC
764 bfp = (BaseFormPtr) currentFormDataPtr;
765 #else
766 bfp = (BaseFormPtr) GetObjectExtra (i);
767 #endif
768 if (bfp == NULL) return;
769
770 path [0] = '"';
771 path [1] = '\0';
772 pathplusone = &(path [1]);
773 GetAppParam ("NCBI", "NCBI", "DATA", "", pathplusone, sizeof (path) - 1);
774
775 /*
776 if (StringChr (path, ' ') != NULL) {
777 Message (MSG_OK, "Unable to process because vector database file\npath must not have a space character. Path is:\n'%s'", path);
778 return;
779 }
780 */
781
782 FileBuildPath (pathplusone, NULL, database);
783 quote [0] = '"';
784 quote [1] = '\0';
785 StringCat (pathplusone, quote);
786
787 date [0] = '\0';
788 dp = DateCurr ();
789 DatePrint (dp, date);
790 DateFree (dp);
791
792 vsd.date = date;
793 vsd.path = path;
794 vsd.database = database;
795 vsd.changed = FALSE;
796 vsd.count = 0;
797 vsd.mon = NULL;
798
799 bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
800 if (bsp != NULL) {
801 DoVecScreens (bsp, (Pointer) &vsd);
802 } else {
803 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
804 if (sep == NULL) return;
805 max = 0;
806 VisitBioseqsInSep (sep, (Pointer) &max, CountVecScreens);
807 if (max > 2) {
808 vsd.mon = MonitorIntNewEx ("VecScreen Progress", 0, max - 1, FALSE);
809 }
810 VisitBioseqsInSep (sep, (Pointer) &vsd, DoVecScreens);
811 if (vsd.mon != NULL) {
812 vsd.mon = MonitorFree (vsd.mon);
813 Update ();
814 }
815 }
816
817 if (vsd.changed) {
818 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
819 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
820 Update ();
821 } else {
822 Message (MSG_POST, "No vector contamination found");
823 }
824 }
825
826 extern void SimpleUniVecScreenProc (IteM i)
827
828 {
829 SimpleVecScreenCommon (i, "UniVec");
830 }
831
832 extern void SimpleUniVecCoreScreenProc (IteM i)
833
834 {
835 SimpleVecScreenCommon (i, "UniVec_Core");
836 }
837
838 static QBQUEUE qbquerylist = NULL;
839
840 static void LIBCALLBACK QBAnnounceCallback (CharPtr requestID, CharPtr seqID, Int2 estimatedSeconds)
841
842 {
843 if (StringHasNoText (requestID)) {
844 requestID = "?";
845 }
846 if (StringHasNoText (seqID)) {
847 seqID = "?";
848 }
849 Message (MSG_POST, "Queued rID %s, seqID %s, estimated seconds = %d",
850 requestID, seqID, (int) estimatedSeconds);
851 }
852
853 static Boolean LIBCALLBACK QBCallback (
854 CharPtr filename,
855 VoidPtr userdata,
856 CharPtr requestID,
857 CharPtr seqID,
858 Boolean success
859 )
860
861 {
862 if (StringHasNoText (requestID)) {
863 requestID = "?";
864 }
865 if (StringHasNoText (seqID)) {
866 seqID = "?";
867 }
868 if (success) {
869 if (! SequinHandleNetResults (filename)) {
870 /* LaunchGeneralTextViewer (path, "QueueFastaQueryToURL failed"); */
871 }
872 } else {
873 Message (MSG_POST, "Failure of rID '%s', seqID %s", requestID, seqID);
874 }
875 return TRUE;
876 }
877
878 static void SimpleQBlastProc (IteM i)
879
880 {
881 BaseFormPtr bfp;
882 BioseqPtr bsp;
883 NewObjectPtr nop;
884 SeqEntryPtr sep = NULL;
885 Int2 which;
886
887 nop = (NewObjectPtr) GetObjectExtra (i);
888 if (nop == NULL) return;
889 #ifdef WIN_MAC
890 bfp = (BaseFormPtr) currentFormDataPtr;
891 #else
892 bfp = nop->bfp;
893 #endif
894 if (bfp == NULL) return;
895 which = BioseqViewOrDocSumChoice (nop);
896 if (which != 1) return;
897 bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
898 if (bsp != NULL) {
899 sep = SeqMgrGetSeqEntryForData (bsp);
900 } else {
901 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
902 }
903 if (sep == NULL) return;
904
905 QBlastAsynchronousRequest ("nr", "blastn", bsp, &qbquerylist, QBCallback, QBAnnounceCallback, NULL);
906 }
907
908 /* Analysis menu can launch external programs or use Web services */
909
910 static QUEUE urlquerylist = NULL;
911
912 static Int4 pendingqueries = 0;
913
914 static Boolean LIBCALLBACK SubmitToNCBIResultProc (CONN conn, VoidPtr userdata, EIO_Status status)
915
916 {
917 AsnIoPtr aop;
918 FILE *fp;
919 Char path [PATH_MAX];
920 SeqEntryPtr sep;
921
922 TmpNam (path);
923 fp = FileOpen (path, "wb");
924 QUERY_CopyResultsToFile (conn, fp);
925 FileClose (fp);
926 aop = AsnIoOpen (path, "rb");
927 sep = SeqEntryAsnRead (aop, NULL);
928 AsnIoClose (aop);
929 aop = AsnIoOpen (path, "w");
930 SeqEntryAsnWrite (sep, aop, NULL);
931 AsnIoFlush (aop);
932 AsnIoClose (aop);
933 LaunchGeneralTextViewer (path, "Echo binary transformation of Seq-entry");
934 FileRemove (path);
935 return TRUE;
936 }
937
938 extern void SubmitToNCBI (IteM i)
939
940 {
941 AsnIoPtr aop;
942 BaseFormPtr bfp;
943 CONN conn;
944 FILE *fp;
945 Char path [PATH_MAX];
946 Char progname [64];
947 SeqEntryPtr sep;
948
949 #ifdef WIN_MAC
950 bfp = currentFormDataPtr;
951 #else
952 bfp = GetObjectExtra (i);
953 #endif
954 if (bfp == NULL) return;
955 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
956 if (sep == NULL) return;
957
958 sprintf (progname, "Sequin/%s", SEQUIN_APPLICATION);
959
960 TmpNam (path);
961
962 aop = AsnIoOpen (path, "wb");
963 SeqEntryAsnWrite (sep, aop, NULL);
964 AsnIoFlush (aop);
965 AsnIoClose (aop);
966
967 conn = QUERY_OpenUrlQuery ("cruncher.nlm.nih.gov", 80,
968 "/cgi-bin/Sequin/testcgi.cgi", "request=echo",
969 progname, 30, eMIME_T_NcbiData, eMIME_AsnBinary,
970 eENCOD_Url,
971 fHCC_UrlDecodeInput | fHCC_UrlEncodeOutput);
972
973 fp = FileOpen (path, "rb");
974 QUERY_CopyFileToQuery (conn, fp);
975 FileClose (fp);
976
977 QUERY_SendQuery (conn);
978
979 QUERY_AddToQueue (&urlquerylist, conn, SubmitToNCBIResultProc, NULL, TRUE);
980
981 pendingqueries++;
982
983 FileRemove (path);
984 }
985
986 static QUEUE cddquerylist = NULL;
987
988 static Int2 cddquerynum = 0;
989
990 #include <cddapi.h>
991
992 #define CDD_EXPECT_VALUE 0.01
993
994 static Boolean LIBCALLBACK CddProc (
995 CONN conn,
996 VoidPtr userdata,
997 EIO_Status status
998 )
999
1000 {
1001 BioseqPtr bsp;
1002 SeqAnnotPtr prev;
1003 SeqAnnotPtr sap;
1004
1005 if (conn == NULL || userdata == NULL) return TRUE;
1006 if (status != eIO_Success) return TRUE;
1007 sap = CddReadReply (conn, status);
1008 if (sap == NULL) return FALSE;
1009
1010 bsp = (BioseqPtr) userdata;
1011 CddCorrectIDs (bsp, sap);
1012
1013 prev = bsp->annot;
1014 if (prev == NULL) {
1015 bsp->annot = sap;
1016 } else {
1017 while (prev->next != NULL) {
1018 prev = prev->next;
1019 }
1020 prev->next = sap;
1021 }
1022
1023 ObjMgrSetDirtyFlag (bsp->idx.entityID, TRUE);
1024 ObjMgrSendMsg (OM_MSG_UPDATE, bsp->idx.entityID, 0, 0);
1025
1026 return TRUE;
1027 }
1028
1029 static void SearchCDD (BioseqPtr bsp, Pointer userdata)
1030
1031 {
1032 BoolPtr dofeats;
1033
1034 if (bsp == NULL) return;
1035 if (! ISA_aa (bsp->mol)) return;
1036
1037 dofeats = (BoolPtr) userdata;
1038 if (! CddAsynchronousQuery (bsp, CDD_EXPECT_VALUE, TRUE, TRUE, *dofeats, "cdd", FALSE, &cddquerylist, CddProc, (Pointer) bsp)) {
1039 ErrPostEx (SEV_ERROR, 0, 0, "Unable to run CDD search");
1040 } else {
1041 cddquerynum++;
1042 }
1043 }
1044
1045 /*
1046 static void SearchCDD (BioseqPtr bsp, Pointer userdata)
1047
1048 {
1049 BoolPtr dofeats;
1050 SeqAnnotPtr prev;
1051 SeqAnnotPtr sap;
1052
1053 if (bsp == NULL) return;
1054 if (! ISA_aa (bsp->mol)) return;
1055
1056 dofeats = (BoolPtr) userdata;
1057 sap = CddSynchronousQuery (bsp, CDD_EXPECT_VALUE, TRUE, TRUE, *dofeats, "cdd", FALSE);
1058 if (sap == NULL) return;
1059 CddCorrectIDs (bsp, sap);
1060
1061 prev = bsp->annot;
1062 if (prev == NULL) {
1063 bsp->annot = sap;
1064 } else {
1065 while (prev->next != NULL) {
1066 prev = prev->next;
1067 }
1068 prev->next = sap;
1069 }
1070 }
1071 */
1072
1073 static void SimpleCDDSearchCommonProc (IteM i, Boolean makeFeats)
1074
1075 {
1076 BaseFormPtr bfp;
1077 Boolean dofeats;
1078 SeqEntryPtr sep;
1079
1080 #ifdef WIN_MAC
1081 bfp = currentFormDataPtr;
1082 #else
1083 bfp = GetObjectExtra (i);
1084 #endif
1085 if (bfp == NULL) return;
1086 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1087 if (sep == NULL) return;
1088
1089 WatchCursor ();
1090 Update ();
1091
1092 if (makeFeats) {
1093 FreeCDDRegions (sep);
1094 } else {
1095 FreeCDDAligns (sep);
1096 }
1097
1098 dofeats = makeFeats;
1099 VisitBioseqsInSep (sep, (Pointer) &dofeats, SearchCDD);
1100
1101 /*
1102 RemoveDuplicateCDDs (sep);
1103
1104 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1105 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1106 */
1107 ArrowCursor ();
1108 Update ();
1109 }
1110
1111 void SimpleCDDSearchFeatProc (IteM i)
1112
1113 {
1114 SimpleCDDSearchCommonProc (i, TRUE);
1115 }
1116
1117 void SimpleCDDSearchAlignProc (IteM i)
1118
1119 {
1120 SimpleCDDSearchCommonProc (i, FALSE);
1121 }
1122
1123 extern void SequinCheckSocketsProc (void)
1124
1125 {
1126 Int4 remaining;
1127
1128 remaining = QUERY_CheckQueue (&urlquerylist);
1129 if (remaining < pendingqueries) {
1130 Beep ();
1131 pendingqueries--;
1132 }
1133 remaining = VecScreenCheckQueue (&vsquerylist);
1134 if (remaining < vsquerynum) {
1135 vsquerynum = remaining;
1136 Message (MSG_POST, "There are %d vector screens remaining", (int) vsquerynum);
1137 }
1138 remaining = QBlastCheckQueue (&qbquerylist);
1139 remaining = CddCheckQueue (&cddquerylist);
1140 if (remaining < cddquerynum) {
1141 cddquerynum = remaining;
1142 Message (MSG_POST, "There are %d cdd searches remaining", (int) cddquerynum);
1143 }
1144 }
1145
1146 static Boolean LIBCALLBACK DemoModeResultProc (CONN conn, VoidPtr userdata, EIO_Status status)
1147
1148 {
1149 FILE *fp;
1150 Char path [PATH_MAX];
1151
1152 TmpNam (path);
1153 fp = FileOpen (path, "w");
1154 QUERY_CopyResultsToFile (conn, fp);
1155 FileClose (fp);
1156 LaunchGeneralTextViewer (path, "QueueFastaQueryToURL results");
1157 FileRemove (path);
1158 return TRUE;
1159 }
1160
1161 static Boolean LIBCALLBACK SequinHandleURLResults (CONN conn, VoidPtr userdata, EIO_Status status)
1162
1163 {
1164 FILE *fp;
1165 Char path [PATH_MAX];
1166
1167 TmpNam (path);
1168 fp = FileOpen (path, "w");
1169 QUERY_CopyResultsToFile (conn, fp);
1170 FileClose (fp);
1171 if (! SequinHandleNetResults (path)) {
1172 /* LaunchGeneralTextViewer (path, "QueueFastaQueryToURL failed"); */
1173 }
1174 FileRemove (path);
1175 return TRUE;
1176 }
1177
1178 static void FinishURLProc (NewObjectPtr nop, CharPtr arguments, CharPtr path)
1179
1180 {
1181 CONN conn;
1182 FILE *fp;
1183 Char progname [64];
1184 QueryResultProc resultproc;
1185 EMIME_SubType subtype;
1186
1187 sprintf (progname, "Sequin/%s", SEQUIN_APPLICATION);
1188
1189 if (nop->demomode) {
1190 resultproc = DemoModeResultProc;
1191 } else {
1192 resultproc = nop->resultproc;
1193 }
1194 if (nop->format == 1) {
1195 subtype = eMIME_Fasta;
1196 } else if (nop->format == 2) {
1197 subtype = eMIME_AsnText;
1198 } else {
1199 subtype = eMIME_Unknown;
1200 }
1201
1202 conn = QUERY_OpenUrlQuery (nop->host_machine, nop->host_port,
1203 nop->host_path, arguments,
1204 progname, nop->timeoutsec,
1205 eMIME_T_NcbiData, subtype, eENCOD_Url,
1206 fHCC_UrlDecodeInput | fHCC_UrlEncodeOutput);
1207 if (conn == NULL) return;
1208
1209 fp = FileOpen (path, "r");
1210 QUERY_CopyFileToQuery (conn, fp);
1211 FileClose (fp);
1212
1213 QUERY_SendQuery (conn);
1214
1215 QUERY_AddToQueue (&urlquerylist, conn, resultproc, NULL, TRUE);
1216
1217 pendingqueries++;
1218 }
1219
1220 static void DoAnalysisProc (NewObjectPtr nop, BaseFormPtr bfp, Int2 which, CharPtr arguments, ResultProc dotheanalysis)
1221
1222 {
1223 AsnIoPtr aop;
1224 BioseqPtr bsp;
1225 Char path1 [PATH_MAX];
1226 SeqEntryPtr sep;
1227
1228 if (nop == NULL || bfp == NULL) return;
1229 switch (which) {
1230 case 1 :
1231 if (BioseqViewCanSaveFasta (bfp->form, nop->fastaNucOK, nop->fastaProtOK, nop->onlyBspTarget)) {
1232 TmpNam (path1);
1233 switch (nop->format) {
1234 case 1 :
1235 ExportBioseqViewFasta (bfp->form, path1, nop->fastaNucOK, nop->fastaProtOK, nop->onlyBspTarget);
1236 break;
1237 case 2 :
1238 sep = NULL;
1239 if (nop->onlyBspTarget) {
1240 bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
1241 sep = SeqMgrGetSeqEntryForData (bsp);
1242 } else {
1243 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1244 }
1245 if (sep != NULL) {
1246 aop = AsnIoOpen (path1, "w");
1247 SeqEntryAsnWrite (sep, aop, NULL);
1248 AsnIoFlush (aop);
1249 AsnIoClose (aop);
1250 }
1251 break;
1252 default :
1253 break;
1254 }
1255 if (dotheanalysis != NULL) {
1256 dotheanalysis (path1);
1257 } else {
1258 FinishURLProc (nop, arguments, path1);
1259 }
1260 FileRemove (path1);
1261 } else {
1262 ErrPostEx (SEV_ERROR, 0, 0, "BioseqView cannot save fasta format");
1263 }
1264 break;
1265 case 2 :
1266 /*
1267 if (DocSumCanSaveFasta (bfp->form, nop->fastaNucOK, nop->fastaProtOK)) {
1268 TmpNam (path1);
1269 ExportDocSumFasta (bfp->form, path1, nop->fastaNucOK, nop->fastaProtOK);
1270 if (dotheanalysis != NULL) {
1271 dotheanalysis (path1);
1272 } else {
1273 FinishURLProc (nop, arguments, path1);
1274 }
1275 FileRemove (path1);
1276 } else {
1277 ErrPostEx (SEV_ERROR, 0, 0, "DocSum cannot save fasta format");
1278 }
1279 */
1280 ErrPostEx (SEV_ERROR, 0, 0, "DocSum cannot save fasta format");
1281 break;
1282 default :
1283 break;
1284 }
1285 }
1286
1287 /* encodes spaces as %20 in URLs */
1288 static CharPtr StrSaveNoNullEncodeSpaces (CharPtr from)
1289
1290 {
1291 Char ch;
1292 size_t len = 0;
1293 CharPtr p;
1294 CharPtr q;
1295 CharPtr to;
1296
1297 if (StringHasNoText (from)) return NULL;
1298 p = from;
1299 ch = *p;
1300 while (ch != '\0') {
1301 if (ch == ' ') {
1302 len += 3;
1303 } else {
1304 len++;
1305 }
1306 p++;
1307 ch = *p;
1308 }
1309 to = MemNew (len + 1);
1310 if (to == NULL) return NULL;
1311
1312 q = to;
1313 p = from;
1314 ch = *p;
1315 while (ch != '\0') {
1316 if (ch == ' ') {
1317 *q = '%';
1318 q++;
1319 *q = '2';
1320 q++;
1321 *q = '0';
1322 q++;
1323 } else {
1324 *q = ch;
1325 q++;
1326 }
1327 p++;
1328 ch = *p;
1329 }
1330 *q = '\0';
1331 return to;
1332 }
1333
1334 typedef struct urlargform {
1335 FORM_MESSAGE_BLOCK
1336
1337 NewObjectPtr nop;
1338 BaseFormPtr bfp;
1339 ValNodePtr controls;
1340 ValNodePtr helps;
1341 Int2 which;
1342 } UrlArgForm, PNTR UrlArgFormPtr;
1343
1344 static void AcceptArgumentFormProc (ButtoN b)
1345
1346 {
1347 CharPtr args = NULL;
1348 CharPtr arguments = NULL;
1349 ButtoN btn;
1350 Char ch;
1351 Int2 choice;
1352 Char cpy [256];
1353 GrouP grp;
1354 ValNodePtr head = NULL;
1355 Int2 i;
1356 CharPtr itms;
1357 CharPtr last;
1358 size_t len;
1359 LisT lst;
1360 NewObjectPtr nop;
1361 Boolean notFirst = FALSE;
1362 PopuP pop;
1363 ValNodePtr ppt;
1364 CharPtr ptr;
1365 CharPtr str;
1366 Char tmp [256];
1367 TexT txt;
1368 UrlArgFormPtr ufp;
1369 UrlParamPtr upp;
1370 Int2 val;
1371 ValNodePtr vnp;
1372
1373 ufp = (UrlArgFormPtr) GetObjectExtra (b);
1374 if (ufp == NULL) return;
1375 Hide (ufp->form);
1376 Update ();
1377 nop = ufp->nop;
1378 if (nop != NULL) {
1379 if (! StringHasNoText (nop->prefix)) {
1380 ValNodeCopyStr (&head, 0, nop->prefix);
1381 }
1382 for (vnp = ufp->controls, ppt = nop->paramlist;
1383 vnp != NULL && ppt != NULL;
1384 vnp = vnp->next, ppt = ppt->next) {
1385 upp = (UrlParamPtr) ppt->data.ptrvalue;
1386 if (upp == NULL) continue;
1387 choice = vnp->choice;
1388 switch (upp->type) {
1389 case 1 :
1390 txt = (TexT) vnp->data.ptrvalue;
1391 str = SaveStringFromText (txt);
1392 if (str != NULL) {
1393 sprintf (tmp, "%s=%s", upp->param, str);
1394 ValNodeCopyStr (&head, ppt->choice, tmp);
1395 MemFree (str);
1396 }
1397 break;
1398 case 2 :
1399 btn = (ButtoN) vnp->data.ptrvalue;
1400 if (GetStatus (btn)) {
1401 sprintf (tmp, "%s=TRUE", upp->param);
1402 } else {
1403 sprintf (tmp, "%s=FALSE", upp->param);
1404 }
1405 ValNodeCopyStr (&head, ppt->choice, tmp);
1406 break;
1407 case 3 :
1408 pop = (PopuP) vnp->data.ptrvalue;
1409 val = GetValue (pop);
1410 if (val > 0) {
1411 i = 0;
1412 itms = upp->choices;
1413 StringNCpy_0 (tmp, itms, sizeof (tmp));
1414 last = tmp;
1415 ptr = last;
1416 ch = *ptr;
1417 while (ch != '\0') {
1418 if (ch == ',') {
1419 *ptr = '\0';
1420 i++;
1421 if (val == i) {
1422 sprintf (cpy, "%s=%s", upp->param, last);
1423 ValNodeCopyStr (&head, ppt->choice, cpy);
1424 }
1425 ptr++;
1426 last = ptr;
1427 ch = *ptr;
1428 } else {
1429 ptr++;
1430 ch = *ptr;
1431 }
1432 }
1433 if (! StringHasNoText (last)) {
1434 i++;
1435 if (val == i) {
1436 sprintf (cpy, "%s=%s", upp->param, last);
1437 ValNodeCopyStr (&head, ppt->choice, cpy);
1438 }
1439 }
1440 }
1441 break;
1442 case 4 :
1443 grp = (GrouP) vnp->data.ptrvalue;
1444 val = GetValue (grp);
1445 if (val > 0) {
1446 i = 0;
1447 itms = upp->choices;
1448 StringNCpy_0 (tmp, itms, sizeof (tmp));
1449 last = tmp;
1450 ptr = last;
1451 ch = *ptr;
1452 while (ch != '\0') {
1453 if (ch == ',') {
1454 *ptr = '\0';
1455 i++;
1456 if (val == i) {
1457 sprintf (cpy, "%s=%s", upp->param, last);
1458 ValNodeCopyStr (&head, ppt->choice, cpy);
1459 }
1460 ptr++;
1461 last = ptr;
1462 ch = *ptr;
1463 } else {
1464 ptr++;
1465 ch = *ptr;
1466 }
1467 }
1468 if (! StringHasNoText (last)) {
1469 i++;
1470 if (val == i) {
1471 sprintf (cpy, "%s=%s", upp->param, last);
1472 ValNodeCopyStr (&head, ppt->choice, cpy);
1473 }
1474 }
1475 }
1476 break;
1477 case 5 :
1478 lst = (LisT) vnp->data.ptrvalue;
1479 val = GetValue (lst);
1480 if (val > 0) {
1481 i = 0;
1482 itms = upp->choices;
1483 StringNCpy_0 (tmp, itms, sizeof (tmp));
1484 last = tmp;
1485 ptr = last;
1486 ch = *ptr;
1487 while (ch != '\0') {
1488 if (ch == ',') {
1489 *ptr = '\0';
1490 i++;
1491 if (val == i) {
1492 sprintf (cpy, "%s=%s", upp->param, last);
1493 ValNodeCopyStr (&head, ppt->choice, cpy);
1494 }
1495 ptr++;
1496 last = ptr;
1497 ch = *ptr;
1498 } else {
1499 ptr++;
1500 ch = *ptr;
1501 }
1502 }
1503 if (! StringHasNoText (last)) {
1504 i++;
1505 if (val == i) {
1506 sprintf (cpy, "%s=%s", upp->param, last);
1507 ValNodeCopyStr (&head, ppt->choice, cpy);
1508 }
1509 }
1510 }
1511 break;
1512 default :
1513 break;
1514 }
1515 }
1516 head = SortValNode (head, SortByVnpChoice);
1517 if (! StringHasNoText (nop->suffix)) {
1518 ValNodeCopyStr (&head, 0, nop->suffix);
1519 }
1520 for (len = 0, vnp = head; vnp != NULL; vnp = vnp->next) {
1521 len += StringLen ((CharPtr) vnp->data.ptrvalue) + 1;
1522 }
1523 if (len > 0) {
1524 arguments = MemNew (len + 5);
1525 if (arguments != NULL) {
1526 vnp = head;
1527 notFirst = FALSE;
1528 while (vnp != NULL) {
1529 if (notFirst) {
1530 StringCat (arguments, "&");
1531 }
1532 StringCat (arguments, (CharPtr) vnp->data.ptrvalue);
1533 notFirst = TRUE;
1534 vnp = vnp->next;
1535 }
1536 }
1537 }
1538 args = /* StrSaveNoNullEncodeSpaces */ StringSave (arguments);
1539 MemFree (arguments);
1540 DoAnalysisProc (nop, ufp->bfp, ufp->which, args, NULL);
1541 MemFree (args);
1542 }
1543 Remove (ufp->form);
1544 }
1545
1546 static void ShowArgumentHelp (ButtoN b)
1547
1548 {
1549 NewObjectPtr nop;
1550 ValNodePtr ppt;
1551 CharPtr str;
1552 UrlArgFormPtr ufp;
1553 UrlParamPtr upp;
1554 ValNodePtr vnp;
1555
1556 ufp = (UrlArgFormPtr) GetObjectExtra (b);
1557 if (ufp == NULL) return;
1558 nop = ufp->nop;
1559 if (nop == NULL) return;
1560 for (vnp = ufp->helps, 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 if ((Pointer) b == (Pointer) vnp->data.ptrvalue) {
1566 str = upp->help;
1567 Message (MSG_OK, "%s", str);
1568 return;
1569 }
1570 }
1571 Beep ();
1572 }
1573
1574 static void ArgumentFormMessage (ForM f, Int2 mssg)
1575
1576 {
1577 UrlArgFormPtr ufp;
1578
1579 ufp = (UrlArgFormPtr) GetObjectExtra (f);
1580 if (ufp != NULL) {
1581 switch (mssg) {
1582 case VIB_MSG_CLOSE :
1583 Remove (f);
1584 break;
1585 default :
1586 if (ufp->appmessage != NULL) {
1587 ufp->appmessage (f, mssg);
1588 }
1589 break;
1590 }
1591 }
1592 }
1593
1594 static void CleanupArgumentForm (GraphiC g, VoidPtr data)
1595
1596 {
1597 UrlArgFormPtr ufp;
1598
1599 ufp = (UrlArgFormPtr) data;
1600 if (ufp != NULL) {
1601 ValNodeFree (ufp->controls);
1602 ValNodeFree (ufp->helps);
1603 }
1604 StdCleanupFormProc (g, data);
1605 }
1606
1607 static ValNodePtr RearrangeParamList (ValNodePtr paramlist)
1608
1609 {
1610 ValNodePtr curr;
1611 CharPtr group;
1612 ValNodePtr head = NULL;
1613 ValNodePtr list;
1614 ValNodePtr next;
1615 ValNodePtr PNTR prev;
1616 ValNodePtr ppt;
1617 UrlParamPtr upp;
1618
1619 ppt = paramlist;
1620 while (ppt != NULL) {
1621 list = ppt->next;
1622 ppt->next = NULL;
1623 ValNodeLink (&head, ppt);
1624 upp = (UrlParamPtr) ppt->data.ptrvalue;
1625 if (upp == NULL) {
1626 ppt = list;
1627 continue;
1628 }
1629 group = upp->group;
1630 curr = list;
1631 prev = &list;
1632 while (curr != NULL) {
1633 next = curr->next;
1634 upp = (UrlParamPtr) curr->data.ptrvalue;
1635 if (upp == NULL) {
1636 prev = &(curr->next);
1637 curr = next;
1638 continue;
1639 }
1640 if (StringICmp (upp->group, group) == 0) {
1641 *prev = next;
1642 curr->next = NULL;
1643 ValNodeLink (&head, curr);
1644 } else {
1645 prev = &(curr->next);
1646 }
1647 curr = next;
1648 }
1649 ppt = list;
1650 }
1651 return head;
1652 }
1653
1654 static void BuildArgumentForm (NewObjectPtr nop, BaseFormPtr bfp, Int2 which)
1655
1656 {
1657 ButtoN b;
1658 ButtoN btn;
1659 GrouP c;
1660 Char ch;
1661 CharPtr def;
1662 Int2 delta;
1663 TexT first = NULL;
1664 GrouP g;
1665 GrouP grp;
1666 GrouP h;
1667 ValNodePtr hlp;
1668 Int2 i;
1669 CharPtr itms;
1670 CharPtr last;
1671 CharPtr lastGroup = " ";
1672 LisT lst;
1673 GrouP m;
1674 Int2 max;
1675 Int2 min;
1676 ValNodePtr moveMe = NULL;
1677 Nlm_Handle obj1, obj2;
1678 PopuP pop;
1679 PrompT prmpt;
1680 ValNodePtr ppt;
1681 CharPtr ptr;
1682 RecT r;
1683 StdEditorProcsPtr sepp;
1684 CharPtr str;
1685 Char tmp [128];
1686 TexT txt;
1687 UrlArgFormPtr ufp;
1688 UrlParamPtr upp;
1689 Int2 val;
1690 ValNodePtr vnp;
1691 WindoW w;
1692
1693 if (nop == NULL || bfp == NULL) return;
1694 ufp = (UrlArgFormPtr) MemNew (sizeof (UrlArgForm));
1695 if (ufp == NULL) return;
1696
1697 nop->paramlist = RearrangeParamList (nop->paramlist);
1698
1699 w = FixedWindow (-50, -33, -10, -10, "Arguments", NULL);
1700 SetObjectExtra (w, ufp, CleanupArgumentForm);
1701 ufp->form = (ForM) w;
1702 ufp->formmessage = ArgumentFormMessage;
1703
1704 sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
1705 if (sepp != NULL) {
1706 SetActivate (w, sepp->activateForm);
1707 ufp->appmessage = sepp->handleMessages;
1708 }
1709
1710 ufp->bfp = bfp;
1711 ufp->nop = nop;
1712 ufp->which = which;
1713
1714 m = HiddenGroup (w, 1, 0, NULL);
1715
1716 g = NULL;
1717 for (ppt = nop->paramlist;
1718 ppt != NULL;
1719 ppt = ppt->next) {
1720 upp = (UrlParamPtr) ppt->data.ptrvalue;
1721 if (upp == NULL) continue;
1722 if (StringICmp (upp->group, lastGroup) != 0) {
1723 if (StringHasNoText (upp->group)) {
1724 if (StringHasNoText (lastGroup)) {
1725 g = HiddenGroup (m, 3, 0, NULL);
1726 } else {
1727 g = NormalGroup (m, 3, 0, "", programFont, NULL);
1728 }
1729 } else {
1730 g = NormalGroup (m, 3, 0, upp->group, programFont, NULL);
1731 }
1732 lastGroup = upp->group;
1733 }
1734 if (g == NULL) {
1735 g = HiddenGroup (m, 3, 0, NULL);
1736 }
1737 switch (upp->type) {
1738 case 1 :
1739 str = upp->prompt;
1740 StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
1741 def = upp->dfault;
1742 if (StringHasNoText (def)) {
1743 def = "";
1744 }
1745 txt = DialogText (g, def, 10, NULL);
1746 if (first == NULL) {
1747 first = txt;
1748 }
1749 ValNodeAddPointer (&(ufp->controls), 1, (Pointer) txt);
1750 ValNodeAddPointer (&moveMe, 0, (Pointer) txt);
1751 b = PushButton (g, "?", ShowArgumentHelp);
1752 SetObjectExtra (b, ufp, NULL);
1753 ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1754 break;
1755 case 2 :
1756 str = upp->prompt;
1757 btn = CheckBox (g, str, NULL);
1758 def = upp->dfault;
1759 if (StringICmp (def, "TRUE") == 0) {
1760 SetStatus (btn, TRUE);
1761 }
1762 prmpt = StaticPrompt (g, "", 0, 0, programFont, 'l');
1763 ValNodeAddPointer (&moveMe, 0, (Pointer) prmpt);
1764 ValNodeAddPointer (&(ufp->controls), 2, (Pointer) btn);
1765 b = PushButton (g, "?", ShowArgumentHelp);
1766 SetObjectExtra (b, ufp, NULL);
1767 ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1768 break;
1769 case 3 :
1770 str = upp->prompt;
1771 StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
1772 h = HiddenGroup (g, 1, 0, NULL);
1773 pop = PopupList (h, TRUE, NULL);
1774 def = upp->dfault;
1775 val = 0;
1776 i = 0;
1777 itms = upp->choices;
1778 StringNCpy_0 (tmp, itms, sizeof (tmp));
1779 last = tmp;
1780 ptr = last;
1781 ch = *ptr;
1782 while (ch != '\0') {
1783 if (ch == ',') {
1784 *ptr = '\0';
1785 PopupItem (pop, last);
1786 i++;
1787 if (StringICmp (def, last) == 0) {
1788 val = i;
1789 }
1790 ptr++;
1791 last = ptr;
1792 ch = *ptr;
1793 } else {
1794 ptr++;
1795 ch = *ptr;
1796 }
1797 }
1798 if (! StringHasNoText (last)) {
1799 PopupItem (pop, last);
1800 i++;
1801 if (StringICmp (def, last) == 0) {
1802 val = i;
1803 }
1804 }
1805 if (val > 0) {
1806 SetValue (pop, val);
1807 }
1808 ValNodeAddPointer (&(ufp->controls), 3, (Pointer) pop);
1809 ValNodeAddPointer (&moveMe, 0, (Pointer) pop);
1810 b = PushButton (g, "?", ShowArgumentHelp);
1811 SetObjectExtra (b, ufp, NULL);
1812 ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1813 break;
1814 case 4 :
1815 str = upp->prompt;
1816 StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
1817 h = HiddenGroup (g, 1, 0, NULL);
1818 grp = HiddenGroup (h, -5, 0, NULL);
1819 def = upp->dfault;
1820 val = 0;
1821 i = 0;
1822 itms = upp->choices;
1823 StringNCpy_0 (tmp, itms, sizeof (tmp));
1824 last = tmp;
1825 ptr = last;
1826 ch = *ptr;
1827 while (ch != '\0') {
1828 if (ch == ',') {
1829 *ptr = '\0';
1830 RadioButton (grp, last);
1831 i++;
1832 if (StringICmp (def, last) == 0) {
1833 val = i;
1834 }
1835 ptr++;
1836 last = ptr;
1837 ch = *ptr;
1838 } else {
1839 ptr++;
1840 ch = *ptr;
1841 }
1842 }
1843 if (! StringHasNoText (last)) {
1844 RadioButton (grp, last);
1845 i++;
1846 if (StringICmp (def, last) == 0) {
1847 val = i;
1848 }
1849 }
1850 if (val > 0) {
1851 SetValue (grp, val);
1852 }
1853 ValNodeAddPointer (&(ufp->controls), 4, (Pointer) grp);
1854 ValNodeAddPointer (&moveMe, 0, (Pointer) grp);
1855 b = PushButton (g, "?", ShowArgumentHelp);
1856 SetObjectExtra (b, ufp, NULL);
1857 ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1858 break;
1859 case 5 :
1860 str = upp->prompt;
1861 StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
1862 h = HiddenGroup (g, 1, 0, NULL);
1863 lst = SingleList (h, 10, 3, NULL);
1864 def = upp->dfault;
1865 val = 0;
1866 i = 0;
1867 itms = upp->choices;
1868 StringNCpy_0 (tmp, itms, sizeof (tmp));
1869 last = tmp;
1870 ptr = last;
1871 ch = *ptr;
1872 while (ch != '\0') {
1873 if (ch == ',') {
1874 *ptr = '\0';
1875 ListItem (lst, last);
1876 i++;
1877 if (StringICmp (def, last) == 0) {
1878 val = i;
1879 }
1880 ptr++;
1881 last = ptr;
1882 ch = *ptr;
1883 } else {
1884 ptr++;
1885 ch = *ptr;
1886 }
1887 }
1888 if (! StringHasNoText (last)) {
1889 ListItem (lst, last);
1890 i++;
1891 if (StringICmp (def, last) == 0) {
1892 val = i;
1893 }
1894 }
1895 if (val > 0) {
1896 SetValue (lst, val);
1897 }
1898 ValNodeAddPointer (&(ufp->controls), 5, (Pointer) lst);
1899 ValNodeAddPointer (&moveMe, 0, (Pointer) lst);
1900 b = PushButton (g, "?", ShowArgumentHelp);
1901 SetObjectExtra (b, ufp, NULL);
1902 ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
1903 break;
1904 default :
1905 break;
1906 }
1907 }
1908
1909 min = 0;
1910 max = 0;
1911 for (vnp = moveMe; vnp != NULL; vnp = vnp->next) {
1912 obj1 = (Nlm_Handle) vnp->data.ptrvalue;
1913 GetPosition (obj1, &r);
1914 min = MAX (min, r.left);
1915 }
1916 for (vnp = moveMe; vnp != NULL; vnp = vnp->next) {
1917 obj1 = (Nlm_Handle) vnp->data.ptrvalue;
1918 GetPosition (obj1, &r);
1919 delta = min - r.left;
1920 OffsetRect (&r, delta, 0);
1921 SetPosition (obj1, &r);
1922 AdjustPrnt (obj1, &r, FALSE);
1923 max = MAX (max, r.right);
1924 }
1925 max += 3;
1926 for (vnp = moveMe, hlp = ufp->helps;
1927 vnp != NULL && hlp != NULL;
1928 vnp = vnp->next, hlp = hlp->next) {
1929 obj2 = (Nlm_Handle) hlp->data.ptrvalue;
1930 GetPosition (obj2, &r);
1931 delta = max - r.left;
1932 OffsetRect (&r, delta, 0);
1933 SetPosition (obj2, &r);
1934 AdjustPrnt (obj2, &r, TRUE);
1935 }
1936
1937 c = HiddenGroup (w, 2, 0, NULL);
1938 SetGroupSpacing (c, 10, 3);
1939 b = DefaultButton (c, "Accept", AcceptArgumentFormProc);
1940 SetObjectExtra (b, ufp, NULL);
1941 PushButton (c, "Cancel", StdCancelButtonProc);
1942
1943 AlignObjects (ALIGN_CENTER, (HANDLE) m, (HANDLE) c, NULL);
1944 RealizeWindow (w);
1945 Show (w);
1946 Select (w);
1947 if (first != NULL) {
1948 Select (first);
1949 }
1950 }
1951
1952 static void DoURLProc (IteM i)
1953
1954 {
1955 CharPtr args = NULL;
1956 BaseFormPtr bfp;
1957 size_t len;
1958 NewObjectPtr nop;
1959 Int2 which;
1960
1961 nop = (NewObjectPtr) GetObjectExtra (i);
1962 if (nop == NULL) return;
1963 #ifdef WIN_MAC
1964 bfp = (BaseFormPtr) currentFormDataPtr;
1965 #else
1966 bfp = nop->bfp;
1967 #endif
1968 if (bfp == NULL) return;
1969 which = BioseqViewOrDocSumChoice (nop);
1970 if (nop->paramlist == NULL) {
1971 len = StringLen (nop->prefix) + StringLen (nop->suffix);
1972 if (len > 0) {
1973 args = MemNew (sizeof (Char) * (len + 2));
1974 StringCpy (args, nop->prefix);
1975 if (! StringHasNoText (nop->suffix)) {
1976 StringCat (args, "&");
1977 StringCat (args, nop->suffix);
1978 }
1979 }
1980 DoAnalysisProc (nop, bfp, which, args, NULL);
1981 } else {
1982 BuildArgumentForm (nop, bfp, which);
1983 }
1984 }
1985
1986 extern void EnableAnalysisItems (BaseFormPtr bfp, Boolean isDocSum)
1987
1988 {
1989 Boolean hasFastaNuc;
1990 Boolean hasFastaProt;
1991 NewObjectPtr nop;
1992
1993 if (bfp == NULL) return;
1994 #ifdef WIN_MAC
1995 nop = (NewObjectPtr) macUserDataPtr;
1996 #else
1997 nop = (NewObjectPtr) bfp->userDataPtr;
1998 #endif
1999 if (isDocSum) {
2000 } else {
2001 }
2002 while (nop != NULL) {
2003 if (nop->kind == 1) {
2004 /* annotate menu item, ignore it */
2005 } else if (isDocSum) {
2006 if (nop->dsmOK) {
2007 /*
2008 hasFastaNuc = DocSumCanSaveFasta (bfp->form, TRUE, FALSE);
2009 hasFastaProt = DocSumCanSaveFasta (bfp->form, FALSE, TRUE);
2010 if (nop->fastaNucOK && hasFastaNuc) {
2011 SafeEnable (nop->item);
2012 } else if (nop->fastaProtOK && hasFastaProt) {
2013 SafeEnable (nop->item);
2014 } else {
2015 SafeDisable (nop->item);
2016 }
2017 */
2018 SafeDisable (nop->item);
2019 } else {
2020 SafeDisable (nop->item);
2021 }
2022 } else {
2023 if (nop->bspOK) {
2024 hasFastaNuc = BioseqViewCanSaveFasta (bfp->form, TRUE, FALSE, nop->onlyBspTarget);
2025 hasFastaProt = BioseqViewCanSaveFasta (bfp->form, FALSE, TRUE, nop->onlyBspTarget);
2026 if (nop->fastaNucOK && hasFastaNuc) {
2027 SafeEnable (nop->item);
2028 } else if (nop->fastaProtOK && hasFastaProt) {
2029 SafeEnable (nop->item);
2030 } else {
2031 SafeDisable (nop->item);
2032 }
2033 } else {
2034 SafeDisable (nop->item);
2035 }
2036 }
2037 nop = nop->next;
2038 }
2039 }
2040
2041 static VoidPtr LinkNewObjectLists (NewObjectPtr list1, NewObjectPtr list2)
2042
2043 {
2044 NewObjectPtr nop;
2045
2046 if (list1 == NULL) return list2;
2047 nop = list1;
2048 while (nop->next != NULL) {
2049 nop = nop->next;
2050 }
2051 nop->next = list2;
2052 return list1;
2053 }
2054
2055 static void CleanupAnalysisExtraProc (GraphiC g, VoidPtr data)
2056
2057 {
2058 NewObjectPtr nop;
2059 ValNodePtr ppt;
2060 UrlParamPtr upp;
2061
2062 nop = (NewObjectPtr) data;
2063 if (nop != NULL) {
2064 MemFree (nop->host_machine);
2065 MemFree (nop->host_path);
2066 for (ppt = nop->paramlist; ppt != NULL; ppt = ppt->next) {
2067 upp = (UrlParamPtr) ppt->data.ptrvalue;
2068 if (upp == NULL) continue;
2069 MemFree (upp->param);
2070 MemFree (upp->prompt);
2071 MemFree (upp->dfault);
2072 MemFree (upp->choices);
2073 MemFree (upp->group);
2074 MemFree (upp->help);
2075 }
2076 ValNodeFreeData (nop->paramlist);
2077 MemFree (nop->prefix);
2078 MemFree (nop->suffix);
2079 }
2080 MemFree (data);
2081 }
2082
2083 typedef struct sbstruc {
2084 CharPtr name;
2085 MenU menu;
2086 } Sbstruc, PNTR SbstrucPtr;
2087
2088 static ValNodePtr analysissubmenulist = NULL;
2089
2090 static void AddAnalysisItem (MenU m, BaseFormPtr bfp,
2091 Boolean bspviewOK, Boolean docsumOK,
2092 Boolean nucOK, Boolean protOK, Boolean onlyBspTarget,
2093 CharPtr host_machine, Uint2 host_port,
2094 CharPtr host_path, CharPtr program,
2095 Uint2 timeoutsec, Int2 format, Boolean demomode,
2096 QueryResultProc resultproc, ValNodePtr paramlist,
2097 CharPtr prefix, CharPtr suffix,
2098 CharPtr title, CharPtr submenu,
2099 ItmActnProc actn, NewObjectPtr PNTR head)
2100
2101 {
2102 IteM i;
2103 NewObjectPtr last;
2104 size_t len;
2105 NewObjectPtr nop;
2106 SbstrucPtr sbp;
2107 CharPtr tmp;
2108 ValNodePtr vnp;
2109 MenU x;
2110
2111 if (m == NULL || actn == NULL) return;
2112 x = NULL;
2113 if (! StringHasNoText (submenu)) {
2114 vnp = analysissubmenulist;
2115 while (vnp != NULL && x == NULL) {
2116 sbp = (SbstrucPtr) vnp->data.ptrvalue;
2117 if (sbp != NULL && StringICmp (sbp->name, submenu) == 0) {
2118 x = sbp->menu;
2119 }
2120 vnp = vnp->next;
2121 }
2122 if (x == NULL) {
2123 sbp = (SbstrucPtr) MemNew (sizeof (Sbstruc));
2124 if (sbp != NULL) {
2125 sbp->name = StringSave (submenu);
2126 sbp->menu = SubMenu (m, sbp->name);
2127 x = sbp->menu;
2128 ValNodeAddPointer (&analysissubmenulist, 0, (VoidPtr) sbp);
2129 }
2130 }
2131 }
2132 if (x == NULL) {
2133 x = m;
2134 }
2135 i = CommandItem (x, title, actn);
2136 nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
2137 if (nop != NULL) {
2138 nop->kind = 2; /* analysis menu item */
2139 nop->bfp = bfp;
2140 nop->item = i;
2141 nop->bspOK = bspviewOK;
2142 nop->dsmOK = docsumOK;
2143 nop->fastaNucOK = nucOK;
2144 nop->fastaProtOK = protOK;
2145 nop->onlyBspTarget = onlyBspTarget;
2146 nop->host_machine = /* StrSaveNoNullEncodeSpaces */ StringSave (host_machine);
2147 nop->host_port = host_port;
2148 len = StringLen (host_path);
2149 tmp = MemNew (len + StringLen (program) + 5);
2150 if (tmp != NULL) {
2151 StringCpy (tmp, host_path);
2152 if (len > 1 && tmp [len - 1] != '/') {
2153 StringCat (tmp, "/");
2154 }
2155 StringCat (tmp, program);
2156 }
2157 nop->host_path = /* StrSaveNoNullEncodeSpaces */ StringSave (tmp);
2158 MemFree (tmp);
2159 nop->query = NULL;
2160 /*
2161 nop->host_path = StrSaveNoNullEncodeSpaces (host_path);
2162 nop->query = StrSaveNoNullEncodeSpaces (program);
2163 */
2164 nop->timeoutsec = timeoutsec;
2165 nop->format = format;
2166 nop->demomode = demomode;
2167 nop->resultproc = resultproc;
2168 nop->paramlist = paramlist;
2169 nop->prefix = StringSaveNoNull (prefix);
2170 nop->suffix = StringSaveNoNull (suffix);
2171 }
2172 SetObjectExtra (i, (Pointer) nop, CleanupAnalysisExtraProc);
2173 if (head == NULL) return;
2174 last = *head;
2175 if (last != NULL) {
2176 while (last->next != NULL) {
2177 last = last->next;
2178 }
2179 last->next = nop;
2180 } else {
2181 *head = nop;
2182 }
2183 }
2184
2185 /* Sample seqncgis.cnf/seqncgis.ini/.seqncgisrc/sequincgi.cfg config file.
2186 PATH can contain query (separated by ? symbol), or separate QUERY item can
2187 be used, or multiple QUERY and TITLE items can also be used.
2188
2189 [SERVICES]
2190 PATH=mydisk:Common Files:services:
2191
2192 [ORDER]
2193 ORDER_1=tRNAscan
2194 ORDER_2=Seg
2195
2196 [tRNAscan]
2197 PROGRAM=testcgi.cgi?request=trnascan
2198 HOST=www.myserver.myschool.edu
2199 PORT=80
2200 PATH=/MyServices/cgi-bin/testcgi.cgi
2201 SUBMENU=Search
2202 FORMATIN=FASTA
2203 FLAGS=SEQ,NUC,TRG
2204 TIMEOUT=30
2205
2206 [Seg]
2207 PROGRAM=segify
2208 HOST=www.myserver.myschool.edu
2209 PORT=80
2210 PATH=/MyServices/cgi-bin/testcgi.cgi
2211 FORMATIN=fasta
2212 FLAGS=SEQ,DOC,PRT,TRG
2213 SUBMENU=Secondary structure prediction
2214 PROMPT_1=Window Size
2215 PARAM_1=window
2216 DESCRIPTION_1=window size for determining low-complexity segments
2217 TYPE_1=text
2218 DEFAULT_1=12
2219 REQUIRED_1=FALSE
2220 IMPORTANCE_1=
2221 GROUP_1=Algorithm
2222 HELP_1=window size for determining low-complexity segments
2223 PROMPT_2=Trigger Complexity
2224 PARAM_2=trigger
2225 DESCRIPTION_2=trigger complexity for determining low-complexity segments
2226 TYPE_2=text
2227 DEFAULT_2=2.2
2228 REQUIRED_2=FALSE
2229 IMPORTANCE_2=
2230 GROUP_2=Algorithm
2231 HELP_2=trigger complexity for determining low-complexity segments
2232 ...
2233
2234 [ENZYMES]
2235 ENZ_1=BamHI
2236 ENZ_2=EcoRI
2237 ENZ_3=HindIII
2238
2239 */
2240
2241 static Int2 GetServiceParam (ValNodePtr head, CharPtr type, CharPtr buf, Int2 buflen)
2242
2243 {
2244 size_t len;
2245 Boolean seenBracket = FALSE;
2246 CharPtr str;
2247 ValNodePtr vnp;
2248
2249 if (buf == NULL || buflen <= 0) return 0;
2250 *buf = '\0';
2251 len = StringLen (type);
2252 for (vnp = head; vnp != NULL; vnp = vnp->next) {
2253 str = (CharPtr) vnp->data.ptrvalue;
2254 if (str != NULL) {
2255 if (str [0] == '[') {
2256 if (seenBracket) return 0;
2257 seenBracket = TRUE;
2258 } else if (StringNICmp (str, type, len) == 0) {
2259 str += len;
2260 StringNCpy_0 (buf, str, buflen);
2261 return (Int2) StringLen (buf);
2262 }
2263 }
2264 }
2265 return 0;
2266 }
2267
2268 static ValNodePtr GetConfigParamAndPromptLists (CharPtr sect)
2269
2270 {
2271 Int2 i;
2272 ValNodePtr paramlist = NULL;
2273 Uint1 paramtype;
2274 Char title [512];
2275 Char tmp [32];
2276 UrlParamPtr upp;
2277
2278 if (sect == NULL) return NULL;
2279 i = 1;
2280 sprintf (tmp, "PARAM_%d", (int) i);
2281 while (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2282 upp = (UrlParamPtr) MemNew (sizeof (UrlParamData));
2283 if (upp == NULL) continue;
2284 upp->param = StringSave (title);
2285 sprintf (tmp, "TYPE_%d", (int) i);
2286 paramtype = 1;
2287 if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2288 if (StringICmp (title, "text") == 0) {
2289 paramtype = 1;
2290 } else if (StringICmp (title, "checkbox") == 0) {
2291 paramtype = 2;
2292 } else if (StringICmp (title, "popup") == 0) {
2293 paramtype = 3;
2294 } else if (StringICmp (title, "radio") == 0) {
2295 paramtype = 4;
2296 } else if (StringICmp (title, "list") == 0) {
2297 paramtype = 5;
2298 }
2299 }
2300 upp->type = paramtype;
2301 sprintf (tmp, "PROMPT_%d", (int) i);
2302 if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2303 upp->prompt = StringSave (title);
2304 } else {
2305 upp->prompt = StringSave (upp->param);
2306 }
2307 sprintf (tmp, "DEFAULT_%d", (int) i);
2308 if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2309 upp->dfault = StringSave (title);
2310 } else {
2311 upp->dfault = StringSave (" ");
2312 }
2313 sprintf (tmp, "CHOICES_%d", (int) i);
2314 if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2315 upp->choices = StringSave (title);
2316 } else {
2317 upp->choices = StringSave (" ");
2318 }
2319 sprintf (tmp, "GROUP_%d", (int) i);
2320 if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2321 upp->group = StringSave (title);
2322 } else {
2323 upp->group = StringSave (" ");
2324 }
2325 sprintf (tmp, "HELP_%d", (int) i);
2326 if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
2327 upp->help = StringSave (title);
2328 } else {
2329 upp->help = StringSave (" ");
2330 }
2331 ValNodeAddPointer (¶mlist, i, (Pointer) upp);
2332 i++;
2333 sprintf (tmp, "PARAM_%d", (int) i);
2334 }
2335 return paramlist;
2336 }
2337
2338 static ValNodePtr GetServiceParamAndPromptLists (ValNodePtr list)
2339
2340 {
2341 Int2 i;
2342 ValNodePtr paramlist = NULL;
2343 Uint1 paramtype;
2344 Char title [512];
2345 Char tmp [32];
2346 UrlParamPtr upp;
2347
2348 if (list == NULL) return NULL;
2349 i = 1;
2350 sprintf (tmp, "PARAM_%d=", (int) i);
2351 while (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2352 upp = (UrlParamPtr) MemNew (sizeof (UrlParamData));
2353 if (upp == NULL) continue;
2354 upp->param = StringSave (title);
2355 sprintf (tmp, "TYPE_%d", (int) i);
2356 paramtype = 1;
2357 if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2358 if (StringICmp (title, "text") == 0) {
2359 paramtype = 1;
2360 } else if (StringICmp (title, "checkbox") == 0) {
2361 paramtype = 2;
2362 } else if (StringICmp (title, "popup") == 0) {
2363 paramtype = 3;
2364 } else if (StringICmp (title, "radio") == 0) {
2365 paramtype = 4;
2366 } else if (StringICmp (title, "list") == 0) {
2367 paramtype = 5;
2368 }
2369 }
2370 upp->type = paramtype;
2371 sprintf (tmp, "PROMPT_%d=", (int) i);
2372 if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2373 upp->prompt = StringSave (title);
2374 } else {
2375 upp->prompt = StringSave (upp->param);
2376 }
2377 sprintf (tmp, "DEFAULT_%d=", (int) i);
2378 if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2379 upp->dfault = StringSave (title);
2380 } else {
2381 upp->dfault = StringSave (" ");
2382 }
2383 sprintf (tmp, "CHOICES_%d=", (int) i);
2384 if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2385 upp->choices = StringSave (title);
2386 } else {
2387 upp->choices = StringSave (" ");
2388 }
2389 sprintf (tmp, "GROUP_%d=", (int) i);
2390 if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2391 upp->group = StringSave (title);
2392 } else {
2393 upp->group = StringSave (" ");
2394 }
2395 sprintf (tmp, "HELP_%d=", (int) i);
2396 if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
2397 upp->help = StringSave (title);
2398 } else {
2399 upp->help = StringSave (" ");
2400 }
2401 ValNodeAddPointer (¶mlist, i, (Pointer) upp);
2402 i++;
2403 sprintf (tmp, "PARAM_%d=", (int) i);
2404 }
2405 return paramlist;
2406 }
2407
2408 static void ReadAnalysisConfigFile (CharPtr sect, MenU m, BaseFormPtr bfp,
2409 Boolean bspviewOK, Boolean docsumOK,
2410 NewObjectPtr PNTR head)
2411
2412 {
2413 Boolean demomode = FALSE;
2414 Int2 format = 1;
2415 Char host [128];
2416 Boolean nucOK = FALSE;
2417 Boolean onlyBspTarget = FALSE;
2418 ValNodePtr paramlist = NULL;
2419 Char program [128];
2420 Char path [256];
2421 Uint2 port = 80;
2422 Char prefix [128];
2423 Boolean protOK = FALSE;
2424 Char submenu [128];
2425 Char suffix [128];
2426 Uint2 timeoutsec = 30;
2427 Char title [128];
2428 Char tmp [32];
2429 unsigned int val;
2430
2431 if (! GetAppParam ("SEQNCGIS", sect, "TITLE", NULL, title, sizeof (title) - 1)) {
2432 StringNCpy_0 (title, sect, sizeof (title));
2433 }
2434 if (GetAppParam ("SEQNCGIS", sect, "HOST", NULL, host, sizeof (host) - 1)) {
2435 if (GetAppParam ("SEQNCGIS", sect, "FLAGS", NULL, tmp, sizeof (tmp) - 1)) {
2436 if (StringStr (tmp, "SEQ") == NULL) {
2437 bspviewOK = FALSE;
2438 }
2439 if (StringStr (tmp, "DOC") == NULL) {
2440 docsumOK = FALSE;
2441 }
2442 if (StringStr (tmp, "NUC") != NULL) {
2443 nucOK = TRUE;
2444 }
2445 if (StringStr (tmp, "PRT") != NULL) {
2446 protOK = TRUE;
2447 }
2448 if (StringStr (tmp, "TRG") != NULL) {
2449 onlyBspTarget = TRUE;
2450 }
2451 }
2452
2453 if ((! bspviewOK) && (! docsumOK)) return;
2454
2455 if (GetAppParam ("SEQNCGIS", sect, "PORT", NULL, tmp, sizeof (tmp) - 1) &&
2456 sscanf (tmp, "%u", &val) == 1) {
2457 port = (Uint2) val;
2458 } else {
2459 port = 80;
2460 }
2461 if (GetAppParam ("SEQNCGIS", sect, "FORMATIN", NULL, tmp, sizeof (tmp) - 1)) {
2462 if (StringICmp (tmp, "FASTA") == 0) {
2463 format = 1;
2464 } else if (StringICmp (tmp, "ASN.1") == 0) {
2465 format = 2;
2466 }
2467 }
2468 if (GetAppParam ("SEQNCGIS", sect, "TIMEOUT", NULL, tmp, sizeof (tmp) - 1) &&
2469 sscanf (tmp, "%u", &val) == 1) {
2470 timeoutsec = (Uint2) val;
2471 } else {
2472 timeoutsec = 30;
2473 }
2474 submenu [0] = '\0';
2475 GetAppParam ("SEQNCGIS", sect, "SUBMENU", NULL, submenu, sizeof (submenu) - 1);
2476 if (GetAppParam ("SEQNCGIS", sect, "DEMO", NULL, tmp, sizeof (tmp) - 1)) {
2477 if (StringICmp (tmp, "TRUE") == 0) {
2478 demomode = TRUE;
2479 }
2480 }
2481
2482 if (GetAppParam ("SEQNCGIS", sect, "PATH", NULL, path, sizeof (path) - 1)) {
2483 if (GetAppParam ("SEQNCGIS", sect, "PROGRAM", NULL, program, sizeof (program) - 1)) {
2484 paramlist = GetConfigParamAndPromptLists (sect);
2485 prefix [0] = '\0';
2486 GetAppParam ("SEQNCGIS", sect, "PREFIX", NULL, prefix, sizeof (prefix) - 1);
2487 suffix [0] = '\0';
2488 GetAppParam ("SEQNCGIS", sect, "SUFFIX", NULL, suffix, sizeof (suffix) - 1);
2489 AddAnalysisItem (m, bfp, bspviewOK, docsumOK,
2490 nucOK, protOK, onlyBspTarget,
2491 host, port, path, program, timeoutsec, format, demomode,
2492 SequinHandleURLResults, paramlist, prefix, suffix,
2493 title, submenu, DoURLProc, head);
2494 }
2495 }
2496 }
2497 }
2498
2499 static void ReadServiceConfigFile (CharPtr pathbase, ValNodePtr config,
2500 MenU m, BaseFormPtr bfp,
2501 Boolean bspviewOK, Boolean docsumOK,
2502 NewObjectPtr PNTR head)
2503
2504 {
2505 Char ch;
2506 Boolean demomode = FALSE;
2507 Int2 format = 1;
2508 FILE *fp;
2509 Boolean goOn = TRUE;
2510 Char host [128];
2511 Boolean keepGoing;
2512 ValNodePtr list = NULL;
2513 Boolean nucOK = FALSE;
2514 Boolean onlyBspTarget = FALSE;
2515 ValNodePtr paramlist = NULL;
2516 Char program [128];
2517 Char path [PATH_MAX];
2518 Uint2 port = 80;
2519 Char prefix [128];
2520 Boolean protOK = FALSE;
2521 CharPtr ptr;
2522 Boolean seenBracket;
2523 Char str [256];
2524 Char submenu [128];
2525 Char suffix [128];
2526 Uint2 timeoutsec = 30;
2527 Char title [128];
2528 Char tmp [32];
2529 unsigned int val;
2530 ValNodePtr vnp;
2531
2532 if (path == NULL || config == NULL || config->data.ptrvalue == NULL) return;
2533 StringNCpy_0 (path, pathbase, sizeof (path));
2534 FileBuildPath (path, NULL, (CharPtr) config->data.ptrvalue);
2535 fp = FileOpen (path, "r");
2536 if (fp == NULL) return;
2537 while (FileGets (str, sizeof (str), fp) != NULL) {
2538 ptr = str;
2539 ch = *ptr;
2540 while (ch != '\0' && ch != '\n' && ch != '\r') {
2541 ptr++;
2542 ch = *ptr;
2543 }
2544 *ptr = '\0';
2545 ValNodeCopyStr (&list, 1, str);
2546 }
2547 FileClose (fp);
2548 while (goOn) {
2549 goOn = FALSE;
2550 title [0] = '\0';
2551 if (GetServiceParam (list, "TITLE=", tmp, sizeof (tmp) - 1)) {
2552 StringNCpy_0 (title, tmp, sizeof (title));
2553 }
2554 if (StringHasNoText (title)) {
2555 if (GetServiceParam (list, "[", title, sizeof (title) - 1)) {
2556 ptr = StringChr (title, ']');
2557 if (ptr != NULL) {
2558 *ptr = '\0';
2559 }
2560 }
2561 }
2562 if (title [0] != '\0' && GetServiceParam (list, "HOST=", host, sizeof (host) - 1)) {
2563 if (GetServiceParam (list, "FLAGS=", tmp, sizeof (tmp) - 1)) {
2564 if (StringStr (tmp, "SEQ") == NULL) {
2565 bspviewOK= FALSE;
2566 }
2567 if (StringStr (tmp, "DOC") == NULL) {
2568 docsumOK= FALSE;
2569 }
2570 if (StringStr (tmp, "NUC") != NULL) {
2571 nucOK= TRUE;
2572 }
2573 if (StringStr (tmp, "PRT") != NULL) {
2574 protOK= TRUE;
2575 }
2576 if (StringStr (tmp, "TRG") != NULL) {
2577 onlyBspTarget= TRUE;
2578 }
2579 }
2580
2581 if (bspviewOK || docsumOK) {
2582
2583 if (GetServiceParam (list, "PORT=", tmp, sizeof (tmp) - 1) &&
2584 sscanf (tmp, "%u", &val) == 1) {
2585 port = (Uint2) val;
2586 } else {
2587 port = 80;
2588 }
2589 if (GetServiceParam (list, "FORMATIN=", tmp, sizeof (tmp) - 1)) {
2590 if (StringICmp (tmp, "FASTA") == 0) {
2591 format = 1;
2592 } else if (StringICmp (tmp, "ASN.1") == 0) {
2593 format = 2;
2594 }
2595 }
2596 if (GetServiceParam (list, "TIMEOUT=", tmp, sizeof (tmp) - 1) &&
2597 sscanf (tmp, "%u", &val) == 1) {
2598 timeoutsec = (Uint2) val;
2599 } else {
2600 timeoutsec = 30;
2601 }
2602 submenu [0] = '\0';
2603 GetServiceParam (list, "SUBMENU=", submenu, sizeof (submenu) - 1);
2604 if (GetServiceParam (list, "DEMO=", tmp, sizeof (tmp) - 1)) {
2605 if (StringICmp (tmp, "TRUE") == 0) {
2606 demomode = TRUE;
2607 }
2608 }
2609
2610 if (GetServiceParam (list, "PATH=", path, sizeof (path) - 1)) {
2611 if (GetServiceParam (list, "PROGRAM=", program, sizeof (program) - 1)) {
2612 paramlist = GetServiceParamAndPromptLists (list);
2613 prefix [0] = '\0';
2614 GetServiceParam (list, "PREFIX=", prefix, sizeof (prefix) - 1);
2615 suffix [0] = '\0';
2616 GetServiceParam (list, "SUFFIX=", suffix, sizeof (suffix) - 1);
2617 AddAnalysisItem (m, bfp, bspviewOK, docsumOK,
2618 nucOK, protOK, onlyBspTarget,
2619 host, port, path, program, timeoutsec, format, demomode,
2620 SequinHandleURLResults, paramlist, prefix, suffix,
2621 title, submenu, DoURLProc, head);
2622 }
2623 }
2624
2625 }
2626 }
2627
2628 seenBracket = FALSE;
2629 keepGoing = TRUE;
2630 for (vnp = list; vnp != NULL && keepGoing; vnp = vnp->next) {
2631 ptr = (CharPtr) vnp->data.ptrvalue;
2632 if (ptr != NULL) {
2633 if (ptr [0] == '[') {
2634 if (seenBracket) {
2635 keepGoing = FALSE;
2636 } else {
2637 seenBracket = TRUE;
2638 }
2639 }
2640 if (keepGoing) {
2641 vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
2642 }
2643 }
2644 }
2645
2646 }
2647
2648 ValNodeFreeData (list);
2649 }
2650
2651 extern MenU CreateAnalysisMenu (WindoW w, BaseFormPtr bfp, Boolean bspviewOK, Boolean docsumOK)
2652
2653 {
2654 NewObjectPtr first;
2655 ValNodePtr head1 = NULL, head2 = NULL;
2656 Int2 i;
2657 size_t len;
2658 MenU m;
2659 Char path1 [PATH_MAX];
2660 Char path2 [PATH_MAX];
2661 CharPtr ptr;
2662 SbstrucPtr sbp;
2663 Char sect [256];
2664 Char temp [32];
2665 ValNodePtr vnp;
2666
2667 ProgramPath (path1, sizeof (path1));
2668 ptr = StringRChr (path1, DIRDELIMCHR);
2669 if (ptr != NULL) {
2670 ptr++;
2671 *ptr = '\0';
2672 }
2673 FileBuildPath (path1, "services", NULL);
2674 head1 = DirCatalog (path1);
2675
2676 if (GetAppParam ("SEQNCGIS", "SERVICES", "PATH", NULL, path2, sizeof (path2) - 1)) {
2677 len = StringLen (path2);
2678 if (path2 [len - 1] != DIRDELIMCHR) {
2679 StringCat (path2, DIRDELIMSTR);
2680 }
2681 if (StringCmp (path1, path2) != 0) {
2682 head2 = DirCatalog (path2);
2683 }
2684 }
2685
2686 if ((! extraServices) && (! indexerVersion) && (! genomeCenter) &&
2687 head1 == NULL && head2 == NULL) {
2688 if (! GetAppParam ("SEQNCGIS", "ORDER", NULL, NULL, sect, sizeof (sect) - 1)) {
2689 return NULL;
2690 }
2691 }
2692 m = PulldownMenu (w, "Analysis");
2693 if (m == NULL) return NULL;
2694 analysissubmenulist = NULL;
2695 first = NULL;
2696 if (bspviewOK) {
2697 AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
2698 NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
2699 "Restriction Search", "Search",
2700 SimpleRsiteProc, &first);
2701 if (indexerVersion) {
2702 AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
2703 NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
2704 "QBlast Test", "Search",
2705 SimpleQBlastProc, &first);
2706 }
2707 }
2708 if (bspviewOK || docsumOK) {
2709 if (useEntrez) {
2710 i = 1;
2711 sprintf (temp, "ORDER_%d", (int) i);
2712 while (GetAppParam ("SEQNCGIS", "ORDER", temp, NULL, sect, sizeof (sect) - 1)) {
2713 ReadAnalysisConfigFile (sect, m, bfp, bspviewOK, docsumOK, &first);
2714 i++;
2715 sprintf (temp, "ORDER_%d", (int) i);
2716 }
2717 for (vnp = head1; vnp != NULL; vnp = vnp->next) {
2718 if (vnp->choice == 0) {
2719 ReadServiceConfigFile (path1, vnp, m, bfp, bspviewOK, docsumOK, &first);
2720 }
2721 }
2722 for (vnp = head2; vnp != NULL; vnp = vnp->next) {
2723 if (vnp->choice == 0) {
2724 ReadServiceConfigFile (path2, vnp, m, bfp, bspviewOK, docsumOK, &first);
2725 }
2726 }
2727 }
2728 }
2729 if (bspviewOK) {
2730 }
2731 if (docsumOK) {
2732 }
2733 #ifdef WIN_MAC
2734 macUserDataPtr = LinkNewObjectLists (macUserDataPtr, first);
2735 #else
2736 bfp->userDataPtr = LinkNewObjectLists (bfp->userDataPtr, first);
2737 #endif
2738 for (vnp = analysissubmenulist; vnp != NULL; vnp = vnp->next) {
2739 sbp = (SbstrucPtr) vnp->data.ptrvalue;
2740 if (sbp != NULL) {
2741 sbp->name = MemFree (sbp->name);
2742 }
2743 }
2744 analysissubmenulist = ValNodeFreeData (analysissubmenulist);
2745 ValNodeFreeData (head1);
2746 ValNodeFreeData (head2);
2747 return m;
2748 }
2749
2750 /* NEW UPDATE SEQUENCE SECTION */
2751
2752
2753 #define SQN_LEFT 1
2754 #define SQN_RIGHT 2
2755 #define SQN_MIDDLE 3
2756
2757 static Uint4 sqn_binary_search_on_uint4_list(Uint4Ptr list, Uint4 pos, Uint4 listlen)
2758 {
2759 Uint4 L;
2760 Uint4 mid;
2761 Uint4 R;
2762
2763 if (list == NULL || listlen == 0)
2764 return 0;
2765 L = 0;
2766 R = listlen - 1;
2767 while (L < R)
2768 {
2769 mid = (L+R)/2;
2770 if (list[mid + 1] <= pos)
2771 {
2772 L = mid + 1;
2773 } else
2774 {
2775 R = mid;
2776 }
2777 }
2778 return R;
2779 }
2780
2781 static Int4 MapRowCoordsSpecial(SeqAlignPtr sap, Uint4 pos, Int4 row, Int4 which_end)
2782 {
2783 DenseSegPtr dsp;
2784 Int4 idx;
2785 Int4 offset;
2786 SAIndexPtr saip;
2787 Int4 start;
2788
2789 if (sap == NULL || row < 0)
2790 return -1;
2791 if (sap->saip == NULL)
2792 return -1;
2793 saip = (SAIndexPtr)sap->saip;
2794 dsp = (DenseSegPtr)sap->segs;
2795 start = sqn_binary_search_on_uint4_list(saip->aligncoords, pos, dsp->numseg);
2796 offset = pos - saip->aligncoords[start];
2797 idx = (dsp->dim*start) + row - 1;
2798 if (dsp->starts[idx] == -1)
2799 {
2800 if (which_end == SQN_RIGHT)
2801 {
2802 /* round down */
2803 while (start >= 0) {
2804 idx = (dsp->dim*start) + row - 1;
2805 if (dsp->starts[idx] != -1)
2806 return (dsp->starts[idx] + dsp->lens[start] - 1);
2807 start--;
2808 }
2809 return -2;
2810 } else if (which_end == SQN_LEFT)
2811 {
2812 /* round up */
2813 while (start < dsp->numseg) {
2814 idx = (dsp->dim*start) + row - 1;
2815 if (dsp->starts[idx] != -1)
2816 return (dsp->starts[idx]);
2817 start++;
2818 }
2819 return -2;
2820 }
2821 } else
2822 {
2823 idx = (dsp->dim*start) + row - 1;
2824 if (dsp->strands[idx] != Seq_strand_minus)
2825 return (dsp->starts[idx] + offset);
2826 else
2827 return (dsp->starts[idx] + dsp->lens[start] - 1 - offset);
2828 }
2829 return -1;
2830 }
2831
2832 static Int4 MapBioseqToBioseqSpecial(SeqAlignPtr sap, Int4 begin, Int4 fin, Int4 pos, Int4 which_end)
2833 {
2834 Int4 bspos;
2835 Int4 sapos;
2836 Int4 start1;
2837 Int4 start2;
2838 Int4 stop1;
2839 Int4 stop2;
2840
2841 if (sap == NULL || sap->saip == NULL)
2842 return -2;
2843 AlnMgr2GetNthSeqRangeInSA(sap, begin, &start1, &stop1);
2844 AlnMgr2GetNthSeqRangeInSA(sap, fin, &start2, &stop2);
2845 /* check to see whether the position is outside the alignment */
2846 if (pos < start1)
2847 return (start2 - (start1 - pos));
2848 else if (pos > stop1)
2849 return (stop2 + (pos-stop1));
2850 sapos = AlnMgr2MapBioseqToSeqAlign(sap, pos, begin);
2851 bspos = MapRowCoordsSpecial(sap, sapos, fin, which_end);
2852 if (bspos >= 0)
2853 return bspos;
2854 else if (which_end == SQN_LEFT)
2855 return (start2-1);
2856 else if (which_end == SQN_RIGHT)
2857 return (stop2+1);
2858 else
2859 return 0;
2860 }
2861
2862 static void ListPhrapGraphsCallback (SeqGraphPtr sgp, Pointer userdata)
2863 {
2864 ValNodePtr PNTR vnpp;
2865
2866 if (sgp == NULL || userdata == NULL) return;
2867 if (StringICmp (sgp->title, "Phrap Quality") == 0)
2868 {
2869 vnpp = (ValNodePtr PNTR) userdata;
2870 ValNodeAddPointer (vnpp, 0, sgp);
2871 }
2872 }
2873
2874 /* THOUGHTS:
2875 * Can we/must we update quality scores before/after the old Bioseq has been replaced?
2876 * If we replace quality scores after the bioseq has been replaced, the oldbsp->length
2877 * is the length of the buffer we need to hold the quality scores,
2878 * otherwise use the newbsp->length.
2879 * Useful functions:
2880 aln_len = AlnMgr2GetAlnLength(salp, FALSE);
2881
2882 NLM_EXTERN Int4 AlnMgr2GetNumAlnBlocks(SeqAlignPtr sap)
2883 NLM_EXTERN Boolean AlnMgr2GetNthBlockRange(SeqAlignPtr sap, Int4 n, Int4Ptr start, Int4Ptr stop)
2884
2885
2886 * Assumptions: data replacement has already taken place, oldbsp is in row 1 of salp,
2887 * newbsp is in row 2 of salp.
2888
2889 */
2890 static Boolean
2891 ReplaceQualityScores
2892 (BioseqPtr oldbsp,
2893 BioseqPtr newbsp,
2894 FILE *log_fp,
2895 BoolPtr data_in_log)
2896 {
2897 ValNodePtr oldhead = NULL, newhead = NULL, vnp;
2898 SeqGraphPtr sgp, last_sgp = NULL, new_sgp;
2899 SeqAnnotPtr sap, last_sap;
2900 Char acc_str [256];
2901
2902 if (oldbsp == NULL || newbsp == NULL
2903 || !ISA_na (oldbsp->mol) || !ISA_na (newbsp->mol))
2904 {
2905 return FALSE;
2906 }
2907
2908 /* first, remove old scores */
2909 VisitGraphsOnBsp (oldbsp, &oldhead, ListPhrapGraphsCallback);
2910 for (vnp = oldhead; vnp != NULL; vnp = vnp->next)
2911 {
2912 sgp = vnp->data.ptrvalue;
2913 if (sgp != NULL)
2914 {
2915 sgp->idx.deleteme = TRUE;
2916 }
2917 }
2918 oldhead = ValNodeFree (oldhead);
2919 DeleteMarkedObjects (0, OBJ_BIOSEQ, (Pointer) oldbsp);
2920
2921 /* now copy new quality scores to old sequence */
2922 VisitGraphsOnBsp (newbsp, &newhead, ListPhrapGraphsCallback);
2923
2924 if (newhead == NULL)
2925 {
2926 if (log_fp != NULL && data_in_log != NULL)
2927 {
2928 SeqIdWrite (oldbsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
2929 fprintf (log_fp, "Quality scores cleared for %s\n", acc_str);
2930 *data_in_log = TRUE;
2931 }
2932 }
2933 else
2934 {
2935 /* now add in new phrap annotations */
2936 last_sap = NULL;
2937 last_sgp = NULL;
2938 for (sap = oldbsp->annot; sap != NULL && sap->type !=3; sap = sap->next)
2939 {
2940 last_sap = sap;
2941 }
2942
2943 if (sap == NULL)
2944 {
2945 sap = SeqAnnotNew ();
2946 sap->type = 3;
2947 sap->data = NULL;
2948 if (last_sap == NULL)
2949 {
2950 oldbsp->annot = sap;
2951 }
2952 else
2953 {
2954 last_sap->next = sap;
2955 }
2956 }
2957
2958
2959 for (sgp = (SeqGraphPtr) sap->data; sgp != NULL; sgp = sgp->next)
2960 {
2961 last_sgp = sgp;
2962 }
2963 for (vnp = newhead; vnp != NULL; vnp = vnp->next)
2964 {
2965 sgp = (SeqGraphPtr) vnp->data.ptrvalue;
2966 if (sgp != NULL)
2967 {
2968 new_sgp = (SeqGraphPtr) AsnIoMemCopy (sgp, (AsnReadFunc) SeqGraphAsnRead, (AsnWriteFunc) SeqGraphAsnWrite);
2969 if (new_sgp != NULL)
2970 {
2971 new_sgp->next = NULL;
2972 if (last_sgp == NULL)
2973 {
2974 sap->data = new_sgp;
2975 }
2976 else
2977 {
2978 last_sgp->next = new_sgp;
2979 }
2980 last_sgp = new_sgp;
2981 }
2982 }
2983 }
2984 SeqIdWrite (oldbsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
2985 fprintf (log_fp, "Replaced quality scores for %s\n", acc_str);
2986 *data_in_log = TRUE;
2987 }
2988
2989
2990 return TRUE;
2991 }
2992
2993
2994 extern void RemoveQualityScores
2995 (BioseqPtr bsp,
2996 FILE *log_fp,
2997 BoolPtr data_in_log)
2998
2999 {
3000 ValNodePtr score_list = NULL, vnp;
3001 Char acc_str [256];
3002 SeqGraphPtr sgp;
3003
3004 if (bsp == NULL) return;
3005
3006 VisitGraphsOnBsp (bsp, &score_list, ListPhrapGraphsCallback);
3007 if (score_list == NULL) return;
3008
3009 if (log_fp != NULL && data_in_log != NULL)
3010 {
3011 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
3012 fprintf (log_fp, "Quality scores cleared for %s\n", acc_str);
3013 *data_in_log = TRUE;
3014 }
3015
3016 for (vnp = score_list; vnp != NULL; vnp = vnp->next)
3017 {
3018 sgp = vnp->data.ptrvalue;
3019 if (sgp != NULL)
3020 {
3021 sgp->idx.deleteme = TRUE;
3022 }
3023 }
3024
3025 score_list = ValNodeFree (score_list);
3026 DeleteMarkedObjects (0, OBJ_BIOSEQ, (Pointer) bsp);
3027 }
3028
3029
3030 #define SEQGRAPH_FloatHi 1
3031 #define SEQGRAPH_Int4 2
3032 #define SEQGRAPH_BS 3
3033
3034 /* remove compression from SeqGraph */
3035 static Boolean ExpandSeqGraph (SeqGraphPtr sgp)
3036 {
3037 Int4 oldpos = 0, newpos = 0, i;
3038 Pointer new_values = NULL;
3039 Int4 new_numval;
3040 Int2 cur_byte;
3041
3042 if (sgp == NULL || sgp->compr == 0 || sgp->compr == 1) {
3043 return TRUE;
3044 } else if (sgp->compr < 0) {
3045 return FALSE;
3046 }
3047
3048 new_numval = sgp->numval * sgp->compr;
3049
3050 /* allocate space for new values */
3051 switch (sgp->flags[2]) {
3052 case SEQGRAPH_FloatHi:
3053 new_values = MemNew (sizeof (FloatHi) * new_numval);
3054 break;
3055 case SEQGRAPH_Int4:
3056 new_values = MemNew (sizeof (Int4) * new_numval);
3057 break;
3058 case SEQGRAPH_BS:
3059 new_values = (Pointer) BSNew (new_numval);
3060 BSSeek ((ByteStorePtr)new_values, 0, SEEK_SET);
3061 BSSeek ((ByteStorePtr) sgp->values, 0, SEEK_SET);
3062 break;
3063 }
3064
3065 /* copy and expand */
3066 while (oldpos < sgp->numval) {
3067 cur_byte = 0;
3068 if (sgp->flags[2] == SEQGRAPH_BS) {
3069 cur_byte = BSGetByte ((ByteStorePtr) sgp->values);
3070 }
3071 for (i = 0; i < sgp->compr; i++) {
3072 switch (sgp->flags[2]) {
3073 case SEQGRAPH_FloatHi:
3074 ((FloatHiPtr)new_values)[newpos++] = ((FloatHiPtr)sgp->values)[oldpos];
3075 break;
3076 case SEQGRAPH_Int4:
3077 ((Int4Ptr)new_values)[newpos++] = ((Int4Ptr)sgp->values)[oldpos];
3078 break;
3079 case SEQGRAPH_BS:
3080 BSPutByte ((ByteStorePtr) new_values, cur_byte);
3081 break;
3082 }
3083 }
3084 oldpos++;
3085 }
3086
3087 /* free old values and replace with new */
3088 if (sgp->flags[2] == SEQGRAPH_BS) {
3089 sgp->values = BSFree ((ByteStorePtr) sgp->values);
3090 } else {
3091 sgp->values = MemFree (sgp->values);
3092 }
3093 sgp->values = new_values;
3094 sgp->numval = new_numval;
3095 sgp->compr = 0;
3096
3097 return TRUE;
3098 }
3099
3100 static Boolean TruncateSeqGraphValues (SeqGraphPtr sgp, Int4 len, Boolean onleft)
3101 {
3102 Int4 oldpos, newpos = 0;
3103 Pointer new_values = NULL;
3104 Int4 new_numval;
3105 Int2 cur_byte;
3106 Int4 imin = 0, imax = 0;
3107 FloatHi fmin, fmax;
3108
3109 if (sgp == NULL) return TRUE;
3110 if (!ExpandSeqGraph (sgp)) return FALSE;
3111
3112 new_numval = sgp->numval - len;
3113
3114 /* allocate space for new values */
3115 switch (sgp->flags[2]) {
3116 case SEQGRAPH_FloatHi:
3117 new_values = MemNew (sizeof (FloatHi) * new_numval);
3118 fmin = ((FloatHiPtr)sgp->values)[0];
3119 fmax = fmin;
3120 break;
3121 case SEQGRAPH_Int4:
3122 new_values = MemNew (sizeof (Int4) * new_numval);
3123 imin = ((Int4Ptr)sgp->values)[0];
3124 imax = imin;
3125 break;
3126 case SEQGRAPH_BS:
3127 new_values = (Pointer) BSNew (new_numval);
3128 BSSeek ((ByteStorePtr)new_values, 0, SEEK_SET);
3129 if (onleft) {
3130 BSSeek ((ByteStorePtr) sgp->values, len, SEEK_SET);
3131 } else {
3132 BSSeek ((ByteStorePtr) sgp->values, 0, SEEK_SET);
3133 }
3134 imin = BSGetByte ((ByteStorePtr) sgp->values);
3135 imax = imin;
3136 /* put pointer back */
3137 if (onleft) {
3138 BSSeek ((ByteStorePtr) sgp->values, len, SEEK_SET);
3139 } else {
3140 BSSeek ((ByteStorePtr) sgp->values, 0, SEEK_SET);
3141 }
3142 break;
3143 }
3144
3145 /* copy */
3146 if (onleft) {
3147 oldpos = len;
3148 } else {
3149 oldpos = 0;
3150 }
3151 while (oldpos < sgp->numval && newpos < new_numval) {
3152 switch (sgp->flags[2]) {
3153 case SEQGRAPH_FloatHi:
3154 ((FloatHiPtr)new_values)[newpos] = ((FloatHiPtr)sgp->values)[oldpos];
3155 if (((FloatHiPtr)new_values)[newpos] > fmax) {
3156 fmax = ((FloatHiPtr)new_values)[newpos];
3157 }
3158 if (((FloatHiPtr)new_values)[newpos] < fmin) {
3159 fmin = ((FloatHiPtr)new_values)[newpos];
3160 }
3161 break;
3162 case SEQGRAPH_Int4:
3163 ((Int4Ptr)new_values)[newpos] = ((Int4Ptr)sgp->values)[oldpos];
3164 if (((Int4Ptr)new_values)[newpos] > imax) {
3165 imax = ((Int4Ptr)new_values)[newpos];
3166 }
3167 if (((Int4Ptr)new_values)[newpos] < imin) {
3168 imin = ((Int4Ptr)new_values)[newpos];
3169 }
3170 break;
3171 case SEQGRAPH_BS:
3172 cur_byte = BSGetByte ((ByteStorePtr) sgp->values);
3173 BSPutByte ((ByteStorePtr) new_values, cur_byte);
3174 if (cur_byte > imax) {
3175 imax = cur_byte;
3176 }
3177 if (cur_byte < imin) {
3178 imin = cur_byte;
3179 }
3180 break;
3181 }
3182 oldpos++;
3183 newpos++;
3184 }
3185
3186 /* free old values and replace with new */
3187 if (sgp->flags[2] == SEQGRAPH_BS) {
3188 sgp->values = BSFree ((ByteStorePtr) sgp->values);
3189 } else {
3190 sgp->values = MemFree (sgp->values);
3191 }
3192 sgp->values = new_values;
3193 sgp->numval = new_numval;
3194
3195 /* replace mins and maxes */
3196 if (sgp->flags[2] == SEQGRAPH_FloatHi) {
3197 sgp->max.realvalue = fmax;
3198 sgp->min.realvalue = fmin;
3199 } else {
3200 sgp->max.intvalue = imax;
3201 sgp->min.intvalue = imin;
3202 }
3203 return TRUE;
3204 }
3205
3206
3207
3208 /* assume Bioseq has already been trimmed - length of old Bioseq was trim5 + bsp->length + trim3 */
3209 static Boolean
3210 TrimQualityScoresForSequenceUpdate
3211 (BioseqPtr bsp,
3212 Int4 trim5,
3213 Int4 trim3,
3214 FILE *log_fp,
3215 BoolPtr data_in_log)
3216 {
3217 ValNodePtr score_list = NULL, vnp;
3218 SeqGraphPtr sgp;
3219 SeqIntPtr sip;
3220 Int4 left, right;
3221 Boolean rval = FALSE;
3222 Char acc_str [256];
3223
3224 if (bsp == NULL) return FALSE;
3225
3226 VisitGraphsOnBsp (bsp, &score_list, ListPhrapGraphsCallback);
3227 if (score_list == NULL) return FALSE;
3228
3229 for (vnp = score_list; vnp != NULL; vnp = vnp->next) {
3230 sgp = vnp->data.ptrvalue;
3231 if (sgp != NULL && sgp->loc != NULL && sgp->loc->choice == SEQLOC_INT) {
3232 sip = (SeqIntPtr) sgp->loc->data.ptrvalue;
3233 /* trim on right */
3234 if (sip->from > trim5 + bsp->length) {
3235 sgp->idx.deleteme = TRUE;
3236 rval = TRUE;
3237 } else if (sip->to > trim5 + bsp->length - 1) {
3238 right = sip->to - trim5 - bsp->length + 1;
3239 sip->to = trim5 + bsp->length - 1;
3240 TruncateSeqGraphValues (sgp, right, FALSE);
3241 rval = TRUE;
3242 }
3243
3244 sip->from -= trim5;
3245 sip->to -= trim5;
3246 if (sip->to < 0) {
3247 sgp->idx.deleteme = TRUE;
3248 rval = TRUE;
3249 } else if (sip->from < 0) {
3250 left = 0 - sip->from;
3251 sip->from = 0;
3252 TruncateSeqGraphValues (sgp, left, TRUE);
3253 rval = TRUE;
3254 }
3255 }
3256 }
3257
3258 if (rval && log_fp != NULL && data_in_log != NULL) {
3259 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
3260 fprintf (log_fp, "Quality scores trimmed for %s\n", acc_str);
3261 *data_in_log = TRUE;
3262 }
3263 return rval;
3264 }
3265
3266
3267 static Boolean AdjustAlignment (
3268 UpsDataPtr udp,
3269 Int2 choice
3270 )
3271
3272 {
3273 DenseSegPtr dsp;
3274 Int2 j;
3275 SeqAlignPtr sap;
3276
3277 if (udp == NULL) return FALSE;
3278
3279 sap = udp->salp;
3280 if (sap == NULL) return FALSE;
3281 AMFreeAllIndexes (sap);
3282
3283 if (sap->segtype == SAS_DENSEG) {
3284 dsp = (DenseSegPtr) sap->segs;
3285
3286 switch (choice) {
3287 case 2 :
3288 /* adjust alignment 5' */
3289 if (dsp != NULL && dsp->lens != NULL && dsp->numseg > 0) {
3290 dsp->lens [dsp->numseg - 1] += udp->old3;
3291 }
3292 break;
3293 case 3 :
3294 /* adjust alignment 3' */
3295 if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
3296 dsp->lens [0] += udp->old5;
3297 dsp->starts [0] = 0;
3298 dsp->starts [1] = 0;
3299 for (j = 1; j < dsp->numseg; j++) {
3300 if (dsp->starts [1 + j * 2] != -1) {
3301 dsp->starts [1 + j * 2] += udp->old5 - udp->new5;
3302 }
3303 }
3304 }
3305 break;
3306 case 4 :
3307 /* adjust alignment patch */
3308 if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
3309 dsp->lens [dsp->numseg - 1] += udp->old3;
3310 dsp->lens [0] += udp->old5;
3311 dsp->starts [0] = 0;
3312 dsp->starts [1] = 0;
3313 for (j = 1; j < dsp->numseg; j++) {
3314 if (dsp->starts [1 + j * 2] != -1) {
3315 dsp->starts [1 + j * 2] += udp->old5 - udp->new5;
3316 }
3317 }
3318 }
3319 break;
3320 default :
3321 break;
3322 }
3323 }
3324
3325 AlnMgr2IndexSingleChildSeqAlign (sap);
3326
3327 return TRUE;
3328 }
3329
3330 static void OffsetLoc (SeqLocPtr slp, Int4 offset, SeqIdPtr sip)
3331
3332 {
3333 PackSeqPntPtr psp;
3334 SeqIntPtr sinp;
3335 SeqPntPtr spp;
3336 Uint1 used;
3337
3338 if (slp == NULL) return;
3339 switch (slp->choice) {
3340 case SEQLOC_INT :
3341 sinp = (SeqIntPtr) slp->data.ptrvalue;
3342 if (sinp != NULL) {
3343 sinp->from += offset;
3344 sinp->to += offset;
3345 if (sip != NULL) {
3346 sinp->id = SeqIdFree (sinp->id);
3347 sinp->id = SeqIdDup (sip);
3348 }
3349 }
3350 break;
3351 case SEQLOC_PNT :
3352 spp = (SeqPntPtr) slp->data.ptrvalue;
3353 if (spp != NULL) {
3354 spp->point += offset;
3355 if (sip != NULL) {
3356 spp->id = SeqIdFree (spp->id);
3357 spp->id = SeqIdDup (sip);
3358 }
3359 }
3360 break;
3361 case SEQLOC_PACKED_PNT :
3362 psp = (PackSeqPntPtr) slp->data.ptrvalue;
3363 if (psp != NULL) {
3364 for (used = 0; used < psp->used; used++) {
3365 psp->pnts [used] += offset;
3366 }
3367 if (sip != NULL) {
3368 psp->id = SeqIdFree (psp->id);
3369 psp->id = SeqIdDup (sip);
3370 }
3371 }
3372 break;
3373 default :
3374 break;
3375 }
3376 }
3377
3378 extern void OffsetLocation (SeqLocPtr loc, Int4 offset, SeqIdPtr sip)
3379
3380 {
3381 SeqLocPtr slp;
3382
3383 slp = SeqLocFindNext (loc, NULL);
3384 while (slp != NULL) {
3385 OffsetLoc (slp, offset, sip);
3386 slp = SeqLocFindNext (loc, slp);
3387 }
3388 }
3389
3390 static void PromoteSeqId (SeqIdPtr sip, Pointer userdata)
3391
3392 {
3393 SeqIdPtr bestid, newid, oldid;
3394
3395 bestid = (SeqIdPtr) userdata;
3396
3397 newid = SeqIdDup (bestid);
3398 if (newid == NULL) return;
3399
3400 oldid = ValNodeNew (NULL);
3401 if (oldid == NULL) return;
3402
3403 MemCopy (oldid, sip, sizeof (ValNode));
3404 oldid->next = NULL;
3405
3406 sip->choice = newid->choice;
3407 sip->data.ptrvalue = newid->data.ptrvalue;
3408
3409 SeqIdFree (oldid);
3410 ValNodeFree (newid);
3411
3412 SeqIdStripLocus (sip);
3413 }
3414
3415 static void CorrectFeatureSeqIds (
3416 SeqFeatPtr sfp,
3417 Pointer userdata
3418 )
3419
3420 {
3421 VisitSeqIdsInSeqLoc (sfp->location, userdata, PromoteSeqId);
3422 }
3423
3424 static Boolean DoFeaturePropWithOffset (
3425 UpsDataPtr udp,
3426 Int4 offset,
3427 SeqAnnotPtr PNTR sapp,
3428 Boolean patch
3429 )
3430
3431 {
3432 BioseqPtr bsp, newbsp, oldbsp;
3433 CodeBreakPtr cbp;
3434 SeqMgrFeatContext context;
3435 CdRegionPtr crp;
3436 SeqFeatPtr dup, sfp, last = NULL;
3437 Uint2 entityID;
3438 Boolean keepProteinIDs;
3439 SeqEntryPtr newsep, prdsep, top;
3440 RnaRefPtr rrp;
3441 SeqAnnotPtr sap = NULL, saptmp;
3442 SeqDescrPtr sdp;
3443 SeqIdPtr sip;
3444 tRNAPtr trp;
3445
3446 if (udp == NULL) return FALSE;
3447
3448 SeqEntrySetScope (NULL);
3449
3450 sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &context);
3451 if (sfp == NULL) return FALSE;
3452
3453 if (udp->diffOrgs) {
3454 keepProteinIDs = FALSE;
3455 } else {
3456 keepProteinIDs = GetStatus (udp->keepProteinIDs);
3457 }
3458
3459 oldbsp = udp->oldbsp;
3460
3461 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
3462 top = GetBestTopParentForData (entityID, udp->oldbsp);
3463
3464 sdp = ExtractBioSourceAndPubs (top);
3465
3466 sip = SeqIdFindBest (oldbsp->id, 0);
3467
3468 while (sfp != NULL) {
3469
3470 if ((! patch) || (context.right >= udp->new5 && context.left <= udp->new5 + udp->newa)) {
3471
3472 dup = AsnIoMemCopy ((Pointer) sfp,
3473 (AsnReadFunc) SeqFeatAsnRead,
3474 (AsnWriteFunc) SeqFeatAsnWrite);
3475
3476 if (last == NULL) {
3477 sap = SeqAnnotNew ();
3478 if (oldbsp->annot == NULL) {
3479 oldbsp->annot = sap;
3480 } else {
3481 for (saptmp = oldbsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
3482 saptmp->next = sap;
3483 }
3484 sap->type = 1;
3485 sap->data = (Pointer) dup;
3486 } else {
3487 last->next = dup;
3488 }
3489 last = dup;
3490
3491 /*
3492 sep = SeqMgrGetSeqEntryForData (oldbsp);
3493 CreateNewFeature (sep, NULL, dup->data.choice, dup);
3494 */
3495
3496 OffsetLocation (dup->location, offset, sip);
3497 switch (dup->data.choice) {
3498 case SEQFEAT_CDREGION :
3499 crp = (CdRegionPtr) dup->data.value.ptrvalue;
3500 if (crp != NULL) {
3501 for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
3502 OffsetLocation (cbp->loc, offset, sip);
3503 }
3504 }
3505 break;
3506 case SEQFEAT_RNA :
3507 rrp = (RnaRefPtr) dup->data.value.ptrvalue;
3508 if (rrp != NULL && rrp->ext.choice == 2) {
3509 trp = (tRNAPtr) rrp->ext.value.ptrvalue;
3510 if (trp != NULL && trp->anticodon != NULL) {
3511 OffsetLocation (trp->anticodon, offset, sip);
3512 }
3513 }
3514 break;
3515 default :
3516 break;
3517 }
3518 if (dup->product != NULL) {
3519 SeqEntrySetScope (NULL);
3520 bsp = BioseqFindFromSeqLoc (dup->product);
3521 if (bsp != NULL) {
3522 prdsep = SeqMgrGetSeqEntryForData (bsp);
3523 if (prdsep != NULL) {
3524 newsep = AsnIoMemCopy ((Pointer) prdsep,
3525 (AsnReadFunc) SeqEntryAsnRead,
3526 (AsnWriteFunc) SeqEntryAsnWrite);
3527 if (newsep != NULL) {
3528 if (IS_Bioseq (newsep)) {
3529 newbsp = (BioseqPtr) newsep->data.ptrvalue;
3530 if (newbsp != NULL) {
3531 if (! keepProteinIDs) {
3532 newbsp->id = SeqIdSetFree (newbsp->id);
3533 newbsp->id = MakeNewProteinSeqId (NULL, sip);
3534 newbsp->hist = SeqHistFree (newbsp->hist);
3535 VisitFeaturesOnBsp (newbsp, (Pointer) newbsp->id, CorrectFeatureSeqIds);
3536 SetSeqFeatProduct (dup, newbsp);
3537 /*
3538 dup->product = SeqLocFree (dup->product);
3539 dup->product = CreateWholeInterval (newsep);
3540 */
3541 }
3542 SeqMgrReplaceInBioseqIndex (newbsp);
3543 }
3544 }
3545 AddSeqEntryToSeqEntry (top, newsep, TRUE);
3546 }
3547 }
3548 }
3549 }
3550 }
3551
3552 sfp = SeqMgrGetNextFeature (udp->newbsp, sfp, 0, 0, &context);
3553 }
3554
3555 ReplaceBioSourceAndPubs (top, sdp);
3556
3557 if (sapp != NULL) {
3558 *sapp = sap;
3559 }
3560
3561 return TRUE;
3562 }
3563
3564 /* This function adjusts the endpoints of a location, as long as the
3565 * endpoints are in the area represented by the alignment.
3566 * When we are adjusting locations for an alignment of a part, we will
3567 * be looking at all features indexed on the main segment, but we only
3568 * want to adjust feature endpoints located on the segment that we are
3569 * updating.
3570 */
3571 static Int4 AdjustEndpoint
3572 (SeqAlignPtr salp,
3573 SeqLocPtr slp,
3574 Int4 max_length,
3575 Int4 begin,
3576 Int4 fin,
3577 Int4 endpoint,
3578 Int4 end)
3579 {
3580 BioseqPtr slp_bsp, parent_bsp, old_bsp;
3581 SeqMgrSegmentContext segcontext;
3582 SeqIdPtr old_sip;
3583 Int4 pt;
3584
3585 if (slp == NULL || salp == NULL)
3586 {
3587 return endpoint;
3588 }
3589
3590 old_sip = AlnMgr2GetNthSeqIdPtr (salp, begin);
3591 old_bsp = BioseqFind (old_sip);
3592
3593 parent_bsp = SeqMgrGetParentOfPart (old_bsp, &segcontext);
3594
3595 slp_bsp = BioseqFind (SeqLocId (slp));
3596 if (slp_bsp == old_bsp
3597 || (slp_bsp == parent_bsp
3598 && endpoint >= segcontext.cumOffset + segcontext.from
3599 && endpoint < segcontext.cumOffset + segcontext.to))
3600 {
3601 if (slp_bsp == parent_bsp)
3602 {
3603 endpoint -= segcontext.cumOffset + segcontext.from;
3604 }
3605 pt = MapBioseqToBioseqSpecial (salp, begin, fin, endpoint, end);
3606 if (pt < 0) {
3607 pt = 0;
3608 } else if (pt >= max_length) {
3609 pt = max_length - 1;
3610 }
3611 if (slp_bsp == parent_bsp)
3612 {
3613 pt += segcontext.cumOffset + segcontext.from;
3614 }
3615 }
3616 else
3617 {
3618 pt = endpoint;
3619 }
3620
3621 return pt;
3622 }
3623
3624 static void ReplaceLocation (SeqAlignPtr salp, SeqLocPtr slp, Int4 length, Int4 begin, Int4 fin)
3625
3626 {
3627 PackSeqPntPtr psp;
3628 SeqIntPtr sinp;
3629 SeqPntPtr spp;
3630 Uint1 used;
3631
3632 if (slp == NULL) return;
3633 switch (slp->choice) {
3634 case SEQLOC_INT :
3635 sinp = (SeqIntPtr) slp->data.ptrvalue;
3636 if (sinp != NULL) {
3637 sinp->from = AdjustEndpoint (salp, slp, length, begin, fin,
3638 sinp->from, SQN_LEFT);
3639 sinp->to = AdjustEndpoint (salp, slp, length, begin, fin,
3640 sinp->to, SQN_RIGHT);
3641 }
3642 break;
3643 case SEQLOC_PNT :
3644 spp = (SeqPntPtr) slp->data.ptrvalue;
3645 if (spp != NULL) {
3646 spp->point = AdjustEndpoint (salp, slp, length, begin, fin,
3647 spp->point, SQN_LEFT);
3648 }
3649 break;
3650 case SEQLOC_PACKED_PNT :
3651 psp = (PackSeqPntPtr) slp->data.ptrvalue;
3652 if (psp != NULL) {
3653 for (used = 0; used < psp->used; used++) {
3654 psp->pnts [used] = AdjustEndpoint (salp, slp, length, begin, fin,
3655 psp->pnts [used], SQN_LEFT);
3656 }
3657 }
3658 break;
3659 default :
3660 break;
3661 }
3662 }
3663
3664 /* this function iterates through the pieces of a complex location
3665 * and calls ReplaceLocation for each one. ReplaceLocation will only
3666 * act on SEQLOC_INT, SEQLOC_PNT, and SEQLOC_PACKED_PNT and will ignore
3667 * other types.
3668 */
3669 extern void
3670 ReplaceComplexLocation
3671 (SeqLocPtr slp,
3672 SeqAlignPtr salp,
3673 Int4 new_len,
3674 Int4 begin,
3675 Int4 fin)
3676 {
3677 SeqLocPtr subslp;
3678
3679 if (slp == NULL || salp == NULL)
3680 {
3681 return;
3682 }
3683
3684 subslp = SeqLocFindNext (slp, NULL);
3685 while (subslp != NULL) {
3686 ReplaceLocation (salp, subslp, new_len, begin, fin);
3687 subslp = SeqLocFindNext (slp, subslp);
3688 }
3689 }
3690
3691 static Int4 LengthForNewSequence (UpsDataPtr udp)
3692 {
3693 Int4 new_len = 0;
3694
3695 if (udp == NULL)
3696 {
3697 return 0;
3698 }
3699 else if (GetValue (udp->sfb) == UPDATE_FEATURES_ONLY)
3700 {
3701 new_len = udp->oldbsp->length;
3702 }
3703 else if (udp->rmcval == UPDATE_PATCH)
3704 {
3705 new_len = udp->old5 + udp->newa + udp->old3;
3706 }
3707 else if (udp->rmcval == UPDATE_REPLACE)
3708 {
3709 new_len = udp->new5 + udp->newa + udp->new3;
3710 }
3711 else if (udp->rmcval == UPDATE_EXTEND5)
3712 {
3713 new_len = udp->new5 + udp->olda + udp->old3;
3714 }
3715 else if (udp->rmcval == UPDATE_EXTEND3)
3716 {
3717 new_len = udp->old5 + udp->olda + udp->new3;
3718 }
3719 return new_len;
3720 }
3721
3722 static SeqLocPtr
3723 GetPropagatedLocation
3724 (SeqLocPtr orig_loc,
3725 BioseqPtr newbsp,
3726 BioseqPtr oldbsp,
3727 Int4 new_len,
3728 SeqAlignPtr salp)
3729 {
3730 SeqLocPtr tmp_loc, new_loc;
3731 Boolean split;
3732
3733 tmp_loc = SeqLocCopy (orig_loc);
3734 ReplaceComplexLocation (tmp_loc, salp, new_len, 2, 1);
3735
3736 new_loc = SeqLocCopyRegion (oldbsp->id, tmp_loc, newbsp, 0, oldbsp->length - 1, Seq_strand_plus, &split);
3737
3738 tmp_loc = SeqLocFree (tmp_loc);
3739
3740 return new_loc;
3741 }
3742
3743
3744 static Boolean DoFeaturePropThruAlign (
3745 UpsDataPtr udp,
3746 SeqAnnotPtr PNTR sapp
3747 )
3748
3749 {
3750 BioseqPtr bsp, newbsp, oldbsp;
3751 CodeBreakPtr cbp, prevcbp, nextcbp;
3752 SeqMgrFeatContext context;
3753 CdRegionPtr crp;
3754 SeqFeatPtr dup, sfp, last = NULL;
3755 Uint2 entityID;
3756 Int4 from, to;
3757 Boolean keepProteinIDs;
3758 SeqLocPtr newloc;
3759 SeqEntryPtr newsep, prdsep, top;
3760 RnaRefPtr rrp;
3761 SeqAnnotPtr sap = NULL, saptmp;
3762 SeqDescrPtr sdp;
3763 SeqIdPtr sip;
3764 Boolean split;
3765 tRNAPtr trp;
3766 Boolean partial5, partial3;
3767
3768 if (udp == NULL) return FALSE;
3769
3770 SeqEntrySetScope (NULL);
3771
3772 sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &context);
3773 if (sfp == NULL) return FALSE;
3774
3775 keepProteinIDs = GetStatus (udp->keepProteinIDs);
3776
3777 oldbsp = udp->oldbsp;
3778
3779 entityID = ObjMgrGetEntityIDForPointer (oldbsp);
3780 top = GetBestTopParentForData (entityID, oldbsp);
3781
3782 sdp = ExtractBioSourceAndPubs (top);
3783
3784 sip = SeqIdFindBest (oldbsp->id, 0);
3785
3786 from = udp->new5;
3787 to = udp->new5 + udp->newa;
3788
3789 while (sfp != NULL) {
3790
3791 if (context.right >= from && context.left <= to) {
3792 split = FALSE;
3793 newloc = GetPropagatedLocation (sfp->location, udp->newbsp, udp->oldbsp,
3794 LengthForNewSequence (udp), udp->salp);
3795 if (newloc != NULL) {
3796 CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
3797 SetSeqLocPartial (newloc, partial5, partial3);
3798 dup = AsnIoMemCopy ((Pointer) sfp,
3799 (AsnReadFunc) SeqFeatAsnRead,
3800 (AsnWriteFunc) SeqFeatAsnWrite);
3801
3802 SeqLocFree (dup->location);
3803 dup->location = newloc;
3804 if (split) {
3805 dup->partial = TRUE;
3806 }
3807 dup->partial |= partial5;
3808 dup->partial |= partial3;
3809
3810 if (last == NULL) {
3811 sap = SeqAnnotNew ();
3812 if (oldbsp->annot == NULL) {
3813 oldbsp->annot = sap;
3814 } else {
3815 for (saptmp = oldbsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
3816 saptmp->next = sap;
3817 }
3818 sap->type = 1;
3819 sap->data = (Pointer) dup;
3820 } else {
3821 last->next = dup;
3822 }
3823 last = dup;
3824
3825 switch (dup->data.choice) {
3826 case SEQFEAT_CDREGION :
3827 crp = (CdRegionPtr) dup->data.value.ptrvalue;
3828 if (crp != NULL) {
3829 prevcbp = NULL;
3830 for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp) {
3831 nextcbp = cbp->next;
3832 newloc = GetPropagatedLocation (cbp->loc, udp->newbsp, udp->oldbsp,
3833 LengthForNewSequence (udp), udp->salp);
3834 SeqLocFree (cbp->loc);
3835 cbp->loc = newloc;
3836 if (cbp->loc == NULL) {
3837 if (prevcbp != NULL) {
3838 prevcbp->next = nextcbp;
3839 } else {
3840 crp->code_break = nextcbp;
3841 }
3842 cbp->next = NULL;
3843 CodeBreakFree (cbp);
3844 } else {
3845 prevcbp = cbp;
3846 }
3847 }
3848 }
3849 break;
3850 case SEQFEAT_RNA :
3851 rrp = (RnaRefPtr) dup->data.value.ptrvalue;
3852 if (rrp != NULL && rrp->ext.choice == 2) {
3853 trp = (tRNAPtr) rrp->ext.value.ptrvalue;
3854 if (trp != NULL && trp->anticodon != NULL) {
3855 newloc = GetPropagatedLocation (trp->anticodon, udp->newbsp, udp->oldbsp,
3856 LengthForNewSequence (udp), udp->salp);
3857 SeqLocFree (trp->anticodon);
3858 trp->anticodon = newloc;
3859 }
3860 }
3861 break;
3862 default :
3863 break;
3864 }
3865 if (dup->product != NULL) {
3866 SeqEntrySetScope (NULL);
3867 bsp = BioseqFindFromSeqLoc (dup->product);
3868 if (bsp != NULL) {
3869 prdsep = SeqMgrGetSeqEntryForData (bsp);
3870 if (prdsep != NULL) {
3871 newsep = AsnIoMemCopy ((Pointer) prdsep,
3872 (AsnReadFunc) SeqEntryAsnRead,
3873 (AsnWriteFunc) SeqEntryAsnWrite);
3874 if (newsep != NULL) {
3875 if (IS_Bioseq (newsep)) {
3876 newbsp = (BioseqPtr) newsep->data.ptrvalue;
3877 if (newbsp != NULL) {
3878 if (! keepProteinIDs) {
3879 newbsp->id = SeqIdSetFree (newbsp->id);
3880 newbsp->id = MakeNewProteinSeqId (NULL, sip);
3881 VisitFeaturesOnBsp (newbsp, (Pointer) newbsp->id, CorrectFeatureSeqIds);
3882 SetSeqFeatProduct (dup, newbsp);
3883 /*
3884 dup->product = SeqLocFree (dup->product);
3885 dup->product = CreateWholeInterval (newsep);
3886 */
3887 }
3888 SeqMgrReplaceInBioseqIndex (newbsp);
3889 }
3890 }
3891 AddSeqEntryToSeqEntry (top, newsep, TRUE);
3892 }
3893 }
3894 }
3895 }
3896 }
3897 }
3898
3899 sfp = SeqMgrGetNextFeature (udp->newbsp, sfp, 0, 0, &context);
3900 }
3901
3902 ReplaceBioSourceAndPubs (top, sdp);
3903
3904 if (sapp != NULL) {
3905 *sapp = sap;
3906 }
3907
3908 return TRUE;
3909 }
3910
3911 static void UpdateOneFeatureForSequenceReplace
3912 (SeqFeatPtr sfp,
3913 SeqAlignPtr salp,
3914 BioseqPtr oldbsp,
3915 Int4 new_len)
3916 {
3917 CodeBreakPtr cbp;
3918 CdRegionPtr crp;
3919 RnaRefPtr rrp;
3920 tRNAPtr trp;
3921
3922 if (sfp == NULL || salp == NULL)
3923 {
3924 return;
3925 }
3926
3927 ReplaceComplexLocation (sfp->location, salp, new_len, 1, 2);
3928
3929 switch (sfp->data.choice) {
3930 case SEQFEAT_CDREGION :
3931 crp = (CdRegionPtr) sfp->data.value.ptrvalue;
3932 if (crp != NULL)
3933 {
3934 for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next)
3935 {
3936 ReplaceComplexLocation (cbp->loc, salp, new_len, 1, 2);
3937 }
3938 }
3939 break;
3940 case SEQFEAT_RNA :
3941 rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
3942 if (rrp != NULL && rrp->ext.choice == 2) {
3943 trp = (tRNAPtr) rrp->ext.value.ptrvalue;
3944 if (trp != NULL && trp->anticodon != NULL) {
3945 ReplaceComplexLocation (trp->anticodon, salp, new_len, 1, 2);
3946 }
3947 }
3948 break;
3949 default :
3950 break;
3951 }
3952 }
3953
3954 static void UpdateLocationsForSequenceReplace
3955 (SeqAlignPtr salp,
3956 BioseqPtr oldbsp,
3957 BioseqPtr newbsp)
3958 {
3959 BioseqPtr parentbsp;
3960 SeqMgrFeatContext context;
3961 SeqMgrSegmentContext segcontext;
3962 SeqFeatPtr sfp;
3963
3964 if (salp == NULL || oldbsp == NULL || newbsp == NULL)
3965 {
3966 return;
3967 }
3968
3969 /* if this sequence is a part, the features will be indexed on
3970 * the parent.
3971 */
3972 parentbsp = SeqMgrGetParentOfPart (oldbsp, &segcontext);
3973 if (parentbsp == NULL)
3974 {
3975 sfp = SeqMgrGetNextFeature (oldbsp, NULL, 0, 0, &context);
3976 while (sfp != NULL)
3977 {
3978 UpdateOneFeatureForSequenceReplace (sfp, salp, oldbsp, newbsp->length);
3979 sfp = SeqMgrGetNextFeature (oldbsp, sfp, 0, 0, &context);
3980
3981 }
3982 }
3983 else
3984 {
3985 sfp = SeqMgrGetNextFeature (parentbsp, NULL, 0, 0, &context);
3986 while (sfp != NULL)
3987 {
3988 UpdateOneFeatureForSequenceReplace (sfp, salp, oldbsp, newbsp->length);
3989 sfp = SeqMgrGetNextFeature (parentbsp, sfp, 0, 0, &context);
3990 }
3991 }
3992 }
3993
3994 static void
3995 ReplaceOneSequence
3996 (SeqAlignPtr salp,
3997 BioseqPtr oldbsp,
3998 BioseqPtr newbsp)
3999 {
4000 SeqDataPtr bs;
4001 Int4 len, len_change;
4002 Uint1 seq_data_type, seq_ext_type;
4003 Pointer seq_ext;
4004 Uint1 repr;
4005 BioseqPtr parent_bsp;
4006 SeqMgrSegmentContext context;
4007
4008 if (oldbsp == NULL || newbsp == NULL)
4009 {
4010 return;
4011 }
4012
4013 UpdateLocationsForSequenceReplace (salp, oldbsp, newbsp);
4014 len_change = newbsp->length - oldbsp->length;
4015
4016 /* switch bioseqs to finish update */
4017
4018 bs = oldbsp->seq_data;
4019 oldbsp->seq_data = newbsp->seq_data;
4020 newbsp->seq_data = bs;
4021 len = oldbsp->length;
4022 oldbsp->length = newbsp->length;
4023 newbsp->length = len;
4024 seq_data_type = oldbsp->seq_data_type;
4025 oldbsp->seq_data_type = newbsp->seq_data_type;
4026 newbsp->seq_data_type = seq_data_type;
4027 /* also move seq_ext, for delta sequences */
4028 seq_ext_type = oldbsp->seq_ext_type;
4029 seq_ext = oldbsp->seq_ext;
4030 oldbsp->seq_ext_type = newbsp->seq_ext_type;
4031 oldbsp->seq_ext = newbsp->seq_ext;
4032 newbsp->seq_ext_type = seq_ext_type;
4033 newbsp->seq_ext = seq_ext;
4034
4035 /* swap repr */
4036 repr = oldbsp->repr;
4037 oldbsp->repr = newbsp->repr;
4038 newbsp->repr = repr;
4039
4040 /* if this was part of a segmented set, update the parent length */
4041 parent_bsp = SeqMgrGetParentOfPart (oldbsp, &context);
4042 if (parent_bsp != NULL)
4043 {
4044 parent_bsp->length += len_change;
4045 }
4046 }
4047
4048 static Boolean ReplaceSequence (UpsDataPtr udp)
4049
4050 {
4051 MsgAnswer ans;
4052
4053 if (udp == NULL)
4054 {
4055 return TRUE;
4056 }
4057
4058 if (FALSE == udp->isSet)
4059 {
4060 if ((udp->seq1 != NULL || udp->seq2 != NULL)
4061 && StringICmp (udp->seq1, udp->seq2) == 0
4062 && ! udp->revcomp)
4063 {
4064 ans = Message (MSG_OKC, "Replacement sequence is identical to"
4065 " original - possible error");
4066 if (ans == ANS_CANCEL) return FALSE;
4067 }
4068 }
4069
4070 ReplaceOneSequence (udp->salp, udp->oldbsp, udp->newbsp);
4071 return TRUE;
4072 }
4073
4074 static Boolean Merge5Prime (UpsDataPtr udp)
4075
4076 {
4077 ByteStorePtr bs;
4078 Char ch;
4079 Int4 i, newlen;
4080 BioseqPtr newbsp;
4081 CharPtr ptr, str, tmp;
4082
4083 /* construct replacement sequence by recombining between old and overlap */
4084
4085 tmp = udp->seq2;
4086
4087 newlen = udp->new5 + udp->newa + udp->old3;
4088 str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
4089 if (str == NULL)
4090 return FALSE;
4091 ptr = str;
4092
4093 for (i = 0; i < udp->new5 + udp->newa; i++) {
4094 ch = *tmp;
4095 *ptr = ch;
4096 tmp++;
4097 ptr++;
4098 }
4099
4100 tmp = udp->seq1 + udp->old5 + udp->olda;
4101 for (i = 0; i < udp->old3; i++) {
4102 ch = *tmp;
4103 *ptr = ch;
4104 tmp++;
4105 ptr++;
4106 }
4107
4108 *ptr = '\0';
4109 bs = BSNew (newlen);
4110 BSWrite (bs, (VoidPtr) str, newlen);
4111
4112 udp->seq2 = MemFree (udp->seq2);
4113 udp->seq2 = str;
4114
4115 if (bs != NULL && BSLen (bs) < 1) {
4116 bs = BSFree (bs);
4117 }
4118 if (bs == NULL) return FALSE;
4119
4120 /* overlap turned into replacement sequence */
4121
4122 newbsp = udp->newbsp;
4123 newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
4124 newbsp->seq_data = (SeqDataPtr) bs;
4125 newbsp->seq_data_type = Seq_code_iupacna;
4126 newbsp->length = newlen;
4127
4128 /* adjust alignment and reindex */
4129
4130 if (! AdjustAlignment (udp, 2)) return FALSE;
4131
4132 /* then finish by replacing with new sequence */
4133
4134 return ReplaceSequence (udp);
4135 }
4136
4137 static Boolean Merge3Prime (UpsDataPtr udp)
4138
4139 {
4140 ByteStorePtr bs;
4141 Char ch;
4142 Int4 i, newlen;
4143 BioseqPtr newbsp;
4144 CharPtr ptr, str, tmp;
4145
4146 /* construct replacement sequence by recombining between old and overlap */
4147
4148 newlen = udp->old5 + udp->newa + udp->new3;
4149 str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
4150 if (str == NULL)
4151 return FALSE;
4152 ptr = str;
4153
4154 tmp = udp->seq1;
4155 for (i = 0; i < udp->old5; i++) {
4156 ch = *tmp;
4157 *ptr = ch;
4158 tmp++;
4159 ptr++;
4160 }
4161
4162 tmp = udp->seq2 + udp->new5;
4163 for (i = 0; i < udp->newa + udp->new3; i++) {
4164 ch = *tmp;
4165 *ptr = ch;
4166 tmp++;
4167 ptr++;
4168 }
4169
4170 *ptr = '\0';
4171 bs = BSNew (newlen);
4172 BSWrite (bs, (VoidPtr) str, newlen);
4173
4174 udp->seq2 = MemFree (udp->seq2);
4175 udp->seq2 = str;
4176
4177 if (bs != NULL && BSLen (bs) < 1) {
4178 bs = BSFree (bs);
4179 }
4180 if (bs == NULL) return FALSE;
4181
4182 /* overlap turned into replacement sequence */
4183
4184 newbsp = udp->newbsp;
4185 newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
4186 newbsp->seq_data = (SeqDataPtr) bs;
4187 newbsp->seq_data_type = Seq_code_iupacna;
4188 newbsp->length = newlen;
4189
4190 /* adjust alignment and reindex */
4191
4192 if (! AdjustAlignment (udp, 3)) return FALSE;
4193
4194 /* then finish by replacing with new sequence */
4195
4196 return ReplaceSequence (udp);
4197 }
4198
4199 static Boolean ExtendFeatures (UpsDataPtr udp, Int4 offset);
4200
4201 /*------------------------------------------------------------------*/
4202 /* */
4203 /* Merge5PrimeNoOverlap () -- Merge a new sequence onto the 5' end */
4204 /* of an existing sequence. */
4205 /* */
4206 /* Performs a similar function to */
4207 /* Merge5Prime() except works when */
4208 /* there is no alignment between the */
4209 /* two sequences. */
4210 /* */
4211 /*------------------------------------------------------------------*/
4212
4213 static Boolean Merge5PrimeNoOverlap (UpsDataPtr udp)
4214
4215 {
4216 CharPtr origSeqStr;
4217 CharPtr newSeqStr;
4218 CharPtr mergedSeqStr;
4219 Int4 mergedLen;
4220 ByteStorePtr mergedBS;
4221
4222 /* Get original and new sequences */
4223
4224 origSeqStr = GetSequenceByBsp (udp->oldbsp);
4225 newSeqStr = GetSequenceByBsp (udp->newbsp);
4226
4227 /* Concatenate the new sequence onto the beginning */
4228 /* (i.e. the 5' end) of the original sequence. */
4229
4230 mergedLen = StringLen (newSeqStr) + StringLen (origSeqStr);
4231 mergedSeqStr = (CharPtr) MemNew (mergedLen + 1);
4232 sprintf (mergedSeqStr, "%s%s", newSeqStr, origSeqStr);
4233
4234 /* Convert the new sequence into a ByteStore */
4235
4236 mergedBS = BSNew (mergedLen);
4237 BSWrite (mergedBS, (VoidPtr) mergedSeqStr, mergedLen);
4238
4239 /* Replace the original sequence with the */
4240 /* new concatenated sequence. */
4241
4242 udp->newbsp->seq_data = SeqDataFree (udp->newbsp->seq_data, udp->newbsp->seq_data_type);
4243 udp->newbsp->seq_data = (SeqDataPtr) mergedBS;
4244 udp->newbsp->seq_data_type = Seq_code_iupacna;
4245 udp->newbsp->length = mergedLen;
4246
4247 /* Replace the merged sequence and return */
4248
4249 return ExtendFeatures (udp, StringLen (newSeqStr));
4250 }
4251
4252 /*------------------------------------------------------------------*/
4253 /* */
4254 /* Merge3PrimeNoOverlap () -- Merge a new sequence onto the 3' end */
4255 /* of an existing sequence. */
4256 /* */
4257 /* Performs a similar function to */
4258 /* Merge3Prime() except works when */
4259 /* there is no alignment between the */
4260 /* two sequences. */
4261 /* */
4262 /*------------------------------------------------------------------*/
4263
4264 static Boolean Merge3PrimeNoOverlap (UpsDataPtr udp)
4265
4266 {
4267 CharPtr origSeqStr;
4268 CharPtr newSeqStr;
4269 CharPtr mergedSeqStr;
4270 Int4 mergedLen;
4271 ByteStorePtr mergedBS;
4272
4273 /* Get original and new sequences */
4274
4275 origSeqStr = GetSequenceByBsp (udp->oldbsp);
4276 newSeqStr = GetSequenceByBsp (udp->newbsp);
4277
4278 /* Concatenate the new sequence onto the end */
4279 /* (i.e. the 3' end) of the original sequence. */
4280
4281 mergedLen = StringLen (newSeqStr) + StringLen (origSeqStr);
4282 mergedSeqStr = (CharPtr) MemNew (mergedLen + 1);
4283 sprintf (mergedSeqStr, "%s%s", origSeqStr, newSeqStr);
4284
4285 /* Convert the new sequence into a ByteStore */
4286
4287 mergedBS = BSNew (mergedLen);
4288 BSWrite (mergedBS, (VoidPtr) mergedSeqStr, mergedLen);
4289
4290 /* Replace the original sequence with the */
4291 /* new concatenated sequence. */
4292
4293 udp->newbsp->seq_data = SeqDataFree (udp->newbsp->seq_data, udp->newbsp->seq_data_type);
4294 udp->newbsp->seq_data = (SeqDataPtr) mergedBS;
4295 udp->newbsp->seq_data_type = Seq_code_iupacna;
4296 udp->newbsp->length = mergedLen;
4297
4298 /* Replace the merged sequence and return */
4299
4300 return ExtendFeatures (udp, 0);
4301 }
4302
4303 static Boolean OkToPatchDelta (UpsDataPtr udp)
4304 {
4305 Boolean rval = TRUE;
4306
4307 if (udp == NULL || udp->oldbsp == NULL || udp->newbsp == NULL
4308 || udp->oldbsp->repr != Seq_repr_delta || udp->newbsp->repr != Seq_repr_delta
4309 || udp->oldbsp->seq_ext_type != 4 || udp->newbsp->seq_ext_type != 4)
4310 {
4311 rval = FALSE;
4312 }
4313
4314 return rval;
4315 }
4316
4317 static void SplitDeltaSeq (DeltaSeqPtr dsp, Int4 offset)
4318 {
4319 SeqLocPtr slp1, slp2;
4320 SeqLitPtr slip1, slip2;
4321 Int4 len;
4322 Boolean changed;
4323 DeltaSeqPtr dsp_new;
4324 ByteStorePtr bs_1, bs_2;
4325 Int2 residue;
4326 Int4 pos;
4327
4328 if (dsp == NULL || dsp->data.ptrvalue == NULL || offset == 0)
4329 {
4330 return;
4331 }
4332
4333 if (dsp->choice == 1)
4334 {
4335 slp1 = (SeqLocPtr)(dsp->data.ptrvalue);
4336 len = SeqLocLen (slp1);
4337 if (offset > len)
4338 {
4339 return;
4340 }
4341 slp2 = (SeqLocPtr) AsnIoMemCopy (slp1, (AsnReadFunc) SeqLocAsnRead,
4342 (AsnWriteFunc) SeqLocAsnWrite);
4343 slp1 = SeqLocDelete (slp1, SeqLocId (slp1),
4344 offset, len - 1, FALSE, &changed);
4345 slp2 = SeqLocDelete (slp2, SeqLocId (slp2),
4346 0, offset, FALSE, &changed);
4347 dsp_new = ValNodeNew (NULL);
4348 dsp_new->choice = 1;
4349 dsp_new->data.ptrvalue = slp2;
4350 dsp_new->next = dsp->next;
4351 dsp->next = dsp_new;
4352 }
4353 else if (dsp->choice == 2)
4354 {
4355 slip1 = (SeqLitPtr) dsp->data.ptrvalue;
4356 if (offset > slip1->length)
4357 {
4358 return;
4359 }
4360 if (IsDeltaSeqGap (dsp))
4361 {
4362 /* use AsnIoMemCopy, to automatically copy gap data if present */
4363 slip2 = (SeqLitPtr) AsnIoMemCopy (slip1, (AsnReadFunc) SeqLitAsnRead, (AsnWriteFunc) SeqLitAsnWrite);
4364 slip2->length = slip1->length - offset;
4365 slip1->length = offset;
4366 }
4367 else
4368 {
4369 slip2 = SeqLitNew ();
4370 if (slip1->seq_data_type == Seq_code_iupacna)
4371 {
4372 bs_1 = (ByteStorePtr) slip1->seq_data;
4373 }
4374 else
4375 {
4376 bs_1 = BSConvertSeq((ByteStorePtr) slip1->seq_data, Seq_code_iupacna,
4377 slip1->seq_data_type,
4378 slip1->length);
4379 slip1->seq_data_type = Seq_code_iupacna;
4380 slip1->seq_data = (SeqDataPtr) bs_1;
4381 }
4382 bs_2 = BSNew (slip1->length - offset);
4383 pos = offset;
4384 BSSeek(bs_1, pos, SEEK_SET);
4385 BSSeek (bs_2, 0L, SEEK_SET);
4386 while (pos < slip1->length)
4387 {
4388 residue = BSGetByte (bs_1);
4389 BSPutByte (bs_2, residue);
4390 pos++;
4391 }
4392 BSSeek(bs_1, offset, SEEK_SET);
4393 BSDelete(bs_1, slip1->length - offset);
4394
4395 slip2->seq_data = (SeqDataPtr) bs_2;
4396 slip2->seq_data_type = slip1->seq_data_type;
4397 slip2->length = slip1->length - offset;
4398 slip1->length = offset;
4399 }
4400 dsp_new = ValNodeNew (NULL);
4401 dsp_new->choice = 2;
4402 dsp_new->data.ptrvalue = slip2;
4403 dsp_new->next = dsp->next;
4404 dsp->next = dsp_new;
4405 }
4406 }
4407
4408 /* This function will patch a delta sequence with another delta sequence.
4409 * The pieces in the overlap from the old sequence will be replaced by pieces
4410 * in the overlap from the new sequence.
4411 */
4412 static Boolean PatchDeltaSequence (UpsDataPtr udp)
4413
4414 {
4415 Int4 currnew_pos = 0, currold_pos;
4416 SeqLitPtr slip, slip_new;
4417 DeltaSeqPtr dspold, dspnew;
4418 Int4 seqstart;
4419 DeltaSeqPtr new_list = NULL;
4420
4421 if (! OkToPatchDelta (udp))
4422 {
4423 return FALSE;
4424 }
4425
4426 /* keep old 5' end intact */
4427 currold_pos = 0;
4428 seqstart = 0;
4429 dspold = (DeltaSeqPtr) udp->oldbsp->seq_ext;
4430 while (dspold != NULL && currold_pos < udp->old5)
4431 {
4432 seqstart = currold_pos;
4433 if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
4434 {
4435 return FALSE;
4436 }
4437 slip = (SeqLitPtr) (dspold->data.ptrvalue);
4438 currold_pos += slip->length;
4439 if (currold_pos > udp->old5)
4440 {
4441 SplitDeltaSeq (dspold, udp->old5 - seqstart);
4442 slip = (SeqLitPtr) (dspold->data.ptrvalue);
4443 currold_pos = udp->old5;
4444 }
4445 slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
4446 (AsnWriteFunc) SeqLitAsnWrite);
4447 ValNodeAddPointer (&new_list, 2, slip_new);
4448 dspold = dspold->next;
4449 }
4450
4451 /* skip over new 5' end */
4452 currnew_pos = 0;
4453 seqstart = 0;
4454 dspnew = (DeltaSeqPtr) udp->newbsp->seq_ext;
4455 while (dspnew != NULL && currnew_pos < udp->new5)
4456 {
4457 seqstart = currold_pos;
4458 if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
4459 {
4460 return FALSE;
4461 }
4462 slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4463 currnew_pos += slip->length;
4464 if (currnew_pos > udp->new5)
4465 {
4466 SplitDeltaSeq (dspnew, udp->new5 - seqstart);
4467 currnew_pos = udp->new5;
4468 }
4469 dspnew = dspnew->next;
4470 }
4471
4472 /* copy in new overlap */
4473 while (dspnew != NULL && currnew_pos < udp->new5 + udp->newa)
4474 {
4475 seqstart = currold_pos;
4476 if (dspnew->data.ptrvalue == NULL || dspnew->choice != 2)
4477 {
4478 return FALSE;
4479 }
4480 slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4481 currnew_pos += slip->length;
4482 if (currnew_pos > udp->new5 + udp->newa)
4483 {
4484 SplitDeltaSeq (dspnew, udp->new5 + udp->newa - seqstart);
4485 slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4486 currnew_pos = udp->new5 + udp->newa;
4487 }
4488 slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
4489 (AsnWriteFunc) SeqLitAsnWrite);
4490 ValNodeAddPointer (&new_list, 2, slip_new);
4491 dspnew = dspnew->next;
4492 }
4493
4494 /* skip over old overlap */
4495
4496 while (dspold != NULL && currold_pos < udp->old5 + udp->olda)
4497 {
4498 seqstart = currold_pos;
4499 if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
4500 {
4501 return FALSE;
4502 }
4503 slip = (SeqLitPtr) (dspold->data.ptrvalue);
4504 currold_pos += slip->length;
4505 if (currold_pos > udp->old5 + udp->olda)
4506 {
4507 SplitDeltaSeq (dspold, udp->new5 + udp->newa - seqstart);
4508 currold_pos = udp->old5 + udp->olda;
4509 }
4510 dspold = dspold->next;
4511 }
4512
4513 /* copy in old 3' */
4514
4515 while (dspold != NULL)
4516 {
4517 if (dspold->data.ptrvalue == NULL || dspold->choice != 2)
4518 {
4519 return FALSE;
4520 }
4521 slip = (SeqLitPtr) (dspold->data.ptrvalue);
4522 slip_new = (SeqLitPtr) AsnIoMemCopy (slip, (AsnReadFunc) SeqLitAsnRead,
4523 (AsnWriteFunc) SeqLitAsnWrite);
4524 ValNodeAddPointer (&new_list, 2, slip_new);
4525 dspold = dspold->next;
4526 }
4527
4528 /* free newbsp's old SeqLit List */
4529 for (dspnew = (DeltaSeqPtr) udp->newbsp->seq_ext;
4530 dspnew != NULL;
4531 dspnew = dspnew->next)
4532 {
4533 slip = (SeqLitPtr) (dspnew->data.ptrvalue);
4534 SeqLitFree (slip);
4535 }
4536 udp->newbsp->seq_ext = ValNodeFree (udp->newbsp->seq_ext);
4537 udp->newbsp->seq_ext = new_list;
4538 udp->newbsp->length = udp->old5 + udp->newa + udp->old3;
4539 return TRUE;
4540 }
4541
4542 static Boolean OkToPatchRaw (UpsDataPtr udp)
4543 {
4544 Boolean rval = TRUE;
4545
4546 if (udp == NULL || udp->oldbsp == NULL || udp->newbsp == NULL
4547 || udp->oldbsp->repr != Seq_repr_raw || udp->newbsp->repr != Seq_repr_raw)
4548 {
4549 rval = FALSE;
4550 }
4551
4552 return rval;
4553 }
4554
4555 static Boolean PatchRawSequence (UpsDataPtr udp)
4556
4557 {
4558 ByteStorePtr bs;
4559 Char ch;
4560 Int4 i, newlen;
4561 BioseqPtr newbsp;
4562 CharPtr ptr, str, tmp;
4563
4564 newlen = udp->old5 + udp->newa + udp->old3;
4565 str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
4566 if (str == NULL) return FALSE;
4567
4568 /* construct replacement sequence by double recombination */
4569 ptr = str;
4570
4571 tmp = udp->seq1;
4572 for (i = 0; i < udp->old5; i++) {
4573 ch = *tmp;
4574 *ptr = ch;
4575 tmp++;
4576 ptr++;
4577 }
4578
4579 tmp = udp->seq2 + udp->new5;
4580 for (i = 0; i < udp->newa; i++) {
4581 ch = *tmp;
4582 *ptr = ch;
4583 tmp++;
4584 ptr++;
4585 }
4586
4587 tmp = udp->seq1 + udp->old5 + udp->olda;
4588 for (i = 0; i < udp->old3; i++) {
4589 ch = *tmp;
4590 *ptr = ch;
4591 tmp++;
4592 ptr++;
4593 }
4594
4595 *ptr = '\0';
4596 bs = BSNew (newlen);
4597 BSWrite (bs, (VoidPtr) str, newlen);
4598
4599 udp->seq2 = MemFree (udp->seq2);
4600 udp->seq2 = str;
4601
4602 if (bs != NULL && BSLen (bs) < 1) {
4603 bs = BSFree (bs);
4604 }
4605 if (bs == NULL) return FALSE;
4606
4607 /* overlap turned into replacement sequence */
4608
4609 newbsp = udp->newbsp;
4610 newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
4611 newbsp->seq_data = (SeqDataPtr) bs;
4612 newbsp->seq_data_type = Seq_code_iupacna;
4613 newbsp->length = newlen;
4614 return TRUE;
4615 }
4616
4617 static Boolean PatchSequence (UpsDataPtr udp)
4618
4619 {
4620 Boolean rval = FALSE;
4621
4622 if (OkToPatchRaw (udp))
4623 {
4624 rval = PatchRawSequence (udp);
4625 }
4626 else if (OkToPatchDelta (udp))
4627 {
4628 rval = PatchDeltaSequence (udp);
4629 }
4630
4631 if (!rval)
4632 {
4633 return rval;
4634 }
4635
4636 /* adjust alignment and reindex */
4637
4638 if (! AdjustAlignment (udp, 4)) return FALSE;
4639
4640 /* then finish by replacing with new sequence */
4641
4642 return ReplaceSequence (udp);
4643 }
4644
4645 static void MarkProductForDeletion (
4646 SeqLocPtr product
4647 )
4648
4649 {
4650 BioseqPtr bsp;
4651 SeqIdPtr sip;
4652
4653 if (product == NULL) return;
4654 sip = SeqLocId (product);
4655 if (sip == NULL) return;
4656 bsp = BioseqFind (sip);
4657 if (bsp == NULL) return;
4658 bsp->idx.deleteme = TRUE;
4659 }
4660
4661 static void CombineTexts (
4662 CharPtr PNTR txtptr,
4663 CharPtr PNTR oldtxtptr
4664 )
4665
4666 {
4667 size_t len;
4668 CharPtr str;
4669
4670 if (txtptr == NULL || oldtxtptr == NULL) return;
4671
4672 if (*txtptr == NULL) {
4673
4674 *txtptr = *oldtxtptr;
4675 *oldtxtptr = NULL;
4676
4677 } else if (*oldtxtptr != NULL && StringICmp (*txtptr, *oldtxtptr) != 0) {
4678
4679 len = StringLen (*txtptr) + StringLen (*oldtxtptr) + 5;
4680 str = MemNew (sizeof (Char) * len);
4681 StringCpy (str, *txtptr);
4682 StringCat (str, "; ");
4683 StringCat (str, *oldtxtptr);
4684 *txtptr = MemFree (*txtptr);
4685 *txtptr = str;
4686 }
4687 }
4688
4689 static void FuseCommonFeatureFields (
4690 SeqFeatPtr sfp,
4691 SeqFeatPtr oldsfp
4692 )
4693
4694 {
4695 GBQualPtr lastgbq;
4696 SeqFeatXrefPtr lastxref;
4697
4698 if (sfp == NULL || oldsfp == NULL) return;
4699
4700 CombineTexts (&(sfp->comment), &(oldsfp->comment));
4701 CombineTexts (&(sfp->title), &(oldsfp->title));
4702 CombineTexts (&(sfp->except_text), &(oldsfp->except_text));
4703
4704 if (sfp->qual == NULL) {
4705 sfp->qual = oldsfp->qual;
4706 oldsfp->qual = NULL;
4707 } else if (oldsfp->qual != NULL) {
4708 for (lastgbq = sfp->qual; lastgbq->next != NULL; lastgbq = lastgbq->next) continue;
4709 lastgbq->next = oldsfp->qual;
4710 oldsfp->qual = NULL;
4711 }
4712
4713 ValNodeLink (&(sfp->dbxref), oldsfp->dbxref);
4714 oldsfp->dbxref = NULL;
4715
4716 ValNodeLink (&(sfp->cit), oldsfp->cit);
4717 oldsfp->cit = NULL;
4718
4719 if (sfp->xref == NULL) {
4720 sfp->xref = oldsfp->xref;
4721 oldsfp->xref = NULL;
4722 } else if (oldsfp->xref != NULL) {
4723 for (lastxref = sfp->xref; lastxref->next != NULL; lastxref = lastxref->next) continue;
4724 lastxref->next = oldsfp->xref;
4725 oldsfp->xref = NULL;
4726 }
4727
4728 if (sfp->ext == NULL) {
4729 sfp->ext = oldsfp->ext;
4730 oldsfp->ext = NULL;
4731 } else if (oldsfp->ext != NULL) {
4732 sfp->ext = CombineUserObjects (sfp->ext, oldsfp->ext);
4733 oldsfp->ext = NULL;
4734 }
4735
4736 sfp->partial |= oldsfp->partial;
4737 sfp->excpt |= oldsfp->excpt;
4738 sfp->pseudo |= oldsfp->pseudo;
4739 }
4740
4741 static void FuseFeatures (
4742 SeqFeatPtr sfp,
4743 SeqFeatPtr oldsfp
4744 )
4745
4746 {
4747 GeneRefPtr grp, oldgrp;
4748 BioseqPtr prod, oldprod;
4749 SeqFeatPtr prot, oldprot;
4750 ProtRefPtr prp, oldprp;
4751 RnaRefPtr rrp, oldrrp;
4752 SeqIdPtr sip;
4753
4754 if (sfp == NULL || oldsfp == NULL) return;
4755
4756 /* merge common fields */
4757
4758 FuseCommonFeatureFields (sfp, oldsfp);
4759
4760 /* now deal with type-specific data */
4761
4762 switch (sfp->data.choice) {
4763 case SEQFEAT_GENE :
4764 grp = (GeneRefPtr) sfp->data.value.ptrvalue;
4765 oldgrp = (GeneRefPtr) oldsfp->data.value.ptrvalue;
4766 if (grp == NULL || oldgrp == NULL) return;
4767 CombineTexts (&(grp->locus), &(oldgrp->locus));
4768 CombineTexts (&(grp->allele), &(oldgrp->allele));
4769 CombineTexts (&(grp->desc), &(oldgrp->desc));
4770 CombineTexts (&(grp->maploc), &(oldgrp->maploc));
4771 CombineTexts (&(grp->locus_tag), &(oldgrp->locus_tag));
4772 grp->pseudo |= oldgrp->pseudo;
4773 ValNodeLink (&(grp->db), oldgrp->db);
4774 oldgrp->db = NULL;
4775 ValNodeLink (&(grp->syn), oldgrp->syn);
4776 oldgrp->syn = NULL;
4777 break;
4778 case SEQFEAT_CDREGION :
4779 sip = SeqLocId (sfp->product);
4780 prod = BioseqFind (sip);
4781 sip = SeqLocId (oldsfp->product);
4782 oldprod = BioseqFind (sip);
4783 if (prod == NULL || oldprod == NULL) return;
4784 prot = SeqMgrGetBestProteinFeature (prod, NULL);
4785 oldprot = SeqMgrGetBestProteinFeature (oldprod, NULL);
4786 if (prot == NULL || oldprot == NULL) return;
4787 FuseCommonFeatureFields (prot, oldprot);
4788 prp = (ProtRefPtr) prot->data.value.ptrvalue;
4789 oldprp = (ProtRefPtr) oldprot->data.value.ptrvalue;
4790 if (prp == NULL || oldprp == NULL) return;
4791 ValNodeLink (&(prp->name), oldprp->name);
4792 oldprp->name = NULL;
4793 ValNodeLink (&(prp->ec), oldprp->ec);
4794 oldprp->ec = NULL;
4795 ValNodeLink (&(prp->activity), oldprp->activity);
4796 oldprp->activity = NULL;
4797 ValNodeLink (&(prp->db), oldprp->db);
4798 oldprp->db = NULL;
4799 CombineTexts (&(prp->desc), &(oldprp->desc));
4800 break;
4801 case SEQFEAT_RNA :
4802 rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
4803 oldrrp = (RnaRefPtr) oldsfp->data.value.ptrvalue;
4804 if (rrp == NULL || oldrrp == NULL) return;
4805 if (rrp->ext.choice == 1 && oldrrp->ext.choice == 1) {
4806 CombineTexts ((CharPtr PNTR) &(rrp->ext.value.ptrvalue), (CharPtr PNTR) &(oldrrp->ext.value.ptrvalue));
4807 }
4808 break;
4809 case SEQFEAT_REGION :
4810 case SEQFEAT_COMMENT :
4811 if (sfp->data.value.ptrvalue == NULL || oldsfp->data.value.ptrvalue == NULL) return;
4812 CombineTexts ((CharPtr PNTR) &(sfp->data.value.ptrvalue), (CharPtr PNTR) &(oldsfp->data.value.ptrvalue));
4813 break;
4814 default :
4815 break;
4816 }
4817 }
4818
4819 static void RemoveOldFeatsInRegion (
4820 UpsDataPtr udp,
4821 BioseqPtr bsp,
4822 SeqAnnotPtr sap
4823 )
4824
4825 {
4826 SeqMgrFeatContext context;
4827 Int4 left, right;
4828 SeqFeatPtr sfp;
4829
4830 if (udp == NULL || bsp == NULL || sap == NULL) return;
4831 if (sap->type != 1) return;
4832
4833 left = INT4_MAX;
4834 right = INT4_MIN;
4835
4836 for (sfp = (SeqFeatPtr) sap->data; sfp != NULL; sfp = sfp->next) {
4837 if (sfp != SeqMgrGetDesiredFeature (0, bsp, 0, 0, sfp, &context)) continue;
4838 left = MIN (left, context.left);
4839 right = MAX (right, context.right);
4840 }
4841
4842 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
4843
4844 while (sfp != NULL) {
4845
4846 if (context.sap != sap && context.right >= left && context.left <= right) {
4847 sfp->idx.deleteme = TRUE;
4848 MarkProductForDeletion (sfp->product);
4849 }
4850
4851 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
4852 }
4853 }
4854
4855 static void RemoveOldFeats (BioseqPtr bsp)
4856
4857 {
4858 SeqMgrFeatContext context;
4859 SeqFeatPtr sfp;
4860
4861 if (bsp == NULL) return;
4862
4863 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
4864
4865 while (sfp != NULL)
4866 {
4867 sfp->idx.deleteme = TRUE;
4868 MarkProductForDeletion (sfp->product);
4869 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
4870 }
4871 }
4872
4873
4874 static void ResolveDuplicateFeats (
4875 UpsDataPtr udp,
4876 BioseqPtr bsp,
4877 SeqAnnotPtr sap
4878 )
4879
4880 {
4881 SeqMgrFeatContext context, lastcontext;
4882 Int2 i, j;
4883 Boolean ivalssame;
4884 SeqFeatPtr lastsfp = NULL, sfp;
4885 Int2 nobmval;
4886
4887 if (udp == NULL || bsp == NULL || sap == NULL) return;
4888
4889 nobmval = GetValue (udp->nobm);
4890 if (nobmval == UPDATE_FEAT_DUP_USE_BOTH) return; /* keep both */
4891
4892 SeqMgrIndexFeatures (0, (Pointer) bsp);
4893
4894 if (nobmval == UPDATE_FEAT_DUP_REPLACE) {
4895 RemoveOldFeatsInRegion (udp, bsp, sap);
4896 return;
4897 }
4898
4899 lastsfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
4900 if (lastsfp == NULL) return;
4901
4902 MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
4903
4904 sfp = SeqMgrGetNextFeature (bsp, lastsfp, 0, 0, &context);
4905 if (sfp == NULL) return;
4906
4907 while (sfp != NULL) {
4908
4909 if (context.left == lastcontext.left &&
4910 context.right == lastcontext.right &&
4911 context.featdeftype == lastcontext.featdeftype) {
4912
4913 if (context.strand == lastcontext.strand ||
4914 lastcontext.strand == Seq_strand_unknown ||
4915 context.strand == Seq_strand_unknown) {
4916
4917 ivalssame = TRUE;
4918 if (context.numivals != lastcontext.numivals ||
4919 context.ivals == NULL ||
4920 lastcontext.ivals == NULL) {
4921
4922 ivalssame = FALSE;
4923
4924 } else {
4925
4926 for (i = 0, j = 0; i < lastcontext.numivals; i++, j += 2) {
4927 if (context.ivals [j] != lastcontext.ivals [j]) {
4928 ivalssame = FALSE;
4929 }
4930 if (context.ivals [j + 1] != lastcontext.ivals [j + 1]) {
4931 ivalssame = FALSE;
4932 }
4933 }
4934 }
4935
4936 if (ivalssame &&
4937 context.sap != lastcontext.sap &&
4938 (context.sap == sap || lastcontext.sap == sap)) {
4939
4940 if (nobmval == UPDATE_FEAT_DUP_USE_NEW) { /* keep new */
4941 if (context.sap == sap) {
4942 lastsfp->idx.deleteme = TRUE;
4943 MarkProductForDeletion (lastsfp->product);
4944 } else if (lastcontext.sap == sap) {
4945 sfp->idx.deleteme = TRUE;
4946 MarkProductForDeletion (sfp->product);
4947 }
4948
4949 } else if (nobmval == UPDATE_FEAT_DUP_USE_OLD) { /* keep old */
4950 if (context.sap == sap) {
4951 sfp->idx.deleteme = TRUE;
4952 MarkProductForDeletion (sfp->product);
4953 } else if (lastcontext.sap == sap) {
4954 lastsfp->idx.deleteme = TRUE;
4955 MarkProductForDeletion (lastsfp->product);
4956 }
4957
4958 } else if (nobmval == UPDATE_FEAT_DUP_MERGE) { /* merge */
4959 if (context.sap == sap) {
4960 FuseFeatures (sfp, lastsfp);
4961 lastsfp->idx.deleteme = TRUE;
4962 MarkProductForDeletion (lastsfp->product);
4963 } else if (lastcontext.sap == sap) {
4964 FuseFeatures (lastsfp, sfp);
4965 sfp->idx.deleteme = TRUE;
4966 MarkProductForDeletion (sfp->product);
4967 }
4968 }
4969 }
4970 }
4971 }
4972
4973 lastsfp = sfp;
4974 MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
4975
4976 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
4977 }
4978 }
4979
4980 extern void AddCitSubToUpdatedSequence (BioseqPtr upd_bsp, Uint2 input_entityID, CharPtr update_txt)
4981 {
4982 SeqEntryPtr top_sep, upd_sep;
4983
4984 upd_sep = SeqMgrGetSeqEntryForData (upd_bsp);
4985 if (upd_sep == NULL) return;
4986 top_sep = GetTopSeqEntryForEntityID ( input_entityID);
4987 if (top_sep == NULL) return;
4988 CreateUpdateCitSubFromBestTemplate (top_sep, upd_sep, update_txt);
4989 }
4990
4991 static Boolean ExtendFeatures (UpsDataPtr udp, Int4 offset)
4992
4993 {
4994 MsgAnswer ans;
4995 CodeBreakPtr cbp;
4996 SeqMgrFeatContext context;
4997 CdRegionPtr crp;
4998 Int4 len;
4999 BioseqPtr newbsp;
5000 BioseqPtr oldbsp;
5001 RnaRefPtr rrp;
5002 Uint1 seq_data_type;
5003 SeqFeatPtr sfp;
5004 SeqIdPtr sip;
5005 tRNAPtr trp;
5006 SeqDataPtr sdp;
5007
5008 if (udp->salp != NULL)
5009 if (FALSE == udp->isSet)
5010 if (StringICmp (udp->seq1, udp->seq2) == 0) {
5011 ans = Message (MSG_OKC, "Replacement sequence is identical to"
5012 " original - possible error");
5013 if (ans == ANS_CANCEL) return FALSE;
5014 }
5015
5016 oldbsp = udp->oldbsp;
5017 newbsp = udp->newbsp;
5018
5019 sip = SeqIdFindBest (oldbsp->id, 0);
5020 if (sip == NULL) return FALSE;
5021
5022 if (offset > 0) {
5023 sfp = SeqMgrGetNextFeature (oldbsp, NULL, 0, 0, &context);
5024 while (sfp != NULL) {
5025 OffsetLocation (sfp->location, offset, sip);
5026 switch (sfp->data.choice) {
5027 case SEQFEAT_CDREGION :
5028 crp = (CdRegionPtr) sfp->data.value.ptrvalue;
5029 if (crp != NULL) {
5030 for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
5031 OffsetLocation (cbp->loc, offset, sip);
5032 }
5033 }
5034 break;
5035 case SEQFEAT_RNA :
5036 rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
5037 if (rrp != NULL && rrp->ext.choice == 2) {
5038 trp = (tRNAPtr) rrp->ext.value.ptrvalue;
5039 if (trp != NULL && trp->anticodon != NULL) {
5040 OffsetLocation (trp->anticodon, offset, sip);
5041 }
5042 }
5043 break;
5044 default :
5045 break;
5046 }
5047 sfp = SeqMgrGetNextFeature (oldbsp, sfp, 0, 0, &context);
5048 }
5049 }
5050
5051 /* switch bioseqs to finish extension */
5052
5053 sdp = oldbsp->seq_data;
5054 oldbsp->seq_data = newbsp->seq_data;
5055 newbsp->seq_data = sdp;
5056 len = oldbsp->length;
5057 oldbsp->length = newbsp->length;
5058 newbsp->length = len;
5059 seq_data_type = oldbsp->seq_data_type;
5060 oldbsp->seq_data_type = newbsp->seq_data_type;
5061 newbsp->seq_data_type = seq_data_type;
5062
5063 return TRUE;
5064 }
5065
5066 static Boolean ExtendBothEnds (UpsDataPtr udp)
5067
5068 {
5069 ByteStorePtr bs;
5070 Char ch;
5071 Int4 i, newlen;
5072 BioseqPtr newbsp;
5073 BioseqPtr oldbsp;
5074 CharPtr ptr, str, tmp;
5075
5076 /* construct replacement sequence by extending old sequence */
5077
5078 newlen = udp->new5 + udp->olda + udp->new3;
5079 str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
5080 if (str == NULL)
5081 return FALSE;
5082 ptr = str;
5083
5084 tmp = udp->seq2;
5085 for (i = 0; i < udp->new5; i++) {
5086 ch = *tmp;
5087 *ptr = ch;
5088 tmp++;
5089 ptr++;
5090 }
5091
5092 tmp = udp->seq1 + udp->old5;
5093 for (i = 0; i < udp->olda; i++) {
5094 ch = *tmp;
5095 *ptr = ch;
5096 tmp++;
5097 ptr++;
5098 }
5099
5100 tmp = udp->seq2 + udp->new5 + udp->newa;
5101 for (i = 0; i < udp->new3; i++) {
5102 ch = *tmp;
5103 *ptr = ch;
5104 tmp++;
5105 ptr++;
5106 }
5107
5108 *ptr = '\0';
5109 bs = BSNew (newlen);
5110 BSWrite (bs, (VoidPtr) str, newlen);
5111
5112 udp->seq2 = MemFree (udp->seq2);
5113 udp->seq2 = str;
5114
5115 if (bs != NULL && BSLen (bs) < 1) {
5116 bs = BSFree (bs);
5117 }
5118 if (bs == NULL) return FALSE;
5119
5120 /* overlap turned into replacement sequence */
5121
5122 oldbsp = udp->oldbsp;
5123 newbsp = udp->newbsp;
5124 newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
5125 newbsp->seq_data = (SeqDataPtr) bs;
5126 newbsp->seq_data_type = Seq_code_iupacna;
5127 newbsp->length = newlen;
5128
5129 /* then finish by offsetting features */
5130
5131 return ExtendFeatures (udp, udp->new5);
5132 }
5133
5134 static Boolean Extend5Prime (UpsDataPtr udp)
5135
5136 {
5137 ByteStorePtr bs;
5138 Char ch;
5139 Int4 i, newlen;
5140 BioseqPtr newbsp;
5141 BioseqPtr oldbsp;
5142 CharPtr ptr, str, tmp;
5143
5144 /* construct replacement sequence by extending old sequence */
5145
5146 newlen = udp->new5 + udp->olda + udp->old3;
5147 str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
5148 if (str == NULL)
5149 return FALSE;
5150 ptr = str;
5151
5152 tmp = udp->seq2;
5153 for (i = 0; i < udp->new5; i++) {
5154 ch = *tmp;
5155 *ptr = ch;
5156 tmp++;
5157 ptr++;
5158 }
5159
5160 tmp = udp->seq1 + udp->old5;
5161 for (i = 0; i < udp->olda + udp->old3; i++) {
5162 ch = *tmp;
5163 *ptr = ch;
5164 tmp++;
5165 ptr++;
5166 }
5167
5168 *ptr = '\0';
5169 bs = BSNew (newlen);
5170 BSWrite (bs, (VoidPtr) str, newlen);
5171
5172 udp->seq2 = MemFree (udp->seq2);
5173 udp->seq2 = str;
5174
5175 if (bs != NULL && BSLen (bs) < 1) {
5176 bs = BSFree (bs);
5177 }
5178 if (bs == NULL) return FALSE;
5179
5180 /* overlap turned into replacement sequence */
5181
5182 oldbsp = udp->oldbsp;
5183 newbsp = udp->newbsp;
5184 newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
5185 newbsp->seq_data = (SeqDataPtr) bs;
5186 newbsp->seq_data_type = Seq_code_iupacna;
5187 newbsp->length = newlen;
5188
5189 /* then finish by offsetting features */
5190
5191 return ExtendFeatures (udp, udp->new5);
5192 }
5193
5194 static Boolean Extend3Prime (UpsDataPtr udp)
5195
5196 {
5197 ByteStorePtr bs;
5198 Char ch;
5199 Int4 i, newlen;
5200 BioseqPtr newbsp;
5201 BioseqPtr oldbsp;
5202 CharPtr ptr, str, tmp;
5203
5204 /* construct replacement sequence by extending old sequence */
5205
5206 newlen = udp->old5 + udp->olda + udp->new3;
5207 str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
5208 if (str == NULL)
5209 return FALSE;
5210 ptr = str;
5211
5212 tmp = udp->seq1;
5213 for (i = 0; i < udp->old5 + udp->olda; i++) {
5214 ch = *tmp;
5215 *ptr = ch;
5216 tmp++;
5217 ptr++;
5218 }
5219
5220 tmp = udp->seq2 + udp->new5 + udp->newa;
5221 for (i = 0; i < udp->new3; i++) {
5222 ch = *tmp;
5223 *ptr = ch;
5224 tmp++;
5225 ptr++;
5226 }
5227
5228 *ptr = '\0';
5229 bs = BSNew (newlen);
5230 BSWrite (bs, (VoidPtr) str, newlen);
5231
5232 udp->seq2 = MemFree (udp->seq2);
5233 udp->seq2 = str;
5234
5235 if (bs != NULL && BSLen (bs) < 1) {
5236 bs = BSFree (bs);
5237 }
5238 if (bs == NULL) return FALSE;
5239
5240 /* overlap turned into replacement sequence */
5241
5242 oldbsp = udp->oldbsp;
5243 newbsp = udp->newbsp;
5244 newbsp->seq_data = SeqDataFree (newbsp->seq_data, newbsp->seq_data_type);
5245 newbsp->seq_data = (SeqDataPtr) bs;
5246 newbsp->seq_data_type = Seq_code_iupacna;
5247 newbsp->length = newlen;
5248
5249 /* no offset, but ExtendFeatures finishes switch */
5250
5251 return ExtendFeatures (udp, 0);
5252 }
5253
5254 static Boolean ExtendOneSequence (UpsDataPtr udp)
5255 {
5256 Boolean update = FALSE;
5257 MsgAnswer ans;
5258 Uint2 entityID;
5259 CharPtr errmsg = NULL;
5260
5261
5262 if (udp == NULL) return FALSE;
5263
5264 switch (udp->rmcval) {
5265 case UPDATE_REPLACE :
5266 if (udp->old5 > 0 && udp->old3 > 0) {
5267 errmsg = "Unaligned sequence at 5' and 3' ends. Do you wish to proceed?";
5268 } else if (udp->old5 > 0) {
5269 errmsg = "Unaligned sequence at 5' end. Do you wish to proceed?";
5270 } else if (udp->old3 > 0) {
5271 errmsg = "Unaligned sequence at 3' end. Do you wish to proceed?";
5272 }
5273 break;
5274 case UPDATE_EXTEND5 :
5275 if (udp->old5 > 0) {
5276 errmsg = "Unaligned sequence at 5' end. Do you wish to proceed?";
5277 }
5278 break;
5279 case UPDATE_EXTEND3 :
5280 if (udp->old3 > 0) {
5281 errmsg = "Unaligned sequence at 3' end. Do you wish to proceed?";
5282 }
5283 break;
5284 default :
5285 break;
5286 }
5287 if (errmsg != NULL) {
5288 ans = Message (MSG_YN, "%s", errmsg);
5289 if (ans == ANS_NO) {
5290 return FALSE;
5291 }
5292 }
5293
5294 switch (udp->rmcval) {
5295 case UPDATE_REPLACE :
5296 if (ExtendBothEnds (udp)) {
5297 update = TRUE;
5298 }
5299 break;
5300 case UPDATE_EXTEND5:
5301 if (udp->salp == NULL) {
5302 if (Merge5PrimeNoOverlap (udp)) {
5303 update = TRUE;
5304 }
5305 } else if (Extend5Prime (udp)) {
5306 update = TRUE;
5307 }
5308 break;
5309 case UPDATE_EXTEND3 :
5310 if (udp->salp == NULL) {
5311 if (Merge3PrimeNoOverlap (udp)) {
5312 update = TRUE;
5313 }
5314 } else if (Extend3Prime (udp)) {
5315 update = TRUE;
5316 }
5317 break;
5318 default :
5319 break;
5320 }
5321
5322 if (update) {
5323
5324 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
5325 if (GetStatus (udp->add_cit_subs))
5326 {
5327 AddCitSubToUpdatedSequence ( udp->oldbsp, entityID, kSubmitterUpdateText);
5328 }
5329 }
5330 return update;
5331 }
5332
5333 static void OpenSequenceUpdateLog (UpsDataPtr udp)
5334 {
5335 if (udp == NULL || udp->log_fp != NULL)
5336 {
5337 return;
5338 }
5339 TmpNam (udp->log_path);
5340 udp->log_fp = FileOpen (udp->log_path, "wb");
5341 }
5342
5343 static void CloseOutSequenceUpdateLog (UpsDataPtr udp)
5344 {
5345 if (udp == NULL || udp->log_fp == NULL)
5346 {
5347 return;
5348 }
5349 FileClose (udp->log_fp);
5350 udp->log_fp = NULL;
5351 if (udp->data_in_log) {
5352 LaunchGeneralTextViewer (udp->log_path, "Protein changes");
5353 udp->data_in_log = FALSE;
5354 }
5355 FileRemove (udp->log_path);
5356 }
5357
5358
5359 static Boolean PrepareToUpdateSequences (UpsDataPtr udp);
5360 static Boolean PrepareUpdatePtr (UpsDataPtr udp);
5361 static ForM UpdateSequenceForm (UpsDataPtr udp);
5362 static void UpdateOneSequence (
5363 UpsDataPtr udp,
5364 Int2 sfbval,
5365 Boolean add_cit_subs,
5366 Boolean update_proteins);
5367
5368
5369 static Int4 FindNewCDSStop (SeqLocPtr slp, BioseqPtr bsp, Int4 prot_len)
5370 {
5371 Int4 loc_len, tot_len = 0;
5372 SeqLocPtr this_slp;
5373 Int4 curr_start;
5374
5375 for (this_slp = SeqLocFindNext (slp, NULL);
5376 this_slp != NULL;
5377 this_slp = SeqLocFindNext (slp, this_slp))
5378 {
5379 loc_len = SeqLocLen (this_slp);
5380 curr_start = GetOffsetInBioseq (this_slp, bsp, SEQLOC_START);
5381 if (loc_len + tot_len > prot_len)
5382 {
5383 curr_start = GetOffsetInBioseq (this_slp, bsp, SEQLOC_START);
5384 if (SeqLocStrand (this_slp) == Seq_strand_minus)
5385 {
5386 return curr_start - (prot_len - tot_len) + 1;
5387 }
5388 else
5389 {
5390 return curr_start + prot_len - tot_len - 1;
5391 }
5392 }
5393 tot_len += loc_len;
5394 }
5395 return tot_len;
5396 }
5397
5398
5399 static CharPtr FixProteinString
5400 (SeqFeatPtr sfp,
5401 Uint1 strand,
5402 Boolean truncate_proteins,
5403 Boolean PNTR truncated,
5404 Boolean PNTR contains_start,
5405 Boolean PNTR contains_stop)
5406 {
5407 ByteStorePtr bs;
5408 BioseqPtr nucBsp;
5409 CharPtr newprot;
5410 CharPtr ptr;
5411 Char ch;
5412 Int4 start, stop, new_stop, prot_len;
5413 Boolean changed;
5414 CdRegionPtr crp;
5415
5416 if (sfp == NULL || truncated == NULL
5417 || contains_start == NULL
5418 || contains_stop == NULL) {
5419 return NULL;
5420 }
5421
5422 bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
5423 if (bs == NULL) return NULL;
5424 newprot = BSMerge (bs, NULL);
5425 bs = BSFree (bs);
5426 if (newprot == NULL) return NULL;
5427
5428 ptr = newprot;
5429 ch = *ptr;
5430 if (ch == 'M') {
5431 *contains_start = TRUE;
5432 } else {
5433 *contains_start = FALSE;
5434 }
5435 *contains_stop = FALSE;
5436 *truncated = FALSE;
5437 while (ch != '\0')
5438 {
5439 *ptr = TO_UPPER (ch);
5440 if (ch == '*') {
5441 *contains_stop = TRUE;
5442 if (*(ptr + 1) == 0 || truncate_proteins) {
5443 *ptr = 0;
5444 if (truncate_proteins && *(ptr + 1) != 0) {
5445 *truncated = TRUE;
5446 nucBsp = BioseqFindFromSeqLoc (sfp->location);
5447 if (nucBsp == NULL) return newprot;
5448 start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5449 stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5450 prot_len = (1 + ptr - newprot) * 3;
5451 if (sfp->data.choice == SEQFEAT_CDREGION) {
5452 crp = (CdRegionPtr) sfp->data.value.ptrvalue;
5453 if (crp != NULL) {
5454 if (crp->frame == 2) {
5455 prot_len += 1;
5456 } else if (crp->frame == 3) {
5457 prot_len += 2;
5458 }
5459 }
5460 }
5461 new_stop = FindNewCDSStop (sfp->location, nucBsp, prot_len);
5462 if (strand == Seq_strand_minus) {
5463 sfp->location = SeqLocDelete (sfp->location, SeqLocId (sfp->location),
5464 stop, new_stop - 1, FALSE, &changed);
5465 } else {
5466 sfp->location = SeqLocDelete (sfp->location, SeqLocId (sfp->location),
5467 new_stop + 1, stop, FALSE, &changed);
5468 }
5469 }
5470 return newprot;
5471 }
5472 }
5473 ptr++;
5474 ch = *ptr;
5475 }
5476 return newprot;
5477 }
5478
5479 /* This function will truncate base pairs to make the length of the CDS
5480 * a multiple of three. If truncation occurs, the function returns TRUE,
5481 * otherwise the function returns FALSE.
5482 */
5483 static SeqLocPtr ShiftStopForLengthChange
5484 (SeqLocPtr slp,
5485 BioseqPtr nucBsp,
5486 Int4 transl_except_len,
5487 Boolean PNTR changed)
5488 {
5489 Int4 start, stop, new_stop;
5490 Uint1 strand;
5491 SeqIdPtr sip;
5492 Int4 len;
5493
5494 if (slp == NULL || nucBsp == NULL || changed == NULL) {
5495 return NULL;
5496 }
5497
5498 *changed = FALSE;
5499
5500 start = GetOffsetInBioseq (slp, nucBsp, SEQLOC_START);
5501 stop = GetOffsetInBioseq (slp, nucBsp, SEQLOC_STOP);
5502 new_stop = stop;
5503 strand = SeqLocStrand (slp);
5504 len = SeqLocLen (slp);
5505
5506 if (strand == Seq_strand_minus) {
5507 if (len % 3 != transl_except_len) {
5508 new_stop += len % 3 + transl_except_len;
5509 sip = SeqLocId (slp);
5510 slp = SeqLocDelete (slp, sip, stop, new_stop - 1, FALSE, changed);
5511 if (slp == NULL) {
5512 return NULL;
5513 }
5514 }
5515 } else {
5516 if (len % 3 != transl_except_len) {
5517 new_stop -= len % 3 - transl_except_len;
5518 sip = SeqLocId (slp);
5519 slp = SeqLocDelete (slp, sip, new_stop + 1, stop, FALSE, changed);
5520 if (slp == NULL) {
5521 return NULL;
5522 }
5523 }
5524 }
5525 return slp;
5526 }
5527
5528 extern SeqLocPtr
5529 ExpandSeqLoc
5530 (Int4 start,
5531 Int4 stop,
5532 Uint1 strand,
5533 BioseqPtr bsp,
5534 SeqLocPtr slp)
5535 {
5536 Int4 curr_start, curr_stop, tmp_start, tmp_stop;
5537 SeqLocPtr this_slp;
5538
5539 if (slp == NULL) return NULL;
5540
5541 if (slp->choice == SEQLOC_INT || slp->choice == SEQLOC_PNT) {
5542 slp = expand_seq_loc (start, stop, strand, slp);
5543 } else {
5544 curr_start = GetOffsetInBioseq (slp, bsp, SEQLOC_START);
5545 curr_stop = GetOffsetInBioseq (slp, bsp, SEQLOC_STOP);
5546 for (this_slp = SeqLocFindNext (slp, NULL);
5547 this_slp != NULL;
5548 this_slp = SeqLocFindNext (slp, this_slp))
5549 {
5550 tmp_start = GetOffsetInBioseq (this_slp, bsp, SEQLOC_START);
5551 tmp_stop = GetOffsetInBioseq (this_slp, bsp, SEQLOC_STOP);
5552 if (strand == Seq_strand_minus) {
5553 if (tmp_start == curr_start && tmp_start < stop) {
5554 this_slp = expand_seq_loc (tmp_stop, stop, strand, this_slp);
5555 tmp_start = stop;
5556 }
5557 if (tmp_stop == curr_stop && tmp_stop > start) {
5558 this_slp = expand_seq_loc (start, tmp_start, strand, this_slp);
5559 }
5560 } else {
5561 if (tmp_start == curr_start && tmp_start > start) {
5562 this_slp = expand_seq_loc (start, tmp_stop, strand, this_slp);
5563 tmp_start = start;
5564 }
5565 if (tmp_stop == curr_stop && tmp_stop < stop) {
5566 this_slp = expand_seq_loc (tmp_start, stop, strand, this_slp);
5567 }
5568 }
5569 }
5570 }
5571 return slp;
5572 }
5573
5574 static SeqLocPtr ShiftLocationForFrame
5575 (SeqLocPtr slp,
5576 Uint1 frame,
5577 BioseqPtr nucBsp)
5578 {
5579 Int4 max_stop, start, stop;
5580 Uint1 strand;
5581 SeqIdPtr sip;
5582 Int4 offset, new_start;
5583 Boolean changed;
5584
5585
5586 if (slp == NULL || nucBsp == NULL) return NULL;
5587 if (frame == 0 || frame == 1) return slp;
5588
5589 start = GetOffsetInBioseq (slp, nucBsp, SEQLOC_START);
5590 stop = GetOffsetInBioseq (slp, nucBsp, SEQLOC_STOP);
5591 strand = SeqLocStrand (slp);
5592 max_stop = nucBsp->length - 1;
5593 new_start = start;
5594
5595 offset = frame - 1;
5596 sip = SeqLocId (slp);
5597 if (strand == Seq_strand_minus) {
5598 stop -= offset;
5599 new_start = start - offset;
5600 if ((1 + new_start - stop ) % 3 != 0) {
5601 new_start -= (1 + new_start - stop) % 3;
5602 }
5603 if (stop < 0) stop = 0;
5604 slp = ExpandSeqLoc (stop, start, strand, nucBsp, slp);
5605 if (new_start < 0) new_start = 0;
5606 if (new_start < start) {
5607 slp = SeqLocDelete (slp, sip, new_start + 1, start, FALSE, &changed);
5608 }
5609 } else {
5610 stop += offset;
5611 new_start = start + offset;
5612 if ((1 + stop - new_start) % 3 != 0) {
5613 new_start += (1 + stop - new_start) % 3;
5614 }
5615 if (stop > max_stop) stop = max_stop;
5616 slp = ExpandSeqLoc (start, stop, strand, nucBsp, slp);
5617 if (start > max_stop) start = max_stop;
5618 if (new_start > start) {
5619 slp = SeqLocDelete (slp, sip, start, new_start - 1, FALSE, &changed);
5620 }
5621 }
5622 return slp;
5623 }
5624
5625 static TransTablePtr GetTranslationTable (CdRegionPtr crp, Boolean PNTR table_is_local)
5626 {
5627 TransTablePtr tbl = NULL;
5628 ValNodePtr vnp;
5629 Int2 genCode = 0;
5630 Char str [32];
5631
5632 if (crp == NULL || table_is_local == NULL) return NULL;
5633
5634 *table_is_local = FALSE;
5635 /* find genetic code */
5636
5637 if (crp->genetic_code != NULL) {
5638 vnp = (ValNodePtr) crp->genetic_code->data.ptrvalue;
5639 while (vnp != NULL) {
5640 if (vnp->choice == 2) {
5641 genCode = (Int2) vnp->data.intvalue;
5642 }
5643 vnp = vnp->next;
5644 }
5645 }
5646
5647 if (genCode == 7) {
5648 genCode = 4;
5649 } else if (genCode == 8) {
5650 genCode = 1;
5651 } else if (genCode == 0) {
5652 genCode = 1;
5653 }
5654
5655 /* set up translation table */
5656 /* set app property name for storing desired FSA */
5657
5658 sprintf (str, "TransTableFSAforGenCode%d", (int) genCode);
5659
5660 /* get FSA for desired genetic code if it already exists */
5661
5662 tbl = (TransTablePtr) GetAppProperty (str);
5663 if (tbl == NULL) {
5664 tbl = TransTableNew (genCode);
5665 *table_is_local = TRUE;
5666 }
5667 return tbl;
5668 }
5669
5670 static CharPtr ExtendProtein5
5671 (SeqFeatPtr sfp,
5672 Uint2 input_entityID,
5673 Boolean force_partial)
5674 {
5675 CdRegionPtr crp;
5676 TransTablePtr tbl = NULL;
5677 Boolean table_is_local = FALSE;
5678 SeqLocPtr test_slp;
5679 SeqIdPtr sip;
5680 BioseqPtr nucBsp;
5681 Int4 start, new_start;
5682 Int4 stop, new_stop;
5683 Int4 increment = 3000;
5684 Int4 offset;
5685 Uint1 strand;
5686 Boolean found_start = FALSE;
5687 Boolean found_stop = FALSE;
5688 Boolean stop_looking = FALSE;
5689 Int4 dna_len;
5690 CharPtr bases;
5691 Int4 total;
5692 Int2 state;
5693 CharPtr codon_start;
5694 Boolean partial3, partial5;
5695 Boolean contains_start, contains_stop;
5696 Boolean changed;
5697 CharPtr newprot;
5698 Boolean truncated;
5699
5700 if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION
5701 || (crp = (CdRegionPtr)sfp->data.value.ptrvalue) == NULL) {
5702 return NULL;
5703 }
5704 nucBsp = GetBioseqGivenSeqLoc (sfp->location, input_entityID);
5705 if (nucBsp == NULL) return NULL;
5706
5707 tbl = GetTranslationTable (crp, &table_is_local);
5708 if (tbl == NULL) return NULL;
5709
5710 test_slp = SeqLocMerge (nucBsp, sfp->location, NULL, FALSE, FALSE, FALSE);
5711 strand = SeqLocStrand (sfp->location);
5712 sip = SeqLocId (sfp->location);
5713 offset = -1;
5714
5715 start = GetOffsetInBioseq (test_slp, nucBsp, SEQLOC_START);
5716 if (start == 0)
5717 {
5718 stop_looking = TRUE;
5719 }
5720
5721 while (((! found_start && ! found_stop) || force_partial) && ! stop_looking) {
5722 start = GetOffsetInBioseq (test_slp, nucBsp, SEQLOC_START);
5723 stop = GetOffsetInBioseq (test_slp, nucBsp, SEQLOC_STOP);
5724 if (strand == Seq_strand_minus) {
5725 new_start = start + increment;
5726 new_stop = start + 1;
5727 if (new_start > nucBsp->length - 1) {
5728 new_start = start + ((Int4)((nucBsp->length - 1 - start) / 3)) * 3;
5729 stop_looking = TRUE;
5730 }
5731 test_slp = ExpandSeqLoc (stop, new_start, strand, nucBsp, test_slp);
5732 test_slp = SeqLocDelete (test_slp, sip, stop, start, FALSE, &changed);
5733 } else {
5734 new_start = start - increment;
5735 new_stop = start - 1;
5736 if (new_start < 0) {
5737 new_start = start % 3;
5738 stop_looking = TRUE;
5739 }
5740 test_slp = ExpandSeqLoc (new_start, stop, strand, nucBsp, test_slp);
5741 test_slp = SeqLocDelete (test_slp, sip, start, stop, FALSE, &changed);
5742 }
5743 dna_len = SeqLocLen (test_slp);
5744 bases = ReadCodingRegionBases (test_slp, dna_len, crp->frame, &total);
5745 if (bases == NULL) {
5746 stop_looking = TRUE;
5747 } else {
5748 state = 0;
5749 codon_start = bases + StringLen (bases) - 3;
5750 while (codon_start >= bases && ! found_start && ! found_stop) {
5751 state = 0;
5752 state = NextCodonState (tbl, state, (Uint1)*codon_start);
5753 state = NextCodonState (tbl, state, (Uint1)*(codon_start + 1));
5754 state = NextCodonState (tbl, state, (Uint1)*(codon_start + 2));
5755 if (IsOrfStart (tbl, state, TTBL_TOP_STRAND)) {
5756 found_start = TRUE;
5757 if (strand == Seq_strand_minus) {
5758 offset = new_start - (codon_start - bases);
5759 } else {
5760 offset = new_start + codon_start - bases;
5761 }
5762 } else if (IsOrfStop (tbl, state, TTBL_TOP_STRAND)) {
5763 found_stop = TRUE;
5764 } else {
5765 codon_start -= 3;
5766 }
5767 }
5768 MemFree (bases);
5769 }
5770 }
5771
5772 SeqLocFree (test_slp);
5773 if (! found_stop) {
5774 start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5775 stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5776 if (found_start) {
5777 if (strand == Seq_strand_minus) {
5778 sfp->location = ExpandSeqLoc (stop, offset, strand, nucBsp, sfp->location);
5779 } else {
5780 sfp->location = ExpandSeqLoc (offset, stop, strand, nucBsp, sfp->location);
5781 }
5782 } else {
5783 CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5784 SetSeqLocPartial (sfp->location, TRUE, partial3);
5785 sfp->partial = TRUE;
5786 if (crp->frame == 0)
5787 {
5788 crp->frame = 1;
5789 }
5790 if (strand == Seq_strand_minus) {
5791 sfp->location = ExpandSeqLoc (stop, nucBsp->length - 1, strand, nucBsp, sfp->location);
5792 crp->frame = (nucBsp->length - 1 - start + crp->frame - 1) % 3 + 1;
5793 } else {
5794 sfp->location = ExpandSeqLoc (0, stop, strand, nucBsp, sfp->location);
5795 crp->frame = (start + crp->frame - 1) % 3 + 1;
5796 }
5797 }
5798 }
5799 newprot = FixProteinString (sfp, strand, FALSE, &truncated,
5800 &contains_start, &contains_stop);
5801 if (table_is_local) {
5802 TransTableFree (tbl);
5803 }
5804
5805 return newprot;
5806 }
5807
5808
5809 extern CharPtr ExtendProtein3
5810 (SeqFeatPtr sfp,
5811 Uint2 input_entityID,
5812 Boolean force_partial)
5813 {
5814 BioseqPtr nucBsp;
5815 Int4 max_stop, min_start, start, stop;
5816 Uint1 strand;
5817 Boolean contains_start, contains_stop;
5818 Int4 increment = 3000;
5819 CharPtr newprot;
5820 Boolean partial5, partial3;
5821 Boolean truncated;
5822
5823 if (sfp == NULL) return NULL;
5824
5825 nucBsp = GetBioseqGivenSeqLoc (sfp->location, input_entityID);
5826 if (nucBsp == NULL) return NULL;
5827
5828 CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5829 start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5830 stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5831 strand = SeqLocStrand (sfp->location);
5832 max_stop = nucBsp->length - 1;
5833 if (stop > start) {
5834 while (max_stop % 3 != stop % 3) {
5835 max_stop --;
5836 }
5837 min_start = start %3;
5838 } else {
5839 while (max_stop % 3 != start % 3) {
5840 max_stop --;
5841 }
5842 min_start = stop % 3;
5843 }
5844
5845 contains_stop = FALSE;
5846 contains_start = FALSE;
5847 newprot = NULL;
5848 /* need to initialize newprot in case we're already at the edge */
5849 if ((strand != Seq_strand_minus && stop == max_stop)
5850 || (strand == Seq_strand_minus && stop == min_start))
5851 {
5852 newprot = FixProteinString (sfp, strand, FALSE, &truncated,
5853 &contains_start, &contains_stop);
5854 }
5855 while ((! contains_stop || force_partial) &&
5856 ( (strand == Seq_strand_minus && stop > min_start)
5857 || (strand != Seq_strand_minus && stop < max_stop)))
5858 {
5859 if (newprot != NULL) {
5860 MemFree (newprot);
5861 newprot = NULL;
5862 }
5863 if (strand == Seq_strand_minus) {
5864 stop -= increment;
5865 if (stop < min_start) {
5866 stop = min_start;
5867 }
5868 sfp->location = ExpandSeqLoc (stop, start, strand, nucBsp, sfp->location);
5869 } else {
5870 stop += increment;
5871 if (stop > max_stop) {
5872 stop = max_stop;
5873 }
5874 sfp->location = ExpandSeqLoc (start, stop, strand, nucBsp, sfp->location);
5875 }
5876 newprot = FixProteinString (sfp, strand, TRUE, &truncated,
5877 &contains_start, &contains_stop);
5878 }
5879
5880 if (! contains_stop || force_partial) {
5881 start = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_START);
5882 stop = GetOffsetInBioseq (sfp->location, nucBsp, SEQLOC_STOP);
5883 if (strand == Seq_strand_minus) {
5884 sfp->location = ExpandSeqLoc (0, start, strand, nucBsp, sfp->location);
5885 } else {
5886 sfp->location = ExpandSeqLoc (start, nucBsp->length - 1, strand, nucBsp, sfp->location);
5887 }
5888 partial3 = TRUE;
5889 SetSeqLocPartial (sfp->location, partial5, TRUE);
5890 }
5891 return newprot;
5892 }
5893
5894 static Boolean MergeOverlapsForThisFeature (SeqFeatPtr sfp)
5895 {
5896 if (sfp == NULL) return FALSE;
5897 return ! sfp->excpt;
5898 }
5899
5900 static Boolean
5901 AdjustCDSForUpdate
5902 (SeqFeatPtr sfp,
5903 Uint2 input_entityID,
5904 Uint1 frame,
5905 Int4 transl_except_len,
5906 Boolean truncate_proteins,
5907 Boolean extend_proteins5,
5908 Boolean extend_proteins3,
5909 Boolean PNTR truncated,
5910 Boolean PNTR stop_shifted,
5911 Boolean PNTR extended5,
5912 Boolean PNTR extended3,
5913 BioseqPtr protBsp,
5914 BioseqPtr PNTR newbsp)
5915 {
5916 ByteStorePtr bs;
5917 CharPtr newprot, ptr;
5918 SeqEntryPtr nwsep;
5919 BioseqPtr newBsp;
5920 Boolean contains_start, contains_stop;
5921 Uint1 strand;
5922 SeqLocPtr newloc;
5923 BioseqPtr nucBsp;
5924 Boolean partial5, partial3;
5925 CharPtr seqnew = NULL, seqold = NULL;
5926 Boolean rval = FALSE;
5927
5928 if (sfp == NULL
5929 || sfp->idx.subtype != FEATDEF_CDS
5930 || sfp->product == NULL
5931 || protBsp == NULL
5932 || truncated == NULL || stop_shifted == NULL
5933 || extended5 == NULL || extended3 == NULL
5934 || newbsp == NULL)
5935 {
5936 return FALSE;
5937 }
5938
5939 CheckSeqLocForPartial (sfp->location, &partial3, &partial5);
5940
5941 nucBsp = GetBioseqGivenSeqLoc (sfp->location, input_entityID);
5942 if (nucBsp == NULL) return FALSE;
5943
5944 newloc = SeqLocMergeExEx (nucBsp, sfp->location, NULL, FALSE, FALSE,
5945 MergeOverlapsForThisFeature (sfp), FALSE, FALSE, FALSE);
5946
5947 if (newloc == NULL) return FALSE;
5948 sfp->location = newloc;
5949 strand = SeqLocStrand (sfp->location);
5950 sfp->location = ShiftStopForLengthChange (sfp->location, nucBsp, transl_except_len, stop_shifted);
5951 if (sfp->location == NULL) {
5952 return FALSE;
5953 }
5954
5955 sfp->location = ShiftLocationForFrame (sfp->location, frame, nucBsp);
5956
5957 newprot = FixProteinString (sfp, strand, truncate_proteins, truncated,
5958 &contains_start, &contains_stop);
5959
5960 /* Must do 3' end first, otherwise may truncate at stops introduced by expanding 5' end for partiality */
5961 if ((! contains_stop && extend_proteins3 && transl_except_len == 0)
5962 || ((extend_proteins3 || partial3) && !truncate_proteins)) {
5963 MemFree (newprot);
5964 newprot = ExtendProtein3 (sfp, input_entityID, partial3 && !truncate_proteins);
5965 if (newprot == NULL) return FALSE;
5966 *extended3 = TRUE;
5967 } else {
5968 *extended3 = FALSE;
5969 }
5970 if (! contains_start && (extend_proteins5 || partial5)) {
5971 MemFree (newprot);
5972 newprot = ExtendProtein5 (sfp, input_entityID, partial5);
5973 if (newprot == NULL) return FALSE;
5974 *extended5 = TRUE;
5975 } else {
5976 *extended5 = FALSE;
5977 }
5978
5979 sfp->partial = CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5980
5981 bs = BSNew (1000);
5982 if (bs != NULL)
5983 {
5984 ptr = newprot;
5985 BSWrite (bs, (VoidPtr) ptr, (Int4) StringLen (ptr));
5986 }
5987 MemFree (newprot);
5988
5989 newBsp = BioseqNew ();
5990 if (newBsp == NULL) {
5991 return FALSE;
5992 }
5993
5994 newBsp->id = SeqIdParse ("lcl|ProtAlign");
5995 newBsp->repr = Seq_repr_raw;
5996 newBsp->mol = Seq_mol_aa;
5997 newBsp->seq_data_type = Seq_code_ncbieaa;
5998 newBsp->seq_data = (SeqDataPtr) bs;
5999 newBsp->length = BSLen (bs);
6000
6001 /* create SeqEntry for temporary protein bioseq to live in */
6002 nwsep = SeqEntryNew ();
6003 nwsep->choice = 1;
6004 nwsep->data.ptrvalue = newBsp;
6005 SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) newBsp, nwsep);
6006
6007 seqold = GetSequenceByBsp (protBsp);
6008 seqnew = GetSequenceByBsp (newBsp);
6009
6010 if (StringCmp (seqold, seqnew) == 0
6011 || (contains_stop && ! *truncated
6012 && StringNCmp (seqold,
6013 seqnew,
6014 StringLen (seqold)) == 0))
6015 {
6016 SeqEntryFree (nwsep);
6017 rval = FALSE;
6018 }
6019 else
6020 {
6021 *newbsp = newBsp;
6022 rval = TRUE;
6023 }
6024
6025 return rval;
6026 }
6027
6028
6029 static void WarnNoProteinUpdate (BioseqPtr bsp)
6030 {
6031 Char acc_str [256];
6032 CharPtr warn_format = "Protein %s has not been updated - you must manually re-translate the coding regions and move any protein features";
6033 CharPtr warn_msg;
6034
6035 if (bsp == NULL || bsp->id == NULL) return;
6036 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
6037 warn_msg = (CharPtr) MemNew (StringLen (warn_format) + StringLen (acc_str));
6038 if (warn_msg == NULL) return;
6039 sprintf (warn_msg, warn_format, acc_str);
6040 ErrPostEx (SEV_ERROR, 0, 0, warn_msg);
6041 MemFree (warn_msg);
6042 }
6043
6044
6045 static void LogFrameChange (FILE *fp, BioseqPtr bsp, Uint1 frame)
6046 {
6047 Char acc_str [256];
6048
6049 if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
6050 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
6051 fprintf (fp, "Changed frame for %s to %d\n", acc_str, frame);
6052 }
6053
6054
6055 static void LogProteinTruncate (FILE *fp, BioseqPtr bsp)
6056 {
6057 Char acc_str [256];
6058
6059 if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
6060 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
6061 fprintf (fp, "Truncated protein %s at stop\n", acc_str);
6062 }
6063
6064
6065 static void LogProteinStopShift (FILE *fp, BioseqPtr bsp)
6066 {
6067 Char acc_str [256];
6068
6069 if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
6070 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
6071 fprintf (fp, "Adjusted length of CDS for protein %s to be multiple of 3\n", acc_str);
6072 }
6073
6074
6075 static void LogProteinExtend5 (FILE *fp, BioseqPtr bsp)
6076 {
6077 Char acc_str [256];
6078
6079 if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
6080 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
6081 fprintf (fp, "Extended protein %s on 5' end\n", acc_str);
6082 }
6083
6084
6085 static void LogProteinExtend3 (FILE *fp, BioseqPtr bsp)
6086 {
6087 Char acc_str [256];
6088
6089 if (fp == NULL || bsp == NULL || bsp->id == NULL) return;
6090 SeqIdWrite (bsp->id, acc_str, PRINTID_REPORT, sizeof (acc_str));
6091 fprintf (fp, "Extended protein %s on 3' end\n", acc_str);
6092 }
6093
6094 static void LogGeneCorrection (FILE *fp, SeqFeatPtr gene, SeqLocPtr oldloc)
6095 {
6096 CharPtr loc1, loc2;
6097 SeqMgrFeatContext gcontext;
6098 SeqFeatPtr found_gene;
6099
6100 if (fp == NULL || gene == NULL || gene->location == NULL || oldloc == NULL) return;
6101 found_gene = SeqMgrGetDesiredFeature (gene->idx.entityID, NULL, 0, 0, gene, &gcontext);
6102 if (found_gene == NULL) return;
6103 loc1 = SeqLocPrint (gene->location);
6104 loc2 = SeqLocPrint (oldloc);
6105 if (loc1 != NULL && loc2 != NULL && StringCmp (loc1, loc2) != 0) {
6106 fprintf (fp, "Moved gene %s from %s to %s\n", gcontext.label, loc2, loc1);
6107 }
6108 MemFree (loc1);
6109 MemFree (loc2);
6110 }
6111
6112
6113 static void LogGeneBadCorrection (FILE *fp, SeqFeatPtr gene)
6114 {
6115 SeqMgrFeatContext gcontext;
6116 SeqFeatPtr found_gene;
6117
6118 if (fp == NULL || gene == NULL || gene->location == NULL) return;
6119 found_gene = SeqMgrGetDesiredFeature (gene->idx.entityID, NULL, 0, 0, gene, &gcontext);
6120 if (found_gene == NULL) return;
6121 fprintf (fp, "Please examine gene %s, new gene may be too large\n", gcontext.label);
6122 }
6123
6124
6125 static void CorrectCDSGene
6126 (SeqFeatPtr sfp,
6127 SeqFeatPtr gene_sfp,
6128 FILE *fp,
6129 Boolean PNTR data_in_log)
6130 {
6131 BioseqPtr bsp;
6132 Boolean partial5, partial3;
6133 SeqLocPtr log_slp, new_slp;
6134 Int2 res;
6135
6136 if (sfp == NULL || gene_sfp == NULL || fp == NULL
6137 || data_in_log == NULL){
6138 return;
6139 }
6140 bsp = BioseqFindFromSeqLoc (sfp->location);
6141 if (bsp == NULL) return;
6142 new_slp = SeqLocMerge (bsp, sfp->location, NULL, TRUE, FALSE, FALSE);
6143 res = SeqLocCompare (gene_sfp->location, new_slp);
6144 if (res == SLC_A_EQ_B) {
6145 SeqLocFree (new_slp);
6146 return;
6147 }
6148 if (SeqLocLen (gene_sfp->location) > SeqLocLen (new_slp)) {
6149 SeqLocFree (new_slp);
6150 new_slp = SeqLocMerge (bsp, sfp->location, gene_sfp->location, TRUE, FALSE, FALSE);
6151 LogGeneBadCorrection (fp, gene_sfp);
6152 }
6153 log_slp = SeqLocMerge (bsp, sfp->location, NULL, FALSE, FALSE, FALSE);
6154
6155 *data_in_log = TRUE;
6156 SeqLocFree (gene_sfp->location);
6157 gene_sfp->location = new_slp;
6158 CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
6159 SetSeqLocPartial (gene_sfp->location, partial5, partial3);
6160 gene_sfp->partial = sfp->partial;
6161 LogGeneCorrection (fp, gene_sfp, log_slp);
6162 SeqLocFree (log_slp);
6163 }
6164
6165 static void FixProtRefPtrs (ValNodePtr feat_list)
6166 {
6167 ValNodePtr vnp;
6168 SeqFeatPtr sfp;
6169 Uint1 strand;
6170 BioseqPtr bsp;
6171
6172 if (feat_list == NULL) return;
6173 for (vnp = feat_list; vnp != NULL; vnp = vnp->next) {
6174 sfp = (SeqFeatPtr)vnp->data.ptrvalue;
6175 if (sfp == NULL) continue;
6176 bsp = BioseqFindFromSeqLoc (sfp->location);
6177 if (bsp == NULL) continue;
6178 strand = SeqLocStrand (sfp->location);
6179 if (strand == Seq_strand_minus) {
6180 sfp->location = ExpandSeqLoc (bsp->length - 1, 0, strand, bsp, sfp->location);
6181 } else {
6182 sfp->location = ExpandSeqLoc (0, bsp->length - 1, strand, bsp, sfp->location);
6183 }
6184 }
6185 }
6186
6187
6188 static Boolean PrepareUpdateAlignmentForProtein
6189 (SeqFeatPtr sfp,
6190 BioseqPtr protBsp,
6191 Uint2 input_entityID,
6192 FILE * fp,
6193 Boolean truncate_proteins,
6194 Boolean extend_proteins5,
6195 Boolean extend_proteins3,
6196 Boolean correct_cds_genes,
6197 Int4 transl_except_len,
6198 Boolean *data_in_log,
6199 SeqAlignPtr PNTR salpptr,
6200 BioseqPtr PNTR newbspptr)
6201 {
6202 Boolean align_succeeded;
6203 Boolean changed_frame;
6204 Uint1 frame_attempts;
6205 ErrSev level;
6206 CdRegionPtr crp;
6207 SeqLocPtr orig_slp;
6208 Boolean orig_partial;
6209 SeqFeatPtr gene_sfp;
6210 SeqMgrFeatContext gcontext;
6211 Boolean truncated, stop_shifted;
6212 Boolean extended5, extended3;
6213 Uint1 old_frame;
6214 BioseqPtr newBsp = NULL;
6215 Boolean adjust_succeeded;
6216 SeqAlignPtr salp = NULL;
6217 Boolean revcomp;
6218
6219 if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION
6220 || (crp = (CdRegionPtr)sfp->data.value.ptrvalue) == NULL
6221 || protBsp == NULL
6222 || data_in_log == NULL) {
6223 return FALSE;
6224 }
6225
6226 old_frame = crp->frame;
6227
6228 orig_slp = sfp->location;
6229 orig_partial = sfp->partial;
6230 if (correct_cds_genes) {
6231 gene_sfp = SeqMgrGetOverlappingGene (sfp->location, &gcontext);
6232 }
6233 align_succeeded = FALSE;
6234 changed_frame = FALSE;
6235
6236 level = ErrSetMessageLevel (SEV_MAX);
6237 for (frame_attempts = 1;
6238 frame_attempts < 4 && ! align_succeeded;
6239 frame_attempts ++) {
6240 if (sfp->location != orig_slp) {
6241 if (sfp->location->choice == 0) {
6242 SeqLocFree (sfp->location);
6243 }
6244 sfp->location = orig_slp;
6245 }
6246 sfp->partial = orig_partial;
6247 crp->frame = old_frame;
6248 if (newBsp != NULL) {
6249 newBsp = BioseqFree (newBsp);
6250 }
6251 truncated= FALSE;
6252 stop_shifted = FALSE;
6253 extended5 = FALSE;
6254 extended3 = FALSE;
6255 adjust_succeeded = AdjustCDSForUpdate (sfp,
6256 input_entityID,
6257 frame_attempts,
6258 transl_except_len,
6259 truncate_proteins,
6260 extend_proteins5,
6261 extend_proteins3,
6262 &truncated, &stop_shifted,
6263 &extended5, &extended3,
6264 protBsp, &newBsp);
6265 if (sfp->location == NULL || sfp->location->choice == 0)
6266 {
6267 sfp->location = orig_slp;
6268 }
6269 if (adjust_succeeded)
6270 {
6271 salp = Sequin_GlobalAlign2Seq (protBsp, newBsp, &revcomp);
6272 }
6273 if (!adjust_succeeded || salp != NULL)
6274 {
6275 if (frame_attempts > 1) {
6276 changed_frame = TRUE;
6277 LogFrameChange (fp, protBsp, frame_attempts);
6278 *data_in_log = TRUE;
6279 }
6280 break;
6281 }
6282 }
6283 ErrSetMessageLevel (level);
6284 if (adjust_succeeded && salp == NULL)
6285 {
6286 /* put CD Region back to original state */
6287 crp->frame = old_frame;
6288 if (sfp->location != orig_slp) {
6289 SeqLocFree (sfp->location);
6290 sfp->location = orig_slp;
6291 }
6292 sfp->partial = orig_partial;
6293 WarnNoProteinUpdate (protBsp);
6294 newBsp = BioseqFree (newBsp);
6295 return FALSE;
6296 }
6297
6298 if (truncated) {
6299 LogProteinTruncate (fp, protBsp);
6300 *data_in_log = TRUE;
6301 }
6302 if (stop_shifted) {
6303 LogProteinStopShift (fp, protBsp);
6304 *data_in_log = TRUE;
6305 }
6306 if (extended5) {
6307 LogProteinExtend5 (fp, protBsp);
6308 *data_in_log = TRUE;
6309 }
6310 if (extended3) {
6311 LogProteinExtend3 (fp, protBsp);
6312 *data_in_log = TRUE;
6313 }
6314
6315 if (correct_cds_genes && gene_sfp != NULL) {
6316 CorrectCDSGene (sfp, gene_sfp, fp, data_in_log);
6317 }
6318 if (sfp->location != orig_slp) {
6319 SeqLocFree (orig_slp);
6320 }
6321
6322 *salpptr = salp;
6323 *newbspptr = newBsp;
6324 return TRUE;
6325 }
6326
6327
6328 typedef struct proteinfromcdsdata {
6329 Uint2 input_entityID;
6330 Uint4 input_itemID;
6331 Uint4 input_itemtype;
6332 FILE * fp;
6333 Boolean data_to_report;
6334 } ProteinFromCDSData, PNTR ProteinFromCDSPtr;
6335
6336 static void UpdateOneProteinFromCDS (SeqFeatPtr sfp, Pointer userdata)
6337 {
6338 ProteinFromCDSPtr pfcp;
6339 SeqLocPtr new_product;
6340 Boolean data_in_log;
6341 Int4 transl_except_len = 0;
6342 BioseqPtr protBsp;
6343 SeqAlignPtr salp = NULL;
6344 BioseqPtr newbsp = NULL;
6345 Boolean rval;
6346
6347 pfcp = (ProteinFromCDSPtr) userdata;
6348 if ( pfcp == NULL
6349 || sfp == NULL
6350 || sfp->idx.subtype != FEATDEF_CDS
6351 || sfp->product == NULL)
6352 {
6353 return;
6354 }
6355
6356 protBsp = BioseqFindFromSeqLoc (sfp->product);
6357 if (protBsp == NULL)
6358 {
6359 return;
6360 }
6361
6362 data_in_log = FALSE;
6363
6364 if (CodingRegionHasTranslExcept(sfp))
6365 {
6366 transl_except_len = SeqLocLen (sfp->location) % 3;
6367 }
6368
6369 rval = PrepareUpdateAlignmentForProtein (sfp,
6370 protBsp,
6371 pfcp->input_entityID,
6372 pfcp->fp,
6373 TRUE, TRUE, TRUE, TRUE,
6374 transl_except_len,
6375 &data_in_log,
6376 &salp,
6377 &newbsp);
6378 if (data_in_log) {
6379 pfcp->data_to_report = TRUE;
6380 }
6381 if (!rval) return;
6382
6383 ReplaceOneSequence (salp, protBsp, newbsp);
6384 if (sfp->product->choice != SEQLOC_WHOLE)
6385 {
6386 new_product = SeqLocWholeNew (protBsp);
6387 if (new_product == NULL) return;
6388 SeqLocFree (sfp->product);
6389 sfp->product = new_product;
6390 }
6391 }
6392
6393 static Boolean CheckForIDCollision (
6394 BioseqPtr oldbsp,
6395 BioseqPtr newbsp,
6396 BoolPtr islocal
6397 )
6398
6399 {
6400 SeqIdPtr sip;
6401
6402 if (oldbsp == NULL || newbsp == NULL) return FALSE;
6403 for (sip = newbsp->id; sip != NULL; sip = sip->next) {
6404 if (SeqIdIn (sip, oldbsp->id)) {
6405 if (sip->choice == SEQID_LOCAL) {
6406 *islocal = TRUE;
6407 }
6408 return TRUE;
6409 }
6410 }
6411 return FALSE;
6412 }
6413
6414 static CharPtr convPubDescMssg =
6415 "Do you wish to convert publications to apply only to the appropriate ranges?";
6416
6417 #define UPDATE_SKIP_THIS 1
6418 #define UPDATE_SKIP_ALL 2
6419 #define UPDATE_REPLACE_THIS 3
6420 #define UPDATE_REPLACE_ALL 4
6421 #define UPDATE_CANCEL 5
6422
6423 typedef struct noalignmentchoice
6424 {
6425 Boolean done;
6426 Boolean cancelled;
6427 GrouP action_choice;
6428 Boolean skip_this;
6429 Boolean skip_all;
6430 Boolean replace_this;
6431 Boolean replace_all;
6432 } NoAlignmentChoiceData, PNTR NoAlignmentChoicePtr;
6433
6434 static void NoAlignmentChoiceOk (ButtoN b)
6435 {
6436 NoAlignmentChoicePtr nacp;
6437
6438 nacp = (NoAlignmentChoicePtr) GetObjectExtra (b);
6439 if (nacp == NULL) return;
6440 nacp->cancelled = FALSE;
6441 nacp->done = TRUE;
6442 }
6443
6444 static void NoAlignmentChoiceCancel (ButtoN b)
6445 {
6446 NoAlignmentChoicePtr nacp;
6447
6448 nacp = (NoAlignmentChoicePtr) GetObjectExtra (b);
6449 if (nacp == NULL) return;
6450 nacp->cancelled = TRUE;
6451 nacp->done = TRUE;
6452 }
6453
6454 static Int2 GetNoAlignmentChoice (SeqIdPtr id, Int2 previous_choice)
6455 {
6456 Char buf [64];
6457 WindoW w;
6458 GrouP h, g, c;
6459 ButtoN b;
6460 NoAlignmentChoiceData nacd;
6461 Char promptstr[115];
6462 Int2 no_aln_choice;
6463 SeqIdPtr sip, sip_next;
6464
6465 sip = SeqIdFindBest (id, 0);
6466 if (sip == NULL) return UPDATE_CANCEL;
6467 w = ModalWindow(-20, -13, -10, -10, NULL);
6468 if (w == NULL) return 0;
6469
6470 h = HiddenGroup (w, -1, 0, NULL);
6471 g = HiddenGroup(h, 0, 4, NULL);
6472 sip_next = sip->next;
6473 sip->next = NULL;
6474 SeqIdWrite (sip, buf, PRINTID_REPORT, sizeof (buf) - 1);
6475 sip->next = sip_next;
6476 sprintf (promptstr, "There is no alignment between the sequences for %s.", buf);
6477 StaticPrompt (g, promptstr, 0, popupMenuHeight, programFont, 'l');
6478 StaticPrompt (g, "You may choose to :", 0, popupMenuHeight, programFont, 'l');
6479 nacd.action_choice = HiddenGroup (g, 0, 4, NULL);
6480 RadioButton (nacd.action_choice, "Skip This Sequence");
6481 RadioButton (nacd.action_choice, "Skip All Sequences without Alignments");
6482 RadioButton (nacd.action_choice, "Replace This Sequence");
6483 RadioButton (nacd.action_choice, "Replace All Sequences without Alignments");
6484 if (previous_choice > 0 && previous_choice < UPDATE_CANCEL)
6485 {
6486 SetValue (nacd.action_choice, previous_choice);
6487 }
6488 else
6489 {
6490 SetValue (nacd.action_choice, 1);
6491 }
6492 c = HiddenGroup (h, 2, 0, NULL);
6493 b = PushButton (c, "Ok", NoAlignmentChoiceOk);
6494 SetObjectExtra (b, &nacd, NULL);
6495 b = PushButton (c, "Cancel", NoAlignmentChoiceCancel);
6496 SetObjectExtra (b, &nacd, NULL);
6497
6498 AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
6499
6500 nacd.cancelled = FALSE;
6501 nacd.done = FALSE;
6502 Show(w);
6503 Select (w);
6504 while (!nacd.done)
6505 {
6506 ProcessExternalEvent ();
6507 Update ();
6508 }
6509 ProcessAnEvent ();
6510 no_aln_choice = GetValue (nacd.action_choice);
6511 Remove (w);
6512 if (nacd.cancelled)
6513 {
6514 return UPDATE_CANCEL;
6515 }
6516 else
6517 {
6518 return no_aln_choice;
6519 }
6520 }
6521
6522 static Boolean PrepareUpdatePtr (UpsDataPtr udp)
6523 {
6524 Uint2 entityID;
6525 SeqEntryPtr oldsep, newsep;
6526 SeqIdPtr sip;
6527 Boolean islocal = FALSE;
6528 Char buf [64];
6529 SeqAlignPtr salp = NULL;
6530 Boolean revcomp = FALSE;
6531 Boolean asked_about_desc_prop = FALSE;
6532 Boolean propagate_descriptors = FALSE;
6533 SeqIdPtr id, id_next;
6534 MsgAnswer ans;
6535 Char collision_id [100];
6536
6537 if (udp->oldbsp == NULL || udp->newbsp == NULL) return FALSE;
6538 if (ISA_na (udp->oldbsp->mol) != ISA_na (udp->newbsp->mol)) {
6539 Message (MSG_OK, "Both sequences must be either nucleotides or proteins");
6540 return FALSE;
6541 }
6542
6543 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
6544 oldsep = GetBestTopParentForData (entityID, udp->oldbsp);
6545 entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
6546 newsep = GetBestTopParentForData (entityID, udp->newbsp);
6547 if (oldsep == NULL || newsep == NULL)
6548 return FALSE;
6549
6550 if (CONVERTPUBS_NOT_SET == udp->convertPubs)
6551 {
6552 if (Message (MSG_YN, convPubDescMssg) == ANS_YES) {
6553 ConvertPubSrcComDescsToFeats (oldsep, TRUE, FALSE, FALSE, FALSE, &asked_about_desc_prop, &propagate_descriptors, NULL);
6554 ConvertPubSrcComDescsToFeats (newsep, TRUE, FALSE, FALSE, FALSE, &asked_about_desc_prop, &propagate_descriptors, NULL);
6555 udp->convertPubs = CONVERTPUBS_YES;
6556 }
6557 else
6558 udp->convertPubs = CONVERTPUBS_NO;
6559 }
6560
6561 if (CheckForIDCollision (udp->oldbsp, udp->newbsp, &islocal)) {
6562 sprintf (collision_id, "lcl|SequinUpdateSequence%d", udp->seqsubpos);
6563 sip = SeqIdParse (collision_id);
6564 if (sip != NULL) {
6565 BioseqReplaceID (udp->newbsp, sip);
6566 sip = SeqIdFree (sip);
6567 }
6568 }
6569
6570 salp = Sequin_GlobalAlign2Seq (udp->oldbsp, udp->newbsp, &revcomp);
6571
6572 if (salp == NULL) {
6573 if (udp->log_fp != NULL) {
6574 id = SeqIdFindBest (udp->oldbsp->id, 0);
6575 if (id != NULL)
6576 {
6577 id_next = id->next;
6578 id->next = NULL;
6579 SeqIdWrite (id, buf, PRINTID_REPORT, sizeof (buf) - 1);
6580 id->next = id_next;
6581 fprintf (udp->log_fp, "No sequence similarity for %s\n", buf);
6582 udp->data_in_log = TRUE;
6583 }
6584 }
6585 if (udp->suppress_continue_msg) {
6586 return FALSE;
6587 } else {
6588 if (udp->isSet && udp->do_update)
6589 {
6590 if (udp->no_aln_choice != UPDATE_SKIP_ALL && udp->no_aln_choice != UPDATE_REPLACE_ALL)
6591 {
6592 udp->no_aln_choice = GetNoAlignmentChoice (udp->oldbsp->id, udp->no_aln_choice);
6593 }
6594 if (udp->no_aln_choice == UPDATE_CANCEL)
6595 {
6596 return FALSE;
6597 }
6598 }
6599 else if (udp->do_update)
6600 {
6601 ans = Message (MSG_YN, "There is no alignment between the sequences. Do you wish to continue?");
6602 if (ans == ANS_YES)
6603 {
6604 udp->useGUI = TRUE;
6605 }
6606 else
6607 {
6608 return FALSE;
6609 }
6610 }
6611 }
6612 }
6613 udp->salp = salp;
6614 udp->revcomp = revcomp;
6615 udp->diffOrgs = FALSE;
6616 udp->recomb1 = -1;
6617 udp->recomb2 = -1;
6618
6619 return TRUE;
6620 }
6621
6622 static void UpdateProteinsOnNewBsp (SeqFeatPtr sfp, Pointer userdata);
6623
6624 static void
6625 FindProtRefPtrsOnBsp
6626 (BioseqPtr bsp,
6627 ValNodePtr PNTR feat_list)
6628 {
6629 SeqMgrFeatContext context;
6630 SeqFeatPtr sfp;
6631 ValNodePtr vnp;
6632
6633 if (bsp == NULL || feat_list == NULL) return;
6634 sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_PROT, 0, &context);
6635 while (sfp != NULL) {
6636 if (context.left == 0 && context.right == bsp->length - 1) {
6637 vnp = ValNodeNew (*feat_list);
6638 if (vnp != NULL) {
6639 vnp->data.ptrvalue = sfp;
6640 }
6641 if (*feat_list == NULL) {
6642 *feat_list = vnp;
6643 }
6644 }
6645 sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_PROT, 0, &context);
6646 }
6647 }
6648
6649 static ValNodePtr FindProductProtRefs (BioseqPtr bsp)
6650 {
6651 SeqFeatPtr sfp;
6652 SeqMgrFeatContext context;
6653 ValNodePtr feat_list = NULL;
6654
6655 if (bsp == NULL) return NULL;
6656 sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &context);
6657 while (sfp != NULL) {
6658 FindProtRefPtrsOnBsp (BioseqFindFromSeqLoc (sfp->product), &feat_list);
6659 sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &context);
6660 }
6661 return feat_list;
6662 }
6663
6664 static ValNodePtr FindTranslExceptCDSs (BioseqPtr bsp)
6665 {
6666 SeqFeatPtr sfp;
6667 SeqMgrFeatContext context;
6668 ValNodePtr feat_list = NULL;
6669 ValNodePtr vnp;
6670 Int4 cd_len;
6671
6672 if (bsp == NULL) return NULL;
6673 sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &context);
6674 while (sfp != NULL) {
6675 if (CodingRegionHasTranslExcept (sfp))
6676 {
6677 vnp = ValNodeNew(feat_list);
6678 if (feat_list == NULL)
6679 {
6680 feat_list = vnp;
6681 }
6682 if (vnp != NULL)
6683 {
6684 cd_len = SeqLocLen (sfp->location);
6685 vnp->choice = cd_len % 3;
6686 vnp->data.ptrvalue = sfp;
6687 }
6688 }
6689 sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &context);
6690 }
6691 return feat_list;
6692 }
6693
6694 static Int4 GetOriginalTranslExceptLen (SeqFeatPtr sfp, ValNodePtr list)
6695 {
6696 ValNodePtr vnp;
6697
6698 if (sfp == NULL || list == NULL) return 0;
6699 for (vnp = list; vnp != NULL; vnp = vnp->next)
6700 {
6701 if (vnp->data.ptrvalue == sfp)
6702 {
6703 return vnp->choice;
6704 }
6705 }
6706 if (CodingRegionHasTranslExcept (sfp))
6707 {
6708 return SeqLocLen (sfp->location) % 3;
6709 }
6710 return 0;
6711 }
6712
6713 static void UpdateOneSequence (
6714 UpsDataPtr udp,
6715 Int2 sfbval,
6716 Boolean add_cit_subs,
6717 Boolean update_proteins
6718 )
6719 {
6720 SeqAnnotPtr sap = NULL;
6721 Uint2 entityID;
6722 SeqEntryPtr sep;
6723 Boolean update = FALSE;
6724 Boolean feature_update = FALSE;
6725 ValNodePtr prot_feat_list = NULL;
6726
6727 if (udp != NULL)
6728 {
6729 if (GetStatus (udp->replace_all))
6730 {
6731 RemoveOldFeats (udp->oldbsp);
6732 }
6733 }
6734
6735 if (update_proteins && udp != NULL) {
6736 prot_feat_list = FindProductProtRefs (udp->oldbsp);
6737 if (udp->transl_except_list != NULL)
6738 {
6739 ValNodeFree (udp->transl_except_list);
6740 udp->transl_except_list = NULL;
6741 }
6742 udp->transl_except_list = FindTranslExceptCDSs (udp->oldbsp);
6743 }
6744
6745 if (sfbval == UPDATE_SEQUENCE_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
6746 switch (udp->rmcval) {
6747 case UPDATE_REPLACE :
6748 if (ReplaceSequence (udp)) {
6749 update = TRUE;
6750 }
6751 break;
6752 case UPDATE_EXTEND5 :
6753 if (NULL == udp->salp) {
6754 if (Merge5PrimeNoOverlap (udp))
6755 update = TRUE;
6756 }
6757 else
6758 {
6759 if (Merge5Prime (udp))
6760 update = TRUE;
6761 }
6762 break;
6763 case UPDATE_EXTEND3 :
6764 if (NULL == udp->salp) {
6765 if (Merge3PrimeNoOverlap (udp))
6766 update = TRUE;
6767 }
6768 else
6769 {
6770 if (Merge3Prime (udp))
6771 update = TRUE;
6772 }
6773 break;
6774 case UPDATE_PATCH :
6775 if (PatchSequence (udp)) {
6776 update = TRUE;
6777 }
6778 break;
6779 default :
6780 break;
6781 }
6782 if ( sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
6783 switch (udp->rmcval) {
6784 case UPDATE_REPLACE :
6785 if (DoFeaturePropWithOffset (udp, 0, &sap, FALSE)) {
6786 update = TRUE;
6787 feature_update = TRUE;
6788 }
6789 break;
6790 case UPDATE_EXTEND5 :
6791 if (DoFeaturePropWithOffset (udp, 0, &sap, FALSE)) {
6792 update = TRUE;
6793 feature_update = TRUE;
6794 }
6795 break;
6796 case UPDATE_EXTEND3 :
6797 if (DoFeaturePropWithOffset (udp, udp->old5 - udp->new5, &sap, FALSE)) {
6798 update = TRUE;
6799 feature_update = TRUE;
6800 }
6801 break;
6802 case UPDATE_PATCH :
6803 if (DoFeaturePropWithOffset (udp, udp->old5 - udp->new5, &sap, TRUE)) {
6804 update = TRUE;
6805 feature_update = TRUE;
6806 }
6807 break;
6808 default :
6809 break;
6810 }
6811 }
6812 if (udp->rmcval == UPDATE_REPLACE && udp->revcomp && update)
6813 {
6814 ReverseComplementBioseqAndFeats (udp->oldbsp, udp->input_entityID);
6815 }
6816
6817 } else if (sfbval == UPDATE_FEATURES_ONLY) {
6818 switch (udp->rmcval) {
6819 case UPDATE_REPLACE :
6820 if (DoFeaturePropThruAlign (udp, &sap)) {
6821 update = TRUE;
6822 feature_update = TRUE;
6823 }
6824 break;
6825 case UPDATE_EXTEND5 :
6826 if (DoFeaturePropThruAlign (udp, &sap)) {
6827 update = TRUE;
6828 feature_update = TRUE;
6829 }
6830 break;
6831 case UPDATE_EXTEND3 :
6832 if (DoFeaturePropThruAlign (udp, &sap)) {
6833 update = TRUE;
6834 feature_update = TRUE;
6835 }
6836 break;
6837 case UPDATE_PATCH :
6838 if (DoFeaturePropThruAlign (udp, &sap)) {
6839 update = TRUE;
6840 feature_update = TRUE;
6841 }
6842 break;
6843 default :
6844 break;
6845 }
6846 }
6847 if (update) {
6848 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
6849 if (add_cit_subs
6850 && (feature_update || StringCmp (udp->seq1, udp->seq2) != 0))
6851 {
6852 AddCitSubToUpdatedSequence ( udp->oldbsp, entityID, kSubmitterUpdateText);
6853 }
6854 if (update_proteins)
6855 {
6856 SeqMgrClearFeatureIndexes (entityID, udp->oldbsp);
6857 SeqMgrIndexFeatures (entityID, NULL);
6858 sep = GetBestTopParentForData (entityID, udp->oldbsp);
6859 udp->truncate_proteins = GetStatus (udp->truncate_proteins_btn);
6860 udp->extend_proteins5 = GetStatus (udp->extend_proteins5_btn);
6861 udp->extend_proteins3 = GetStatus (udp->extend_proteins3_btn);
6862 udp->correct_cds_genes = GetStatus (udp->correct_cds_genes_btn);
6863 VisitFeaturesInSep (sep, udp, UpdateProteinsOnNewBsp);
6864 FixProtRefPtrs (prot_feat_list);
6865 }
6866 if (! udp->suppress_instant_refresh) {
6867 ObjMgrSetDirtyFlag (entityID, TRUE);
6868 ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
6869 }
6870 }
6871
6872 if (GetStatus (udp->update_quality_scores_btn) && udp->rmcval == UPDATE_REPLACE
6873 && (sfbval == UPDATE_SEQUENCE_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES))
6874 {
6875 ReplaceQualityScores (udp->oldbsp, udp->newbsp, udp->log_fp, &(udp->data_in_log));
6876 }
6877 else if (sfbval != UPDATE_FEATURES_ONLY)
6878 {
6879 RemoveQualityScores (udp->oldbsp, udp->log_fp, &(udp->data_in_log));
6880 }
6881
6882 ValNodeFree (prot_feat_list);
6883 ValNodeFree (udp->transl_except_list);
6884 udp->transl_except_list = NULL;
6885 if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
6886 if (update) {
6887 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
6888 sep = GetTopSeqEntryForEntityID (entityID);
6889 /* need to set scope to make sure we mark the right bioseq for deletion */
6890 SeqEntrySetScope (sep);
6891 /* resolve features unless the policy was to remove all the old ones */
6892 if (!GetStatus (udp->replace_all))
6893 {
6894 ResolveDuplicateFeats (udp, udp->oldbsp, sap);
6895 }
6896 SeqEntrySetScope (NULL);
6897 DeleteMarkedObjects (entityID, 0, NULL);
6898 SeqMgrClearFeatureIndexes (entityID, NULL);
6899 ObjMgrSetDirtyFlag (entityID, TRUE);
6900 ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
6901 }
6902 }
6903 }
6904
6905 static void UpdateProteinsOnNewBsp (SeqFeatPtr sfp, Pointer userdata)
6906 {
6907 UpsDataPtr udp_orig;
6908 SeqLocPtr new_product;
6909 Boolean data_in_log;
6910 Int4 transl_except_len = 0;
6911 Boolean fix_products = TRUE;
6912 BioseqPtr protBsp = NULL;
6913 SeqAlignPtr salp = NULL;
6914 BioseqPtr newbsp = NULL;
6915 Boolean rval;
6916
6917 if (sfp == NULL || sfp->idx.subtype != FEATDEF_CDS || userdata == NULL)
6918 {
6919 return;
6920 }
6921
6922 if (sfp->idx.deleteme)
6923 {
6924 return;
6925 }
6926
6927 protBsp = BioseqFindFromSeqLoc (sfp->product);
6928 if (protBsp == NULL)
6929 {
6930 return;
6931 }
6932 udp_orig = (UpsDataPtr) userdata;
6933
6934 data_in_log = FALSE;
6935 transl_except_len = GetOriginalTranslExceptLen (sfp, udp_orig->transl_except_list);
6936 rval = PrepareUpdateAlignmentForProtein (sfp,
6937 protBsp,
6938 udp_orig->input_entityID,
6939 udp_orig->log_fp,
6940 udp_orig->truncate_proteins,
6941 udp_orig->extend_proteins5,
6942 udp_orig->extend_proteins3,
6943 udp_orig->correct_cds_genes,
6944 transl_except_len,
6945 &data_in_log,
6946 &salp,
6947 &newbsp);
6948 if (data_in_log) {
6949 udp_orig->data_in_log = TRUE;
6950 }
6951 if (!rval) return;
6952
6953 if (protBsp->idx.deleteme)
6954 {
6955 fix_products = FALSE;
6956 }
6957
6958 ReplaceOneSequence (salp, protBsp, newbsp);
6959
6960 if (fix_products)
6961 {
6962 if (sfp->product->choice != SEQLOC_WHOLE) {
6963 new_product = SeqLocWholeNew (protBsp);
6964 if (new_product == NULL) return;
6965 SeqLocFree (sfp->product);
6966 sfp->product = new_product;
6967 }
6968 newbsp = BioseqFree (newbsp);
6969 }
6970 }
6971
6972 extern void UpdateProteinsFromCDS ( IteM i)
6973 {
6974 BaseFormPtr bfp;
6975 SeqEntryPtr sep;
6976 ProteinFromCDSData pfcd;
6977 Char path [PATH_MAX];
6978
6979 #ifdef WIN_MAC
6980 bfp = currentFormDataPtr;
6981 #else
6982 bfp = GetObjectExtra (i);
6983 #endif
6984
6985 if (bfp == NULL)
6986 return;
6987 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
6988 if (sep == NULL) return;
6989
6990 pfcd.input_entityID = bfp->input_entityID;
6991 pfcd.input_itemID = bfp->input_itemID;
6992 pfcd.input_itemtype = bfp->input_itemtype;
6993 pfcd.data_to_report = FALSE;
6994 TmpNam (path);
6995 pfcd.fp = FileOpen (path, "wb");
6996 if (pfcd.fp == NULL) return;
6997
6998 WatchCursor ();
6999 VisitFeaturesInSep (sep, (Pointer) &pfcd, UpdateOneProteinFromCDS);
7000 FileClose (pfcd.fp);
7001 if (pfcd.data_to_report) {
7002 LaunchGeneralTextViewer (path, "Update Log");
7003 }
7004 FileRemove (path);
7005 ArrowCursor ();
7006 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
7007 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
7008 }
7009
7010 /* This section of code is used to warn the user when an alignment update
7011 * will affect the area inside a variation or the area immediately to the
7012 * left or right of a variation.
7013 */
7014 static void VariationAlignmentCallback (SeqFeatPtr sfp, Pointer userdata)
7015 {
7016 CharPtr buf, cp;
7017 UpsDataPtr udp;
7018 Boolean change_found = FALSE;
7019
7020 if (sfp == NULL || userdata == NULL || sfp->idx.subtype != FEATDEF_variation)
7021 {
7022 return;
7023 }
7024 udp = (UpsDataPtr) userdata;
7025 if (udp->salp == NULL)
7026 {
7027 return;
7028 }
7029
7030 buf = FeatureLocationAlignment (sfp, udp->salp, 1, 2);
7031 if (buf == NULL)
7032 {
7033 return;
7034 }
7035 cp = buf;
7036 /* skip over "Old :" */
7037 if (StringLen (cp) > 8)
7038 {
7039 cp += 8;
7040 }
7041 while (*cp != 0 && *cp != '\n' && !change_found)
7042 {
7043 if (*cp == '-')
7044 {
7045 change_found = TRUE;
7046 }
7047 cp++;
7048 }
7049 if (*cp == '\n')
7050 {
7051 cp++;
7052 }
7053 /* skip over "New :" */
7054 if (StringLen (cp) > 8)
7055 {
7056 cp += 8;
7057 }
7058 while (*cp != 0 && *cp != '\n' && !change_found)
7059 {
7060 if (*cp != '.')
7061 {
7062 change_found = TRUE;
7063 }
7064 cp++;
7065 }
7066 if (change_found)
7067 {
7068 ValNodeAddPointer (&udp->affected_variation_features, 0, sfp);
7069 }
7070 buf = MemFree (buf);
7071 }
7072
7073 static CharPtr PrepareVariationFeatureLogEntry (SeqFeatPtr sfp, SeqAlignPtr salp)
7074 {
7075 CharPtr loc_buf, feat_buf, total_buf;
7076 Int4 buf_len;
7077
7078 if (sfp == NULL || salp == NULL)
7079 {
7080 return NULL;
7081 }
7082
7083 loc_buf = SeqLocPrint (sfp->location);
7084 feat_buf = FeatureLocationAlignment (sfp, salp, 1, 2);
7085
7086 buf_len = StringLen (sfp->comment) + StringLen (loc_buf) + StringLen (feat_buf) + 3;
7087 total_buf = (CharPtr) MemNew (buf_len * sizeof (Char));
7088 if (total_buf != NULL)
7089 {
7090 total_buf [0] = 0;
7091 /* add feature name */
7092 if (!StringHasNoText (sfp->comment))
7093 {
7094 StringCpy (total_buf, sfp->comment);
7095 StringCat (total_buf, "\n");
7096 }
7097 /* add feature location */
7098 if (!StringHasNoText (loc_buf))
7099 {
7100 StringCat (total_buf, loc_buf);
7101 StringCat (total_buf, "\n");
7102 }
7103 /* add alignment picture */
7104 if (!StringHasNoText (feat_buf))
7105 {
7106 StringCat (total_buf, feat_buf);
7107 }
7108 loc_buf = MemFree (loc_buf);
7109 feat_buf = MemFree (feat_buf);
7110 }
7111 return total_buf;
7112 }
7113
7114 static Int4
7115 VariationFeatureChangesOk
7116 (ValNodePtr variation_feature_list,
7117 SeqAlignPtr salp,
7118 Boolean allow_skip)
7119 {
7120 WindoW w;
7121 GrouP h, c;
7122 ButtoN b;
7123 DoC doc;
7124 ValNodePtr vnp;
7125 SeqFeatPtr sfp;
7126 CharPtr total_buf;
7127 ModalAcceptCancelData acd;
7128 CharPtr str_format = "%d variation features are affected by this update.";
7129
7130 if (variation_feature_list == NULL || salp == NULL)
7131 {
7132 return TRUE;
7133 }
7134
7135 w = MovableModalWindow (-20, -13, -10, -10, "Affected Variation Sequences", NULL);
7136 h = HiddenGroup(w, -1, 0, NULL);
7137 SetGroupSpacing (h, 10, 10);
7138
7139 doc = DocumentPanel (h, stdCharWidth * 40, stdLineHeight * 12);
7140 SetDocAutoAdjust (doc, TRUE);
7141
7142 total_buf = MemNew (StringLen (str_format) + 15);
7143 if (total_buf != NULL)
7144 {
7145 sprintf (total_buf, str_format, ValNodeLen (variation_feature_list));
7146 AppendText (doc, total_buf, NULL, NULL, programFont);
7147 total_buf = MemFree (total_buf);
7148 }
7149
7150 for (vnp = variation_feature_list; vnp != NULL; vnp = vnp->next)
7151 {
7152 sfp = (SeqFeatPtr) vnp->data.ptrvalue;
7153 total_buf = PrepareVariationFeatureLogEntry (sfp, salp);
7154 if (!StringHasNoText (total_buf))
7155 {
7156 AppendText (doc, total_buf, NULL, NULL, programFont);
7157 }
7158 MemFree (total_buf);
7159 }
7160 UpdateDocument (doc, 0, 0);
7161
7162 c = HiddenGroup (h, 3, 0, NULL);
7163 b = PushButton (c, "Proceed", ModalAcceptButton);
7164 SetObjectExtra (b, &acd, NULL);
7165 if (allow_skip)
7166 {
7167 b = PushButton (c, "Skip Update", ModalThirdOptionButton);
7168 SetObjectExtra (b, &acd, NULL);
7169 }
7170
7171 b = PushButton (c, "Cancel Update", ModalCancelButton);
7172 SetObjectExtra (b, &acd, NULL);
7173
7174
7175 AlignObjects (ALIGN_CENTER, (HANDLE) doc,
7176 (HANDLE) c,
7177 NULL);
7178
7179 Show (w);
7180 Select (w);
7181
7182 acd.cancelled = FALSE;
7183 acd.third_option = FALSE;
7184 acd.accepted = FALSE;
7185 while (!acd.accepted && ! acd.cancelled && !acd.third_option)
7186 {
7187 ProcessExternalEvent ();
7188 Update ();
7189 }
7190 ProcessAnEvent ();
7191 Remove (w);
7192
7193 if (acd.accepted)
7194 {
7195 return 1;
7196 }
7197 else if (acd.cancelled)
7198 {
7199 return 2;
7200 }
7201 else
7202 {
7203 return 3;
7204 }
7205 }
7206
7207 static void
7208 AddVariationFeaturesToLog
7209 (FILE *fp,
7210 BoolPtr data_in_log,
7211 ValNodePtr variation_feature_list,
7212 SeqAlignPtr salp)
7213 {
7214 ValNodePtr vnp;
7215 CharPtr total_buf;
7216 SeqFeatPtr sfp;
7217
7218 if (fp == NULL || variation_feature_list == NULL)
7219 {
7220 return;
7221 }
7222
7223 for (vnp = variation_feature_list; vnp != NULL; vnp = vnp->next)
7224 {
7225 sfp = (SeqFeatPtr) vnp->data.ptrvalue;
7226 total_buf = PrepareVariationFeatureLogEntry (sfp, salp);
7227 if (!StringHasNoText (total_buf))
7228 {
7229 fprintf (fp, total_buf);
7230 if (data_in_log != NULL)
7231 {
7232 *data_in_log = TRUE;
7233 }
7234 }
7235 MemFree (total_buf);
7236 }
7237
7238 }
7239
7240 static void AcceptRMCOrExtend (ButtoN b)
7241 {
7242 UpsDataPtr udp;
7243 Int2 sfbval;
7244 Boolean log_is_local;
7245 Boolean update_proteins = FALSE;
7246 Uint2 entityID;
7247
7248 udp = (UpsDataPtr) GetObjectExtra (b);
7249 if (udp == NULL) return;
7250 SafeHide (udp->form);
7251
7252 sfbval = GetValue (udp->sfb);
7253 udp->rmcval = GetValue (udp->rmc);
7254
7255 if (udp->log_fp == NULL) {
7256 OpenSequenceUpdateLog (udp);
7257 if (udp->log_fp == NULL) return;
7258 log_is_local = TRUE;
7259 } else {
7260 log_is_local = FALSE;
7261 }
7262 WatchCursor ();
7263 Update ();
7264
7265 if (udp->do_update)
7266 {
7267 udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
7268 VisitFeaturesOnBsp (udp->oldbsp, udp, VariationAlignmentCallback);
7269 if (1 == VariationFeatureChangesOk (udp->affected_variation_features, udp->salp, FALSE))
7270 {
7271 if (udp->update_proteins != NULL
7272 && Enabled (udp->update_proteins)
7273 && GetStatus (udp->update_proteins))
7274 {
7275 update_proteins = TRUE;
7276 }
7277 AddVariationFeaturesToLog (udp->log_fp, &(udp->data_in_log),
7278 udp->affected_variation_features, udp->salp);
7279 UpdateOneSequence (udp, sfbval,
7280 GetStatus (udp->add_cit_subs),
7281 update_proteins);
7282 }
7283 udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
7284 }
7285 else
7286 {
7287 if (ExtendOneSequence (udp))
7288 {
7289 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
7290 ObjMgrSetDirtyFlag (entityID, TRUE);
7291 ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
7292 }
7293 }
7294
7295 Remove (udp->form);
7296 if (log_is_local) {
7297 CloseOutSequenceUpdateLog (udp);
7298 }
7299 ArrowCursor ();
7300 Update();
7301 }
7302
7303 static void DoAcceptRMCOrExtendSet (UpsDataPtr udp)
7304 {
7305 Int2 sfbval = 0;
7306 Boolean log_is_local = FALSE;
7307 Boolean update_proteins = FALSE;
7308 Boolean do_update = TRUE;
7309 Boolean old_useGUI;
7310 Char acc_str [256];
7311 SeqIdPtr sip, sip_next;
7312 Int2 prior_rmcval;
7313 Int4 variation_action = 1;
7314
7315 if (udp == NULL) return;
7316
7317 SafeHide (udp->form);
7318 old_useGUI = udp->useGUI;
7319
7320 prior_rmcval = udp->rmcval;
7321 if (udp->do_update)
7322 {
7323 if (udp->salp == NULL
7324 && (udp->no_aln_choice == UPDATE_REPLACE_THIS
7325 || udp->no_aln_choice == UPDATE_REPLACE_ALL))
7326 {
7327 sfbval = UPDATE_SEQUENCE_ONLY;
7328 udp->rmcval = UPDATE_REPLACE;
7329 udp->useGUI = FALSE;
7330 }
7331 else if (udp->salp == NULL
7332 && (udp->no_aln_choice == UPDATE_SKIP_THIS
7333 || udp->no_aln_choice == UPDATE_SKIP_ALL))
7334 {
7335 do_update = FALSE;
7336 }
7337 else
7338 {
7339 sfbval = GetValue (udp->sfb);
7340 udp->rmcval = GetValue (udp->rmc);
7341 prior_rmcval = udp->rmcval;
7342 }
7343 }
7344 else
7345 {
7346 udp->rmcval = GetValue (udp->rmc);
7347 prior_rmcval = udp->rmcval;
7348 }
7349
7350 if (udp->log_fp == NULL)
7351 {
7352 OpenSequenceUpdateLog (udp);
7353 if (udp->log_fp == NULL) return;
7354 log_is_local = TRUE;
7355 }
7356 if (do_update && udp->do_update)
7357 {
7358 udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
7359 VisitFeaturesOnBsp (udp->oldbsp, udp, VariationAlignmentCallback);
7360 variation_action = VariationFeatureChangesOk (udp->affected_variation_features, udp->salp, TRUE);
7361 if (1 != variation_action)
7362 {
7363 do_update = FALSE;
7364 }
7365
7366
7367 }
7368
7369 if (do_update)
7370 {
7371 if (udp->do_update)
7372 {
7373 if (udp->update_proteins != NULL
7374 && Enabled (udp->update_proteins)
7375 && GetStatus (udp->update_proteins))
7376 {
7377 update_proteins = TRUE;
7378 }
7379
7380 AddVariationFeaturesToLog (udp->log_fp, &(udp->data_in_log),
7381 udp->affected_variation_features, udp->salp);
7382 UpdateOneSequence (udp, sfbval, GetStatus (udp->add_cit_subs),
7383 update_proteins);
7384 }
7385 else
7386 {
7387 ExtendOneSequence (udp);
7388 }
7389
7390 Remove (udp->form);
7391 }
7392 else
7393 {
7394 sip = SeqIdFindBest (udp->oldbsp->id, 0);
7395 if (sip != NULL)
7396 {
7397 sip_next = sip->next;
7398 SeqIdWrite (sip, acc_str, PRINTID_REPORT, sizeof (acc_str));
7399 fprintf (udp->log_fp, "Skipped update for %s\n", acc_str);
7400 udp->data_in_log = TRUE;
7401 sip->next = sip_next;
7402 }
7403 }
7404 udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
7405
7406 if (log_is_local)
7407 {
7408 CloseOutSequenceUpdateLog (udp);
7409 }
7410
7411 if (2 == variation_action)
7412 {
7413 FileClose (udp->fp);
7414 CloseOutSequenceUpdateLog (udp);
7415 }
7416
7417 udp->useGUI = old_useGUI;
7418 udp->rmcval = prior_rmcval;
7419 /* if we are updating a set from a SeqSub, we don't want to free the SeqSub yet */
7420 if (udp->seqsubsep != NULL)
7421 {
7422 udp->newbsp = NULL;
7423 }
7424 FreeUdpFields (udp);
7425 }
7426
7427 /*------------------------------------------------------------------*/
7428 /* */
7429 /* AcceptRMCAll () -- Breaks out of the GUI interface and updates */
7430 /* all remaining sequences in the file without */
7431 /* user intervention. */
7432 /* */
7433 /*------------------------------------------------------------------*/
7434
7435 static void AcceptRMCOrExtendAll (ButtoN b)
7436
7437 {
7438 UpsDataPtr udp;
7439 Int2 state;
7440 Int4 count;
7441 Char msgStr[256];
7442
7443 /* Get current data */
7444
7445 udp = (UpsDataPtr) GetObjectExtra (b);
7446 if (udp == NULL)
7447 return;
7448
7449 /* Process the current sequence */
7450
7451 WatchCursor ();
7452 udp->useGUI = FALSE;
7453
7454 if (udp->log_fp == NULL) {
7455 OpenSequenceUpdateLog (udp);
7456 if (udp->log_fp == NULL) return;
7457 }
7458
7459
7460 udp->rmcval = GetValue (udp->rmc);
7461
7462 DoAcceptRMCOrExtendSet (udp);
7463
7464 /* Loop through the file, processing all others */
7465
7466 state = FASTA_READ_OK;
7467 count = 0;
7468
7469 while (FASTA_READ_OK == state) {
7470 count++;
7471 WatchCursor ();
7472 state = UpdateNextBioseqInFastaSet (udp);
7473 if (udp->useGUI)
7474 return;
7475 }
7476
7477 CloseOutSequenceUpdateLog (udp);
7478 ArrowCursor ();
7479
7480 /* If there was an error, report it, otherwise */
7481 /* print a status message. */
7482
7483 if (FASTA_READ_ERROR == state) {
7484 sprintf (msgStr, "Encountered error while updating. Only %d sequences "
7485 "were updated.", count);
7486 Message (MSG_OK, msgStr);
7487 }
7488 else {
7489 sprintf (msgStr, "Successfully processed %d sequences from file (not"
7490 " counting any updated before hitting 'Accept All').", count);
7491 Message (MSG_OK, msgStr);
7492 }
7493 }
7494
7495
7496 static void AcceptRMCOrExtendSet (ButtoN b)
7497
7498 {
7499 UpsDataPtr udp;
7500
7501 udp = (UpsDataPtr) GetObjectExtra (b);
7502 if (udp == NULL)
7503 return;
7504
7505 if (udp->log_fp == NULL) {
7506 OpenSequenceUpdateLog (udp);
7507 if (udp->log_fp == NULL) return;
7508 }
7509
7510 udp->rmcval = GetValue (udp->rmc);
7511
7512 DoAcceptRMCOrExtendSet (udp);
7513
7514 UpdateNextBioseqInFastaSet (udp);
7515 }
7516
7517 static void SetProteinOptionsEnable (UpsDataPtr udp)
7518 {
7519 if (udp == NULL || udp->update_proteins == NULL) return;
7520
7521 if (Enabled (udp->update_proteins) && GetStatus (udp->update_proteins))
7522 {
7523 Enable (udp->truncate_proteins_btn);
7524 Enable (udp->extend_proteins3_btn);
7525 Enable (udp->extend_proteins5_btn);
7526 Enable (udp->correct_cds_genes_btn);
7527 }
7528 else
7529 {
7530 Disable (udp->truncate_proteins_btn);
7531 Disable (udp->extend_proteins3_btn);
7532 Disable (udp->extend_proteins5_btn);
7533 Disable (udp->correct_cds_genes_btn);
7534 }
7535 }
7536
7537 static void SetStatusUpdateAcceptBtns (UpsDataPtr udp, Boolean status)
7538 {
7539 if (udp == NULL) return;
7540
7541 if (status)
7542 {
7543 SafeEnable (udp->accept);
7544 SafeEnable (udp->acceptAll);
7545 }
7546 else
7547 {
7548 SafeDisable (udp->accept);
7549 SafeDisable (udp->acceptAll);
7550 }
7551 }
7552
7553 static void UpdateAccept (GrouP g)
7554
7555 {
7556 Int2 rmcval, sfbval;
7557 UpsDataPtr udp;
7558 Int2 nobmval = UPDATE_FEAT_DUP_NOT_SET;
7559
7560 udp = (UpsDataPtr) GetObjectExtra (g);
7561 if (udp == NULL) return;
7562
7563 rmcval = GetValue (udp->rmc);
7564 sfbval = GetValue (udp->sfb);
7565
7566 if (rmcval == UPDATE_REPLACE)
7567 {
7568 sfbval = GetValue (udp->sfb);
7569 if (sfbval == UPDATE_SEQUENCE_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES)
7570 {
7571 Enable (udp->update_quality_scores_btn);
7572 }
7573 else
7574 {
7575 Disable (udp->update_quality_scores_btn);
7576 }
7577 }
7578 else
7579 {
7580 Disable (udp->update_quality_scores_btn);
7581 }
7582
7583 if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES)
7584 {
7585 if (!GetStatus (udp->replace_all))
7586 {
7587 nobmval = GetValue (udp->nobm);
7588 }
7589 }
7590
7591 /* set enables for protein updates */
7592 if (sfbval == UPDATE_SEQUENCE_ONLY
7593 || (sfbval == UPDATE_SEQUENCE_AND_FEATURES
7594 && (nobmval == UPDATE_FEAT_DUP_USE_OLD || nobmval == UPDATE_FEAT_DUP_USE_BOTH)))
7595 {
7596 SafeEnable (udp->update_proteins);
7597 }
7598 else
7599 {
7600 SafeDisable (udp->update_proteins);
7601 }
7602 SetProteinOptionsEnable (udp);
7603
7604 if (rmcval == UPDATE_CHOICE_NOT_SET) {
7605 SetStatusUpdateAcceptBtns (udp, FALSE);
7606 return;
7607 }
7608 if (! udp->do_update) {
7609 SetStatusUpdateAcceptBtns (udp, TRUE);
7610 return;
7611 }
7612
7613 if (sfbval == UPDATE_CHOICE_NOT_SET || sfbval == UPDATE_SEQUENCE_ONLY || udp->diffOrgs) {
7614 SafeDisable (udp->keepProteinIDs);
7615 if (sfbval == UPDATE_CHOICE_NOT_SET || sfbval == UPDATE_SEQUENCE_ONLY) {
7616 SafeDisable (udp->nobm);
7617 SafeDisable (udp->replace_all);
7618 } else {
7619 SafeEnable (udp->replace_all);
7620 if (GetStatus (udp->replace_all))
7621 {
7622 SafeDisable (udp->nobm);
7623 }
7624 else
7625 {
7626 SafeEnable (udp->nobm);
7627 }
7628 }
7629 } else if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
7630 SafeEnable (udp->keepProteinIDs);
7631 SafeEnable (udp->replace_all);
7632 if (GetStatus (udp->replace_all))
7633 {
7634 SafeDisable (udp->nobm);
7635 }
7636 else
7637 {
7638 SafeEnable (udp->nobm);
7639 }
7640 }
7641 if (sfbval == UPDATE_CHOICE_NOT_SET) {
7642 SetStatusUpdateAcceptBtns (udp, FALSE);
7643 return;
7644 }
7645 if (sfbval == UPDATE_FEATURES_ONLY || sfbval == UPDATE_SEQUENCE_AND_FEATURES) {
7646 if (!GetStatus (udp->replace_all) && nobmval == UPDATE_FEAT_DUP_NOT_SET)
7647 {
7648 SetStatusUpdateAcceptBtns (udp, FALSE);
7649 return;
7650 }
7651 }
7652
7653 SetStatusUpdateAcceptBtns (udp, TRUE);
7654 }
7655
7656 static void UpdateButtons (GrouP g)
7657 {
7658 UpsDataPtr udp;
7659 Int2 rmcval;
7660 Uint2 entityID;
7661 SeqFeatPtr sfp;
7662 SeqMgrFeatContext fcontext;
7663
7664 udp = (UpsDataPtr) GetObjectExtra (g);
7665 if (udp == NULL) return;
7666
7667 rmcval = GetValue (udp->rmc);
7668
7669 if (udp->new5 <= udp->old5 && udp->new3 <= udp->old3)
7670 {
7671 if (rmcval == UPDATE_PATCH)
7672 {
7673 /* If patch sequence matches, must be feature propagation only */
7674
7675 if (StringNICmp (udp->seq1 + udp->old5 - udp->new5,
7676 udp->seq2,
7677 StringLen (udp->seq2)) == 0) {
7678 SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
7679 Disable (udp->sfb);
7680 }
7681 }
7682 else if (rmcval == UPDATE_REPLACE)
7683 {
7684 /* If no features, must be sequence update only */
7685
7686 entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
7687 if (! SeqMgrFeaturesAreIndexed (entityID))
7688 SeqMgrIndexFeatures (entityID, NULL);
7689
7690 sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &fcontext);
7691 if (sfp == NULL)
7692 {
7693 SetValue (udp->sfb, UPDATE_SEQUENCE_ONLY);
7694 Disable (udp->sfb);
7695 Disable (udp->replace_all);
7696 Disable (udp->nobm);
7697 }
7698 else if (!indexerVersion &&
7699 (udp->newbsp->repr != Seq_repr_raw || udp->oldbsp->repr != Seq_repr_raw))
7700 {
7701 SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
7702 Disable (udp->sfb);
7703 }
7704 else
7705 {
7706 Enable (udp->sfb);
7707 }
7708 }
7709 }
7710 UpdateAccept (g);
7711 }
7712
7713 static void DrawAlignBlock (
7714 SegmenT pict,
7715 Int4 top,
7716 Int4 bottom,
7717 Int4 labelpt,
7718 Int2 labelaln,
7719 Int4 len5,
7720 Int4 lena,
7721 Int4 len3,
7722 Int4 aln_length
7723 )
7724
7725 {
7726 Char str [96];
7727
7728 if (len5 > 0) {
7729 AddRectangle (pict, -len5, top, 0, bottom, NO_ARROW, FALSE, 0);
7730 }
7731 sprintf (str, "%ld", (long) len5);
7732 AddLabel (pict, -len5, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
7733
7734 if (len3 > 0) {
7735 AddRectangle (pict, aln_length, top, aln_length + len3, bottom, NO_ARROW, FALSE, 0);
7736 }
7737 sprintf (str, "%ld", (long) len3);
7738 AddLabel (pict, aln_length + len3, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
7739
7740 AddRectangle (pict, 0, top, aln_length, bottom, NO_ARROW, TRUE, 0);
7741 sprintf (str, "%ld", (long) lena);
7742 AddLabel (pict, aln_length / 2, labelpt, str, SMALL_TEXT, 5, labelaln, 0);
7743 }
7744
7745 static SegmenT MakeAlignPicture (
7746 UpsDataPtr udp,
7747 CharPtr strid1,
7748 CharPtr strid2,
7749 SeqAlignPtr sap
7750 )
7751
7752 {
7753 SegmenT pict;
7754 Char str [96];
7755 Int4 top, bottom;
7756
7757 pict = CreatePicture ();
7758 if (sap == NULL) return pict;
7759
7760 top = 0;
7761 bottom = top - 10;
7762
7763 DrawAlignBlock (pict, top, bottom, bottom, LOWER_CENTER, udp->old5, udp->olda, udp->old3, udp->aln_length);
7764
7765 /*
7766 AddLabel (pict, (udp->stopmax - udp->startmax) / 2, bottom - 20, strid1, SMALL_TEXT, 5, LOWER_CENTER, 0);
7767 */
7768
7769
7770 sprintf (str, "%ld", (long) udp->aln_length);
7771 AddLabel (pict, udp->aln_length / 2, 10, str, SMALL_TEXT, 5, MIDDLE_CENTER, 0);
7772
7773
7774 top = 30;
7775 bottom = top - 10;
7776
7777 DrawAlignBlock (pict, top, bottom, top, UPPER_CENTER, udp->new5, udp->newa, udp->new3, udp->aln_length);
7778
7779 /*
7780 AddLabel (pict, (udp->stopmax - udp->startmax) / 2, top + 20, strid2, SMALL_TEXT, 5, UPPER_CENTER, 0);
7781 */
7782
7783 return pict;
7784 }
7785
7786 static void DrawAlignDiffs (
7787 UpsDataPtr udp,
7788 SegmenT pict,
7789 Int4 top,
7790 Int4 bottom,
7791 SeqAlignPtr sap
7792 )
7793
7794 {
7795 AlnMsg2Ptr amp1, amp2;
7796 SegmenT seg;
7797 Int4 len1, len2, i;
7798 Int4 seg_i, seg_n, seg_start, seg_stop;
7799
7800 if (udp->seq1 == NULL || udp->seq2 == NULL) return;
7801 len1 = StringLen (udp->seq1);
7802 len2 = StringLen (udp->seq2);
7803
7804 seg = CreateSegment (pict, 0, 0);
7805 AddAttribute (seg, COLOR_ATT, RED_COLOR, 0, 0, 0, 0);
7806
7807 seg_n = AlnMgr2GetNumSegs(sap);
7808 for (seg_i = 1; seg_i<=seg_n; seg_i++) {
7809 AlnMgr2GetNthSegmentRange(sap, seg_i, &seg_start, &seg_stop);
7810
7811 amp1 = AlnMsgNew2 ();
7812 amp2 = AlnMsgNew2 ();
7813 if (amp1 == NULL || amp2 == NULL) return;
7814
7815 amp1->from_aln = seg_start;
7816 amp1->to_aln = seg_stop;
7817 amp1->row_num = 1;
7818
7819 amp2->from_aln = seg_start;
7820 amp2->to_aln = seg_stop;
7821 amp2->row_num = 2;
7822
7823 AlnMgr2GetNextAlnBit (sap, amp1);
7824 AlnMgr2GetNextAlnBit (sap, amp2);
7825
7826 if (amp1->to_row - amp1->from_row == amp2->to_row - amp2->from_row &&
7827 amp1->type == AM_SEQ && amp2->type == AM_SEQ) {
7828 for (i=0; i<seg_stop-seg_start+1; i++) {
7829 if (udp->seq1[amp1->from_row+i] != udp->seq2[amp2->from_row+i]) {
7830
7831 /* record for accurate scrolling to text view */
7832 ValNodeAddInt (&(udp->mismatches), 0, i);
7833
7834 AddLine (seg, seg_start+i, top, seg_start+i, bottom, FALSE, 0);
7835 }
7836 }
7837 }
7838
7839 AlnMsgFree2 (amp1);
7840 AlnMsgFree2 (amp2);
7841 }
7842 }
7843
7844 static void DrawAlignBits (
7845 UpsDataPtr udp,
7846 SegmenT pict,
7847 Int4 top,
7848 Int4 bottom,
7849 Int4 row,
7850 Int4 pos1,
7851 Int4 pos2,
7852 SeqAlignPtr sap
7853 )
7854
7855 {
7856 AlnMsg2Ptr amp;
7857 Int4 len, start, stop, from, to;
7858 Char str [96];
7859 Boolean wasgap;
7860
7861 amp = AlnMsgNew2 ();
7862 if (amp == NULL) return;
7863
7864 amp->from_aln = 0;
7865 amp->to_aln = -1;
7866 amp->row_num = row;
7867
7868 start = 0;
7869 stop = 0;
7870 from = 0;
7871 to = 0;
7872 wasgap = FALSE;
7873
7874 while (AlnMgr2GetNextAlnBit (sap, amp)) {
7875 len = amp->to_row - amp->from_row + 1;
7876 stop = start + len;
7877 if (amp->type == AM_GAP) {
7878 if (wasgap) {
7879 to = stop;
7880 } else {
7881 AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
7882 wasgap = TRUE;
7883 from = start;
7884 to = stop;
7885 }
7886 } else {
7887 if (wasgap) {
7888
7889 /* record for accurate scrolling to text view */
7890 ValNodeAddInt (&(udp->indels), 0, from);
7891
7892 AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
7893 wasgap = FALSE;
7894 from = start;
7895 to = stop;
7896 } else {
7897 to = stop;
7898 }
7899 }
7900 start += len;
7901 }
7902
7903 if (to > from) {
7904 if (wasgap) {
7905
7906 /* record for accurate scrolling to text view */
7907 ValNodeAddInt (&(udp->indels), 0, from);
7908
7909 AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
7910 } else {
7911 AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
7912 }
7913 }
7914
7915 AlnMsgFree2 (amp);
7916
7917 sprintf (str, "%ld", (long) pos1);
7918 AddLabel (pict, 0, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
7919
7920 sprintf (str, "%ld", (long) pos2);
7921 AddLabel (pict, to, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
7922 }
7923
7924 static SegmenT MakeAlignDetails (
7925 UpsDataPtr udp,
7926 CharPtr strid1,
7927 CharPtr strid2,
7928 SeqAlignPtr sap
7929 )
7930
7931 {
7932 Int4 aln_length;
7933 SegmenT pict;
7934 Int4 top, bottom;
7935
7936 pict = CreatePicture ();
7937 if (sap == NULL) return pict;
7938
7939 aln_length = udp->aln_length;
7940
7941 top = 0;
7942 bottom = top - 10;
7943
7944 DrawAlignBits (udp, pict, top, bottom, 1, udp->old5 + 1, udp->old5 + udp->olda, sap);
7945
7946 /*
7947 AddLabel (pict, aln_length / 2, bottom, strid1, SMALL_TEXT, 5, LOWER_CENTER, 0);
7948 */
7949
7950 top = 30;
7951 bottom = top - 10;
7952
7953 if (udp->revcomp) {
7954 DrawAlignBits (udp, pict, top, bottom, 2, udp->new3 + udp->newa, udp->new3 + 1, sap);
7955 } else {
7956 DrawAlignBits (udp, pict, top, bottom, 2, udp->new5 + 1, udp->new5 + udp->newa, sap);
7957 }
7958
7959 /*
7960 AddLabel (pict, aln_length / 2, top, strid2, SMALL_TEXT, 5, UPPER_CENTER, 0);
7961 */
7962
7963 top = 15;
7964 bottom = top - 10;
7965
7966 DrawAlignDiffs (udp, pict, top, bottom, sap);
7967
7968 return pict;
7969 }
7970
7971 static CharPtr MakeAlignSequence (
7972 UpsDataPtr udp,
7973 SeqAlignPtr sap,
7974 Int4 row,
7975 CharPtr seq
7976 )
7977
7978 {
7979 CharPtr aln;
7980 AlnMsg2Ptr amp;
7981 Int4 aln_length, len, lens, start, stop, from, to, i, j;
7982
7983 if (udp == NULL || sap == NULL || seq == NULL || udp->aln_length < 1) return NULL;
7984 lens = StringLen (seq);
7985
7986 aln = (CharPtr) MemNew (sizeof (Char) * (udp->aln_length + 2));
7987 if (aln == NULL) return NULL;
7988 aln_length = udp->aln_length;
7989 MemSet ((Pointer) aln, '-', aln_length);
7990
7991 amp = AlnMsgNew2 ();
7992 if (amp == NULL) return aln;
7993
7994 amp->from_aln = 0;
7995 amp->to_aln = -1;
7996 amp->row_num = row;
7997
7998 start = 0;
7999 stop = 0;
8000 from = 0;
8001 to = 0;
8002
8003 while (AlnMgr2GetNextAlnBit (sap, amp)) {
8004 len = amp->to_row - amp->from_row + 1;
8005 stop = start + len;
8006
8007 if (amp->type == AM_SEQ) {
8008 for (i = start, j = amp->from_row; i < stop && j < lens; i++, j++) {
8009 aln [i] = seq [j];
8010 }
8011 }
8012 start += len;
8013 }
8014
8015 AlnMsgFree2 (amp);
8016
8017 return aln;
8018 }
8019
8020 static void PrintTAln (ButtoN b)
8021
8022 {
8023 AsnIoPtr aip;
8024 Char path [PATH_MAX];
8025 UpsDataPtr udp;
8026
8027 udp = (UpsDataPtr) GetObjectExtra (b);
8028 if (udp == NULL) return;
8029 TmpNam (path);
8030 aip = AsnIoOpen (path, "w");
8031 if (aip != NULL) {
8032 SeqAlignAsnWrite (udp->salp, aip, NULL);
8033 AsnIoClose (aip);
8034 LaunchGeneralTextViewer (path, "Update Sequence Alignment");
8035 }
8036 FileRemove (path);
8037 }
8038
8039 static void PrintGAln (ButtoN b)
8040
8041 {
8042 UpsDataPtr udp;
8043
8044 udp = (UpsDataPtr) GetObjectExtra (b);
8045 if (udp == NULL) return;
8046 PrintViewer (udp->overview);
8047 PrintViewer (udp->details);
8048 }
8049
8050 static void CalculateOverhangs (
8051 UpsDataPtr udp
8052 )
8053
8054 {
8055 Int4 aln_length;
8056 Uint2 entityID;
8057 SeqAlignPtr sap;
8058 SeqEntryPtr sep;
8059 Int4 stopold, startold, lenold, stopnew, startnew, lennew;
8060
8061 if (udp == NULL) return;
8062 sap = udp->salp;
8063 if (sap == NULL) return;
8064 aln_length = AlnMgr2GetAlnLength (sap, FALSE);
8065 AlnMgr2GetNthSeqRangeInSA (sap, 1, &startold, &stopold);
8066 AlnMgr2GetNthSeqRangeInSA (sap, 2, &startnew, &stopnew);
8067 lenold = udp->oldbsp->length;
8068 lennew = udp->newbsp->length;
8069
8070 udp->old5 = startold;
8071 udp->old3 = lenold - stopold - 1;
8072 udp->olda = stopold - startold + 1;
8073
8074 udp->new5 = startnew;
8075 udp->new3 = lennew - stopnew - 1;
8076 udp->newa = stopnew - startnew + 1;
8077
8078 udp->aln_length = aln_length;
8079 udp->startmax = MAX (startold, startnew);
8080 udp->stopmax = MAX (aln_length + lenold - stopold, aln_length + lennew - stopnew);
8081
8082 udp->strandold = AlnMgr2GetNthStrand (sap, 1);
8083 udp->strandnew = AlnMgr2GetNthStrand (sap, 2);
8084
8085 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
8086 sep = GetTopSeqEntryForEntityID (entityID);
8087 SeqEntrySetScope (sep);
8088 udp->seq1 = GetSequenceByBsp (udp->oldbsp);
8089 SeqEntrySetScope (NULL);
8090
8091 entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
8092 sep = GetTopSeqEntryForEntityID (entityID);
8093 SeqEntrySetScope (sep);
8094 udp->seq2 = GetSequenceByBsp (udp->newbsp);
8095 SeqEntrySetScope (NULL);
8096
8097 udp->aln1 = MakeAlignSequence (udp, sap, 1, udp->seq1);
8098 udp->aln2 = MakeAlignSequence (udp, sap, 2, udp->seq2);
8099
8100 udp->log10_aln_length = 1;
8101 while (aln_length >= 10) {
8102 aln_length /= 10;
8103 (udp->log10_aln_length)++;
8104 }
8105 }
8106
8107 static Int4 CalculateBestScale (
8108 UpsDataPtr udp,
8109 VieweR vwr,
8110 SegmenT pict
8111 )
8112
8113 {
8114 BoxInfo box;
8115 Int2 i;
8116 Int4 max, worldwid, portwid;
8117 RecT r;
8118 Int4 scaleX, oldscaleX;
8119 Int4 wid;
8120
8121 ObjectRect (vwr, &r);
8122 InsetRect (&r, 4, 4);
8123 wid = (Int4) (r.right - r.left + 1);
8124
8125 SegmentBox (pict, &box);
8126 oldscaleX = (box.right - box.left + wid - 1) / wid;
8127 RecalculateSegment (pict, oldscaleX, 1);
8128 SegmentBox (pict, &box);
8129 portwid = wid * oldscaleX;
8130 worldwid = box.right - box.left + 20 * oldscaleX + 1;
8131 max = MAX (worldwid, portwid);
8132 scaleX = (max + wid - 1) / wid;
8133 i = 0;
8134 while (i < 10 && (scaleX > oldscaleX || portwid < worldwid)) {
8135 oldscaleX = scaleX;
8136 RecalculateSegment (pict, oldscaleX, 1);
8137 SegmentBox (pict, &box);
8138 portwid = wid * oldscaleX;
8139 worldwid = box.right - box.left + 20 * oldscaleX + 1;
8140 max = MAX (worldwid, portwid);
8141 scaleX = (max + wid - 1) / wid;
8142 i++;
8143 }
8144
8145 return scaleX;
8146 }
8147
8148 static Uint1 leftTriFillSym [] = {
8149 0x0C, 0x3C, 0xFC, 0x3C, 0x0C, 0x00, 0x00, 0x00
8150 };
8151 static Uint1 rightTriFillSym [] = {
8152 0xC0, 0xF0, 0xFC, 0xF0, 0xC0, 0x00, 0x00, 0x00
8153 };
8154
8155 static void LetDraw (
8156 PaneL pnl
8157 )
8158
8159 {
8160 Char ch1, ch2;
8161 Int2 i, k, q, left, top, bottom, arrowwidth;
8162 size_t len;
8163 Int4 offset, j, pos, realpos;
8164 RecT r, x;
8165 BaR sb;
8166 Char str [32];
8167 UpsDataPtr udp;
8168
8169 udp = (UpsDataPtr) GetObjectExtra (pnl);
8170 if (udp == NULL) return;
8171
8172 ObjectRect (pnl, &r);
8173 InsetRect (&r, 4, 4);
8174
8175 sb = GetSlateHScrollBar ((SlatE) pnl);
8176 offset = GetBarValue (sb);
8177
8178 SelectFont (SetSmallFont ());
8179
8180 /* draw top (new) letters */
8181
8182 if (udp->aln2 != NULL)
8183 {
8184 MoveTo (r.left, r.top + 8 + 3 * udp->lineheight);
8185 for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
8186 PaintChar (udp->aln2 [j]);
8187 }
8188 }
8189
8190 /* draw bottom (old) letters */
8191
8192 if (udp->aln1 != NULL)
8193 {
8194 MoveTo (r.left, r.top + 8 + 5 * udp->lineheight);
8195 for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
8196 PaintChar (udp->aln1 [j]);
8197 }
8198 }
8199
8200 /* draw recombination arrows */
8201
8202 arrowwidth = MIN (6, udp->charwidth);
8203 if (udp->recomb1 >= offset && udp->recomb1 <= offset + udp->maxchars) {
8204 left = r.left + udp->charwidth * (udp->recomb1 - offset);
8205 LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
8206 CopyBits (&x, leftTriFillSym);
8207 }
8208
8209 if (udp->recomb2 >= offset && udp->recomb2 <= offset + udp->maxchars) {
8210 left = r.left + udp->charwidth * (udp->recomb2 - offset - 1);
8211 LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
8212 CopyBits (&x, rightTriFillSym);
8213 }
8214
8215 if (udp->aln1 == NULL || udp->aln2 == NULL)
8216 {
8217 return;
8218 }
8219 /* draw red mismatch lines */
8220
8221 Red ();
8222 top = r.top + 8 + 4 * udp->lineheight - Ascent ();
8223 bottom = top + udp->lineheight - 2;
8224
8225 for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
8226 ch1 = udp->aln1 [j];
8227 ch2 = udp->aln2 [j];
8228 if (ch1 == ch2) {
8229 } else if (ch1 == '-' || ch2 == '-') {
8230 } else {
8231 left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
8232 MoveTo (left, top);
8233 LineTo (left, bottom);
8234 }
8235 }
8236 Black ();
8237
8238 /* draw top (new) tick marks and coordinates */
8239
8240 bottom = r.top + 8 + 3 * udp->lineheight - Ascent () - 2;
8241 top = bottom - 5;
8242 i = 0;
8243 j = offset;
8244 pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 2);
8245 while (pos < 1 && i < udp->maxchars && j < udp->aln_length) {
8246 i++;
8247 j++;
8248 pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 2);
8249 }
8250 for (; i < udp->maxchars + udp->log10_aln_length && j < udp->aln_length; i++, j++) {
8251 ch1 = udp->aln2 [j];
8252 if (ch1 != '-') {
8253 if (udp->revcomp) {
8254 realpos = (udp->newbsp->length - pos - 1);
8255 } else {
8256 realpos = pos;
8257 }
8258 if (((realpos + 1) % 10) == 0) {
8259 left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
8260 if (i < udp->maxchars) {
8261 MoveTo (left, top);
8262 LineTo (left, bottom);
8263 }
8264 sprintf (str, "%ld", (long) (realpos + 1));
8265 len = StringLen (str);
8266 if (len <= j + 1) {
8267 k = i - len + 1;
8268 q = 0;
8269 if (k < 0) {
8270 q -= k;
8271 k = 0;
8272 }
8273 if (q < len) {
8274 left = r.left + k * udp->charwidth;
8275 MoveTo (left, r.top + 8 + udp->lineheight);
8276 while (k < udp->maxchars && q < len) {
8277 PaintChar (str [q]);
8278 k++;
8279 q++;
8280 }
8281 }
8282 }
8283 } else if (((realpos + 1) % 5) == 0) {
8284 left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
8285 if (i < udp->maxchars) {
8286 MoveTo (left, top + 3);
8287 LineTo (left, bottom);
8288 }
8289 }
8290 pos++;
8291 }
8292 }
8293
8294 /* draw bottom (old) tick marks and coordinates */
8295
8296 top = r.top + 8 + 6 * udp->lineheight - Ascent () + 2;
8297 bottom = top + 5;
8298 i = 0;
8299 j = offset;
8300 pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 1);
8301 while (pos < 1 && i < udp->maxchars && j < udp->aln_length) {
8302 i++;
8303 j++;
8304 pos = AlnMgr2MapSeqAlignToBioseq (udp->salp, j, 1);
8305 }
8306 for (; i < udp->maxchars + udp->log10_aln_length && j < udp->aln_length; i++, j++) {
8307 ch1 = udp->aln1 [j];
8308 if (ch1 != '-') {
8309 if (((pos + 1) % 10) == 0) {
8310 left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
8311 if (i < udp->maxchars) {
8312 MoveTo (left, top);
8313 LineTo (left, bottom);
8314 }
8315 sprintf (str, "%ld", (long) (pos + 1));
8316 len = StringLen (str);
8317 if (len <= j + 1) {
8318 k = i - len + 1;
8319 q = 0;
8320 if (k < 0) {
8321 q -= k;
8322 k = 0;
8323 }
8324 if (q < len) {
8325 left = r.left + k * udp->charwidth;
8326 MoveTo (left, r.top + 8 + 7 * udp->lineheight);
8327 while (k < udp->maxchars && q < len) {
8328 PaintChar (str [q]);
8329 k++;
8330 q++;
8331 }
8332 }
8333 }
8334 } else if (((pos + 1) % 5) == 0) {
8335 left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
8336 if (i < udp->maxchars) {
8337 MoveTo (left, top);
8338 LineTo (left, bottom - 3);
8339 }
8340 }
8341 pos++;
8342 }
8343 }
8344 SelectFont (systemFont);
8345 }
8346
8347 static void LetScrl (
8348 BaR sb,
8349 SlatE slt,
8350 Int4 newval,
8351 Int4 oldval
8352 )
8353
8354 {
8355 RecT r;
8356 UpsDataPtr udp;
8357
8358 udp = (UpsDataPtr) GetObjectExtra (slt);
8359 if (udp == NULL) return;
8360
8361 ObjectRect (udp->letters, &r);
8362 InsetRect (&r, 4, 4);
8363 Select (udp->letters);
8364 if (ABS (oldval - newval) < udp->maxchars) {
8365 ScrollRect (&r, (oldval - newval) * udp->charwidth, 0);
8366 } else {
8367 InsetRect (&r, -2, -2);
8368 InvalRect (&r);
8369 }
8370 Update ();
8371 }
8372
8373 static void DtlClck (
8374 VieweR vwr,
8375 SegmenT pict,
8376 PoinT pt
8377 )
8378
8379 {
8380 Int4 goHere;
8381 Int4 offset;
8382 Int4 maxover2;
8383 PntInfo pnt;
8384 BaR sb;
8385 UpsDataPtr udp;
8386 ValNodePtr vnp;
8387
8388 udp = (UpsDataPtr) GetViewerData (vwr);
8389 if (udp == NULL) return;
8390
8391 sb = GetSlateHScrollBar ((SlatE) udp->letters);
8392
8393 MapViewerToWorld (vwr, pt, &pnt);
8394 maxover2 = udp->maxchars / 2;
8395 if (pnt.x <= 0) {
8396 pnt.x = 0;
8397 } else if (pnt.x >= udp->aln_length) {
8398 pnt.x = udp->aln_length - udp->maxchars;
8399 } else if (pnt.x >= maxover2) {
8400
8401 offset = GetBarValue (sb);
8402
8403 /* look for clicks within 5 pixels of an indel start or a mismatch */
8404
8405 goHere = -1;
8406 for (vnp = udp->indels; vnp != NULL && goHere < 0; vnp = vnp->next) {
8407 if (ABS (pnt.x - vnp->data.intvalue) < udp->scaleX * 5) {
8408 goHere = vnp->data.intvalue;
8409 }
8410 }
8411 for (vnp = udp->mismatches; vnp != NULL && goHere < 0; vnp = vnp->next) {
8412 if (ABS (pnt.x - vnp->data.intvalue) < udp->scaleX * 5) {
8413 goHere = vnp->data.intvalue;
8414 }
8415 }
8416
8417 if (goHere >= 0) {
8418 pnt.x = goHere;
8419 } else {
8420 /* if already visible, no need to scroll */
8421 if (pnt.x - maxover2 > offset && pnt.x - maxover2 < offset + maxover2 - 5) return;
8422 if (pnt.x - maxover2 < offset && pnt.x - maxover2 > offset - maxover2 + 5) return;
8423 }
8424
8425 /* go left 1/2 screen so desired point is in the middle */
8426
8427 pnt.x -= maxover2;
8428 }
8429
8430 ResetClip ();
8431 SetBarValue (sb, pnt.x);
8432 Update ();
8433 }
8434
8435 static void FrameVwr (
8436 VieweR vwr,
8437 SegmenT pict
8438 )
8439
8440 {
8441 RecT r;
8442
8443 ResetClip ();
8444 ObjectRect (vwr, &r);
8445 FrameRect (&r);
8446 }
8447
8448 static int LIBCALLBACK SortVnpByInt (VoidPtr ptr1, VoidPtr ptr2)
8449
8450 {
8451 ValNodePtr vnp1;
8452 ValNodePtr vnp2;
8453
8454 if (ptr1 == NULL || ptr2 == NULL) return 0;
8455 vnp1 = *((ValNodePtr PNTR) ptr1);
8456 vnp2 = *((ValNodePtr PNTR) ptr2);
8457 if (vnp1 == NULL || vnp2 == NULL) return 0;
8458
8459 if (vnp1->data.intvalue > vnp2->data.intvalue) {
8460 return 1;
8461 } else if (vnp1->data.intvalue < vnp2->data.intvalue) {
8462 return -1;
8463 }
8464
8465 return 0;
8466 }
8467
8468
8469 static void UpdateSequenceFormMessage (ForM f, Int2 mssg)
8470
8471 {
8472 BaseFormPtr bfp;
8473 StdEditorProcsPtr sepp;
8474
8475 bfp = (BaseFormPtr) GetObjectExtra (f);
8476 if (bfp == NULL) return;
8477 switch (mssg) {
8478 case VIB_MSG_CLOSE :
8479 Remove (f);
8480 break;
8481 case VIB_MSG_QUIT :
8482 QuitProc ();
8483 break;
8484 default :
8485 sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
8486 if (sepp != NULL && sepp->handleMessages != NULL) {
8487 sepp->handleMessages (f, mssg);
8488 }
8489 break;
8490 }
8491 }
8492
8493 static void FreeUdpFields (UpsDataPtr udp)
8494 {
8495 Uint2 entityID;
8496
8497 udp->ovpict = DeletePicture (udp->ovpict);
8498 udp->dtpict = DeletePicture (udp->dtpict);
8499 udp->salp = SeqAlignFree (udp->salp);
8500 entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
8501 udp->newbsp = ObjMgrFreeByEntityID (entityID);
8502 udp->seq1 = MemFree (udp->seq1);
8503 udp->seq2 = MemFree (udp->seq2);
8504 udp->aln1 = MemFree (udp->aln1);
8505 udp->aln1 = NULL;
8506 udp->aln2 = MemFree (udp->aln2);
8507 udp->aln2 = NULL;
8508 udp->indels = ValNodeFree (udp->indels);
8509 udp->mismatches = ValNodeFree (udp->mismatches);
8510 udp->transl_except_list = ValNodeFree (udp->transl_except_list);
8511 udp->affected_variation_features = ValNodeFree (udp->affected_variation_features);
8512 }
8513
8514 static void CleanupUpdateSequenceForm (GraphiC g, VoidPtr data)
8515
8516 {
8517 UpsDataPtr udp;
8518
8519 udp = (UpsDataPtr) data;
8520 if (udp != NULL)
8521 FreeUdpFields (udp);
8522 StdCleanupFormProc (g, data);
8523 }
8524
8525 static CharPtr txt1 =
8526 "Sequence Relationship displays sequence lengths";
8527
8528 static CharPtr txt2 =
8529 "Alignment Details displays sequence positions";
8530
8531 static CharPtr txt3 =
8532 "Click above to scroll Alignment Text position";
8533
8534 /*------------------------------------------------------------------*/
8535 /* */
8536 /* DetermineButtonState () -- Enable/disable buttons based on the */
8537 /* nature of the alignment. */
8538 /* */
8539 /*------------------------------------------------------------------*/
8540
8541 static void DetermineButtonState (UpsDataPtr udp,
8542 ButtoN PNTR replaceButtonPtr,
8543 ButtoN PNTR extend5ButtonPtr,
8544 ButtoN PNTR extend3ButtonPtr,
8545 ButtoN PNTR patchButtonPtr)
8546 {
8547 BioSourcePtr biop1;
8548 BioSourcePtr biop2;
8549 SeqMgrDescContext dcontext;
8550 Uint2 entityID;
8551 SeqMgrFeatContext fcontext;
8552 OrgRefPtr orp1;
8553 OrgRefPtr orp2;
8554 SeqDescrPtr sdp;
8555 SeqFeatPtr sfp;
8556
8557 /* If no alignment then disable the patch button */
8558
8559 if (udp->salp == NULL) {
8560 if (udp->do_update && patchButtonPtr != NULL && *patchButtonPtr != NULL) {
8561 Disable (*patchButtonPtr);
8562 }
8563 if (!udp->do_update)
8564 {
8565 Disable (*replaceButtonPtr);
8566 }
8567 }
8568
8569 /* Extend 5' */
8570
8571 else if (udp->new5 > udp->old5 && udp->new3 < udp->old3) {
8572 SetValue (udp->rmc, UPDATE_EXTEND5);
8573 Disable (*extend3ButtonPtr);
8574 udp->recomb2 = udp->aln_length;
8575 if (! udp->do_update) {
8576 Disable (*replaceButtonPtr);
8577 }
8578 }
8579
8580 /* Extend 3' */
8581
8582 else if (udp->new5 < udp->old5 && udp->new3 > udp->old3) {
8583 SetValue (udp->rmc, UPDATE_EXTEND3);
8584 Disable (*extend5ButtonPtr);
8585 udp->recomb1 = 0;
8586 if (! udp->do_update) {
8587 Disable (*replaceButtonPtr);
8588 }
8589 }
8590
8591 /* Replace */
8592
8593 else {
8594 SetValue (udp->rmc, UPDATE_REPLACE);
8595 Disable (*extend5ButtonPtr);
8596 Disable (*extend3ButtonPtr);
8597 udp->recomb1 = 0;
8598 udp->recomb2 = udp->aln_length;
8599 }
8600
8601 switch (udp->rmcval)
8602 {
8603 case UPDATE_REPLACE:
8604 if (Enabled (*replaceButtonPtr))
8605 {
8606 SetValue (udp->rmc, UPDATE_REPLACE);
8607 }
8608 break;
8609 case UPDATE_EXTEND5:
8610 if (Enabled (*extend5ButtonPtr))
8611 {
8612 SetValue (udp->rmc, UPDATE_EXTEND5);
8613 }
8614 break;
8615 case UPDATE_EXTEND3:
8616 if (Enabled (*extend3ButtonPtr))
8617 {
8618 SetValue (udp->rmc, UPDATE_EXTEND3);
8619 }
8620 break;
8621 case UPDATE_PATCH:
8622 if (Enabled (*patchButtonPtr))
8623 {
8624 SetValue (udp->rmc, UPDATE_PATCH);
8625 }
8626 break;
8627 }
8628
8629 /* If no features, must be sequence update only */
8630
8631 entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
8632 if (! SeqMgrFeaturesAreIndexed (entityID))
8633 SeqMgrIndexFeatures (entityID, NULL);
8634
8635 sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &fcontext);
8636 if (sfp == NULL) {
8637 SetValue (udp->sfb, UPDATE_SEQUENCE_ONLY);
8638 Disable (udp->sfb);
8639 Disable (udp->replace_all);
8640 Disable (udp->nobm);
8641 }
8642
8643 /* If different organisms, must be feature propagation only */
8644
8645 orp1 = NULL;
8646 orp2 = NULL;
8647 sdp = SeqMgrGetNextDescriptor (udp->oldbsp, NULL, Seq_descr_source, &dcontext);
8648 if (sdp != NULL) {
8649 biop1 = (BioSourcePtr) sdp->data.ptrvalue;
8650 if (biop1 != NULL) {
8651 orp1 = biop1->org;
8652 }
8653 }
8654 sdp = SeqMgrGetNextDescriptor (udp->newbsp, NULL, Seq_descr_source, &dcontext);
8655 if (sdp != NULL) {
8656 biop2 = (BioSourcePtr) sdp->data.ptrvalue;
8657 if (biop2 != NULL) {
8658 orp2 = biop2->org;
8659 }
8660 }
8661 if (orp1 != NULL && orp2 != NULL) {
8662 if (StringICmp (orp1->taxname, orp2->taxname) != 0) {
8663 if (sfp != NULL) {
8664 SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
8665 Disable (udp->sfb);
8666 udp->diffOrgs = TRUE;
8667 if (FALSE == udp->isSet)
8668 Message (MSG_OK, "Organisms are different, so features will"
8669 " be propagated, but sequence will not be changed");
8670 } else {
8671 /* no features, cannot do anything */
8672 SetValue (udp->sfb, UPDATE_CHOICE_NOT_SET);
8673 Disable (udp->sfb);
8674 Disable (udp->replace_all);
8675 Disable (udp->nobm);
8676 if (FALSE == udp->isSet)
8677 Message (MSG_OK, "Organisms are different, no features"
8678 " to propagate, so nothing to do");
8679 }
8680 Disable (udp->rmc);
8681 }
8682 }
8683
8684 /* If either sequence is not raw and not indexer version, only allow feature propagation */
8685 if (!indexerVersion &&
8686 (udp->oldbsp->repr != Seq_repr_raw || udp->newbsp->repr != Seq_repr_raw)) {
8687 SetValue (udp->sfb, UPDATE_FEATURES_ONLY);
8688 Disable (udp->sfb);
8689 }
8690
8691 /* Disable accept button unless rmc and sfb are both preset */
8692
8693 UpdateAccept (udp->rmc);
8694
8695 }
8696
8697 static void ChangeUpdateReplaceAll (ButtoN b)
8698 {
8699 UpsDataPtr udp;
8700
8701 if (b == NULL) return;
8702 udp = (UpsDataPtr) GetObjectExtra (b);
8703 if (udp == NULL) return;
8704
8705 if (GetStatus (b))
8706 {
8707 Disable (udp->nobm);
8708 }
8709 else
8710 {
8711 Enable (udp->nobm);
8712 }
8713 /* update accept button */
8714 UpdateAccept (udp->rmc);
8715 }
8716
8717 static void CancelUpdate (ButtoN b)
8718 {
8719 UpsDataPtr udp;
8720
8721 if (b == NULL) return;
8722 udp = (UpsDataPtr) GetObjectExtra (b);
8723 if (udp == NULL) return;
8724 CloseOutSequenceUpdateLog (udp);
8725 StdCancelButtonProc (b);
8726 }
8727
8728 static GrouP CreateUpdateOperationsGroup (GrouP parent, UpsDataPtr udp)
8729 {
8730 GrouP g;
8731 GrouP gp1, gp2, gp3;
8732 ButtoN b1 = NULL, b2 = NULL, b3 = NULL, b4 = NULL;
8733
8734 if (udp == NULL) return NULL;
8735
8736 g = HiddenGroup (parent, -1, 0, NULL);
8737 SetGroupSpacing (g, 5, 5);
8738
8739 gp1 = NormalGroup (g, 4, 0, "Alignment Relationship", programFont, NULL);
8740 udp->rmc = HiddenGroup (gp1, 4, 0, UpdateButtons);
8741 SetObjectExtra (udp->rmc, (Pointer) udp, NULL);
8742 SetGroupSpacing (udp->rmc, 10, 5);
8743 if (udp->do_update) {
8744 b1 = RadioButton (udp->rmc, "Replace");
8745 } else {
8746 b1= RadioButton (udp->rmc, "Extend Both Ends");
8747 }
8748 b2 = RadioButton (udp->rmc, "Extend 5'");
8749 b3 = RadioButton (udp->rmc, "Extend 3'");
8750 if (udp->do_update) {
8751 b4 = RadioButton (udp->rmc, "Patch");
8752 } else {
8753 b4 = NULL;
8754 }
8755
8756 if (udp->do_update) {
8757 gp2 = NormalGroup (g, 4, 0, "Update Operation", programFont, NULL);
8758 udp->sfb = HiddenGroup (gp2, 3, 0, UpdateAccept);
8759 SetObjectExtra (udp->sfb, (Pointer) udp, NULL);
8760 SetGroupSpacing (udp->sfb, 10, 5);
8761 RadioButton (udp->sfb, "Sequence");
8762 RadioButton (udp->sfb, "Features");
8763 RadioButton (udp->sfb, "Sequence + Features");
8764
8765 udp->keepProteinIDs = CheckBox (g, "Keep Protein IDs", NULL);
8766
8767 gp3 = NormalGroup (g, 1, 0, "Feature Policy", programFont, NULL);
8768 udp->replace_all = CheckBox (gp3, "Replace All Features", ChangeUpdateReplaceAll);
8769 SetObjectExtra (udp->replace_all, (Pointer) udp, NULL);
8770 SetValue (udp->replace_all, FALSE);
8771
8772 udp->nobm = NormalGroup (gp3, 5, 0, "Duplicate Features Only", programFont, UpdateAccept);
8773 SetObjectExtra (udp->nobm, (Pointer) udp, NULL);
8774 SetGroupSpacing (udp->nobm, 10, 5);
8775 RadioButton (udp->nobm, "New");
8776 RadioButton (udp->nobm, "Old");
8777 RadioButton (udp->nobm, "Both");
8778 RadioButton (udp->nobm, "Merge");
8779 RadioButton (udp->nobm, "Replace");
8780
8781 AlignObjects (ALIGN_CENTER, (HANDLE) gp1, (HANDLE) gp2,
8782 (HANDLE) udp->keepProteinIDs,
8783 (HANDLE) gp3, NULL);
8784 }
8785 /* Enable/disable buttons based on the nature of the alignment */
8786
8787 DetermineButtonState (udp, &b1, &b2, &b3, &b4);
8788 return g;
8789
8790 }
8791
8792
8793 static void ChangeProteinUpdateStatus (ButtoN b)
8794 {
8795 UpsDataPtr udp;
8796
8797 udp = (UpsDataPtr) GetObjectExtra (b);
8798 if (udp == NULL) return;
8799 SetProteinOptionsEnable (udp);
8800 }
8801
8802 static void SkipUpdate (UpsDataPtr udp)
8803 {
8804 Char acc_str [256];
8805 SeqIdPtr sip, sip_next;
8806
8807 if (udp == NULL) return;
8808
8809 OpenSequenceUpdateLog (udp);
8810 if (udp->log_fp != NULL && udp->oldbsp != NULL && udp->oldbsp->id != NULL)
8811 {
8812 sip = SeqIdFindBest (udp->oldbsp->id, 0);
8813 if (sip != NULL)
8814 {
8815 sip_next = sip->next;
8816 sip->next = NULL;
8817 SeqIdWrite (sip, acc_str, PRINTID_REPORT, sizeof (acc_str));
8818 fprintf (udp->log_fp, "Skipped update for %s\n", acc_str);
8819 udp->data_in_log = TRUE;
8820 sip->next = sip_next;
8821 }
8822 }
8823
8824 /* if we are updating a set from a SeqSub, we don't want to free the SeqSub yet */
8825 if (udp->seqsubsep != NULL)
8826 {
8827 udp->newbsp = NULL;
8828 }
8829 FreeUdpFields (udp);
8830 UpdateNextBioseqInFastaSet (udp);
8831 }
8832
8833 static GrouP CreateExtraUpdateOptionsGroup (GrouP g, UpsDataPtr udp)
8834 {
8835 GrouP y, protein_options = NULL;
8836
8837 if (udp == NULL || g == NULL) return NULL;
8838
8839 y = HiddenGroup (g, -1, 0, NULL);
8840
8841 udp->add_cit_subs = CheckBox (y, "Add Cit-subs for Updated Sequences", NULL);
8842 udp->update_quality_scores_btn = NULL;
8843 if (! ISA_aa (udp->oldbsp->mol) && udp->do_update)
8844 {
8845 udp->update_quality_scores_btn = CheckBox (y, "Replace Quality Scores", NULL);
8846 SetStatus (udp->update_quality_scores_btn, TRUE);
8847
8848 udp->update_proteins = CheckBox (y, "Update Proteins for Updated Sequences", ChangeProteinUpdateStatus);
8849 SetObjectExtra (udp->update_proteins, (Pointer) udp, NULL);
8850 SetStatus (udp->update_proteins, FALSE);
8851 protein_options = HiddenGroup (y, 1, 0, NULL);
8852 udp->truncate_proteins_btn = CheckBox (protein_options,
8853 "Truncate retranslated proteins at stops",
8854 NULL);
8855 SetStatus (udp->truncate_proteins_btn,
8856 udp->truncate_proteins);
8857 udp->extend_proteins3_btn = CheckBox (protein_options,
8858 "Extend retranslated proteins without stops",
8859 NULL);
8860 udp->extend_proteins5_btn = CheckBox (protein_options,
8861 "Extend retranslated proteins without starts",
8862 NULL);
8863 udp->correct_cds_genes_btn = CheckBox (protein_options, "Correct CDS genes", NULL);
8864
8865 SetStatus (udp->extend_proteins3_btn, udp->extend_proteins3);
8866 SetStatus (udp->extend_proteins5_btn, udp->extend_proteins5);
8867 SetStatus (udp->correct_cds_genes_btn, udp->correct_cds_genes);
8868 }
8869 AlignObjects (ALIGN_CENTER, (HANDLE) udp->add_cit_subs,
8870 (HANDLE) udp->update_quality_scores_btn,
8871 (HANDLE) udp->update_proteins,
8872 (HANDLE) protein_options,
8873 NULL);
8874 return y;
8875 }
8876
8877 static void SkipUpdateBtn (ButtoN b)
8878 {
8879 UpsDataPtr udp;
8880
8881 udp = (UpsDataPtr) GetObjectExtra (b);
8882 if (udp == NULL) return;
8883 SafeHide (udp->form);
8884 Remove (udp->form);
8885
8886 SkipUpdate (udp);
8887 }
8888
8889 /*------------------------------------------------------------------*/
8890 /* */
8891 /* UpdateSequenceForm () -- Compares two sequences and displays a */
8892 /* window giving the user options on how */
8893 /* to update one from the other. */
8894 /* */
8895 /*------------------------------------------------------------------*/
8896
8897 static ForM UpdateSequenceForm (UpsDataPtr udp)
8898 {
8899 ButtoN b;
8900 GrouP c, g, y, k, x, z = NULL;
8901 Uint2 hgt;
8902 GrouP ppt0, ppt1, ppt2, ppt3;
8903 RecT r;
8904 BaR sb;
8905 Int4 scaleX;
8906 SeqIdPtr sip;
8907 Char strid1 [MAX_ID_LEN], strid2 [MAX_ID_LEN], txt0 [256];
8908 CharPtr title;
8909 WindoW w;
8910 GrouP misc_options;
8911 Int4 prompt_width = 400;
8912 GrouP left_panel;
8913 GrouP right_panel;
8914
8915 /* Check parameters */
8916
8917 if ((udp->oldbsp == NULL) || (udp->newbsp == NULL))
8918 return NULL;
8919
8920 /* Create window */
8921
8922 if (udp->do_update) {
8923 title = "Update Sequence";
8924 } else {
8925 title = "Extend Sequence";
8926 }
8927 w = FixedWindow (-50, -33, -10, -10, title, NULL);
8928
8929 if (w == NULL)
8930 return NULL;
8931
8932 if (FALSE == udp->isSet)
8933 SetObjectExtra (w, (Pointer) udp, CleanupUpdateSequenceForm);
8934 udp->form = (ForM) w;
8935
8936 /* Get string IDs for the Bioseqs */
8937
8938 sip = SeqIdFindWorst (udp->oldbsp->id);
8939 SeqIdWrite (sip, strid1, PRINTID_REPORT, sizeof (strid1) - 1);
8940 sip = SeqIdFindWorst (udp->newbsp->id);
8941 SeqIdWrite (sip, strid2, PRINTID_REPORT, sizeof (strid2) - 1);
8942 if (StringNICmp (strid2, "SequinUpdateSequence", 20) == 0 &&
8943 udp->newbsp->id->next != NULL) {
8944 sip = SeqIdFindWorst (udp->newbsp->id->next);
8945 SeqIdWrite (sip, strid2, PRINTID_REPORT, sizeof (strid2) - 1);
8946 }
8947
8948 /* FIll in some of the data structure */
8949 /* for passing to the callbacks. */
8950
8951 udp->formmessage = UpdateSequenceFormMessage;
8952
8953 #ifdef WIN_MAC
8954 udp->activate = UpdateSequenceFormActivated;
8955 SetActivate (w, UpdateSequenceFormActivate);
8956 #endif
8957
8958 udp->diffOrgs = FALSE;
8959
8960 CalculateOverhangs (udp);
8961
8962 /* Display the sequences */
8963
8964 sprintf (txt0,
8965 "New sequence: %s - Length: %ld\nOld Sequence: %s - Length: %ld",
8966 strid2, (long) udp->newbsp->length, strid1,
8967 (long) udp->oldbsp->length);
8968 ppt0 = MultiLinePrompt (w, txt0, prompt_width, programFont);
8969
8970 x = HiddenGroup (w, 2, 0, NULL);
8971 left_panel = HiddenGroup (x, -1, 0, NULL);
8972 y = left_panel;
8973
8974 ppt1 = MultiLinePrompt (y, txt1, prompt_width, programFont);
8975 udp->overview = CreateViewer (y, prompt_width + Nlm_vScrollBarWidth, 100,
8976 FALSE, FALSE);
8977
8978 ppt2 = MultiLinePrompt (y, txt2, prompt_width, programFont);
8979 udp->details = CreateViewer (y, prompt_width + Nlm_vScrollBarWidth, 80,
8980 FALSE, FALSE);
8981
8982 ppt3 = MultiLinePrompt (y, txt3, prompt_width, programFont);
8983
8984 #ifdef WIN_MAC
8985 hgt = 90;
8986 #else
8987 hgt = 110;
8988 #endif
8989 udp->letters = AutonomousPanel4 (y, prompt_width + Nlm_vScrollBarWidth, hgt,
8990 LetDraw, NULL, LetScrl, 0, NULL, NULL);
8991 SetObjectExtra (udp->letters, (Pointer) udp, NULL);
8992
8993 if (indexerVersion && shftKey) {
8994 ButtoN b;
8995 z = HiddenGroup (y, 2, 0, NULL);
8996 SetGroupSpacing (z, 10, 3);
8997 b = PushButton (z, "Print Graphic", PrintGAln);
8998 SetObjectExtra (b, (Pointer) udp, NULL);
8999 b = PushButton (z, "Display Alignment", PrintTAln);
9000 SetObjectExtra (b, (Pointer) udp, NULL);
9001 }
9002
9003 udp->ovpict = NULL;
9004 udp->dtpict = NULL;
9005
9006 AlignObjects (ALIGN_CENTER, (HANDLE) udp->overview,
9007 (HANDLE) udp->details, (HANDLE) udp->letters,
9008 (HANDLE) ppt1, (HANDLE) ppt2,
9009 (HANDLE) ppt3, NULL);
9010
9011 right_panel = HiddenGroup (x, -1, 0, NULL);
9012 y = right_panel;
9013
9014 k = HiddenGroup (y, -1, 0, NULL);
9015 g = CreateUpdateOperationsGroup (k, udp);
9016 misc_options = CreateExtraUpdateOptionsGroup (k, udp);
9017 AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) misc_options, NULL);
9018
9019 c = HiddenGroup (w, 5, 0, NULL);
9020 if (udp->isSet)
9021 {
9022 udp->accept = DefaultButton (c, "Accept", AcceptRMCOrExtendSet);
9023 SetObjectExtra (udp->accept, (Pointer) udp, NULL);
9024 udp->acceptAll = DefaultButton (c, "Accept All", AcceptRMCOrExtendAll);
9025 SetObjectExtra (udp->acceptAll, (Pointer) udp, NULL);
9026 b = PushButton (c, "Skip", SkipUpdateBtn);
9027 SetObjectExtra (b, (Pointer) udp, NULL);
9028 }
9029 else
9030 {
9031 udp->accept = DefaultButton (c, "Accept", AcceptRMCOrExtend);
9032 SetObjectExtra (udp->accept, (Pointer) udp, NULL);
9033 }
9034
9035 b = PushButton (c, "Cancel", CancelUpdate);
9036 SetObjectExtra (b, (Pointer) udp, NULL);
9037 UpdateButtons (udp->rmc);
9038
9039 AlignObjects (ALIGN_CENTER,
9040 (HANDLE) ppt0,
9041 (HANDLE) x,
9042 (HANDLE) c, (HANDLE) z, NULL);
9043 RealizeWindow (w);
9044
9045 udp->ovpict = MakeAlignPicture (udp, strid1, strid2, udp->salp);
9046 scaleX = CalculateBestScale (udp, udp->overview, udp->ovpict);
9047 AttachPicture (udp->overview, udp->ovpict, 0, 0, UPPER_LEFT,
9048 scaleX, 1, FrameVwr);
9049
9050 udp->dtpict = MakeAlignDetails (udp, strid1, strid2, udp->salp);
9051 scaleX = CalculateBestScale (udp, udp->details, udp->dtpict);
9052 udp->scaleX = scaleX;
9053 AttachPicture (udp->details, udp->dtpict, 0, 0, UPPER_LEFT,
9054 scaleX, 1, FrameVwr);
9055 SetViewerData (udp->details, (Pointer) udp, NULL);
9056 SetViewerProcs (udp->details, DtlClck, NULL, NULL, NULL);
9057
9058 udp->indels = ValNodeSort (udp->indels, SortVnpByInt);
9059 udp->mismatches = ValNodeSort (udp->mismatches, SortVnpByInt);
9060
9061 SelectFont (SetSmallFont ());
9062 ObjectRect (udp->letters, &r);
9063 InsetRect (&r, 4, 4);
9064 udp->lineheight = LineHeight ();
9065 udp->charwidth = MaxCharWidth ();
9066 udp->maxchars = (r.right-r.left-2+udp->charwidth - 1) / udp->charwidth;
9067 SelectFont (systemFont);
9068
9069 sb = GetSlateHScrollBar ((SlatE) udp->letters);
9070 SetBarMax (sb, udp->aln_length - (Int4) udp->maxchars);
9071 CorrectBarPage (sb, (Int4) udp->maxchars - 1, (Int4) udp->maxchars - 1);
9072
9073 udp->recomb1 = -1;
9074 udp->recomb2 = -1;
9075
9076 return (ForM) w;
9077 }
9078
9079
9080 /*=====================================================================*/
9081 /* */
9082 /* PrepareToUpdateSequences () */
9083 /* */
9084 /*=====================================================================*/
9085
9086 static Boolean PrepareToUpdateSequences (UpsDataPtr udp)
9087 {
9088 ForM f;
9089
9090 if ( ! PrepareUpdatePtr (udp))
9091 {
9092 CloseOutSequenceUpdateLog (udp);
9093 return FALSE;
9094 }
9095
9096 if (TRUE == udp->useGUI)
9097 {
9098 if (udp->salp == NULL && udp->do_update &&
9099 (udp->no_aln_choice == UPDATE_REPLACE_THIS
9100 || udp->no_aln_choice == UPDATE_SKIP_THIS
9101 || udp->no_aln_choice == UPDATE_REPLACE_ALL
9102 || udp->no_aln_choice == UPDATE_REPLACE_THIS))
9103 {
9104 CalculateOverhangs (udp);
9105 DoAcceptRMCOrExtendSet (udp);
9106 UpdateNextBioseqInFastaSet (udp);
9107 }
9108 else
9109 {
9110 f = UpdateSequenceForm (udp);
9111 if (f == NULL)
9112 {
9113 CloseOutSequenceUpdateLog (udp);
9114 return FALSE;
9115 }
9116 Show (f);
9117 Select (f);
9118 SendHelpScrollMessage (helpForm, "Edit Menu", "Update Sequence");
9119 }
9120 }
9121 else {
9122 CalculateOverhangs (udp);
9123 DoAcceptRMCOrExtendSet (udp);
9124 }
9125 return TRUE;
9126 }
9127
9128 /*=====================================================================*/
9129 /* */
9130 /* FindMatchingBioseq () -- Callback function for exploring Bioseqs. */
9131 /* Finds the bioseq that matches a given */
9132 /* string ID. */
9133 /* */
9134 /*=====================================================================*/
9135
9136 static Boolean LIBCALLBACK FindMatchingBioseq (BioseqPtr bsp,
9137 SeqMgrBioseqContextPtr bContext)
9138 {
9139 Char currentId[MAX_ID_LEN];
9140 UpdateDataPtr pUpdateData;
9141 Int2 result;
9142 SeqIdPtr sip, sip_next;
9143
9144 pUpdateData = (UpdateDataPtr) bContext->userdata;
9145
9146 /* Get the string IDs for the current Bioseq */
9147
9148 for (sip = bsp->id; sip != NULL; sip = sip->next)
9149 {
9150 sip_next = sip->next;
9151 sip->next = NULL;
9152 SeqIdWrite (sip, currentId, PRINTID_TEXTID_ACC_ONLY,
9153 sizeof (currentId) - 1);
9154
9155 /* Compare it to the string ID of the new Bioseq */
9156
9157 result = StringICmp (pUpdateData->newId, currentId);
9158
9159 /* if TEXTID_ACC_ONLY doesn't match, try PRINTID_REPORT */
9160 if (result != 0)
9161 {
9162 SeqIdWrite (sip, currentId, PRINTID_REPORT,
9163 sizeof (currentId) - 1);
9164
9165 /* Compare it to the string ID of the new Bioseq */
9166
9167 result = StringICmp (pUpdateData->newId, currentId);
9168 }
9169
9170 sip->next = sip_next;
9171 /* If they match, save the Bioseq and quit searching */
9172
9173 if (0 == result) {
9174 pUpdateData->matchingBsp = bsp;
9175 return FALSE;
9176 }
9177 }
9178
9179 /* Else continue */
9180
9181 return TRUE;
9182 }
9183
9184 static Boolean SkipProteinInNucUpdate (SeqEntryPtr sep, UpsDataPtr udp)
9185 {
9186 Char newId[MAX_ID_LEN];
9187 SeqIdPtr sip;
9188 BioseqPtr bsp;
9189 Boolean rval = FALSE;
9190 MsgAnswer ans;
9191
9192 if (sep == NULL || ! IS_Bioseq (sep) || sep->data.ptrvalue == NULL || udp == NULL)
9193 {
9194 return FALSE;
9195 }
9196
9197 bsp = (BioseqPtr) sep->data.ptrvalue;
9198 if (ISA_na (bsp->mol))
9199 {
9200 return FALSE;
9201 }
9202
9203 sip = SeqIdFindWorst (bsp->id);
9204 SeqIdWrite (sip, newId, PRINTID_REPORT, sizeof (newId) - 1);
9205 ans = Message (MSG_YN, "Found a protein (%s) in the update file, expecting "
9206 "only nucleotides. Do you want to skip this sequence and continue?", newId);
9207 if (ans == ANS_YES)
9208 {
9209 rval = TRUE;
9210 fprintf (udp->log_fp, "Skipped protein Bioseq (%s) in nucleotide update\n", newId);
9211 udp->data_in_log = TRUE;
9212 }
9213 return rval;
9214 }
9215
9216 static void RemoveUpdateSet (UpsDataPtr udp)
9217 {
9218 #if 0
9219 ObjMgrPtr omp;