summaryrefslogtreecommitdiff
path: root/sequin/sequin9.c
diff options
context:
space:
mode:
authorAaron M. Ucko <ucko@debian.org>2005-03-23 17:39:07 +0000
committerAaron M. Ucko <ucko@debian.org>2005-03-23 17:39:07 +0000
commita7c5bff619aa4850d09825888b5f46c7cd086f11 (patch)
tree2ab2dd2ff2977a5e0bcfdd90a17ca4f1a73181fc /sequin/sequin9.c
parentbfbecafe8b6142e8356e8447f0822b43e94b64b7 (diff)
Load ncbi (6.1.20010709) into ncbi-tools6/branches/upstream/current.
Diffstat (limited to 'sequin/sequin9.c')
-rw-r--r--sequin/sequin9.c6957
1 files changed, 6957 insertions, 0 deletions
diff --git a/sequin/sequin9.c b/sequin/sequin9.c
new file mode 100644
index 00000000..d80af54b
--- /dev/null
+++ b/sequin/sequin9.c
@@ -0,0 +1,6957 @@
+/* sequin9.c
+* ===========================================================================
+*
+* PUBLIC DOMAIN NOTICE
+* National Center for Biotechnology Information (NCBI)
+*
+* This software/database is a "United States Government Work" under the
+* terms of the United States Copyright Act. It was written as part of
+* the author's official duties as a United States Government employee and
+* thus cannot be copyrighted. This software/database is freely available
+* to the public for use. The National Library of Medicine and the U.S.
+* Government do not place any restriction on its use or reproduction.
+* We would, however, appreciate having the NCBI and the author cited in
+* any work or product based on this material
+*
+* Although all reasonable efforts have been taken to ensure the accuracy
+* and reliability of the software and data, the NLM and the U.S.
+* Government do not and cannot warrant the performance or results that
+* may be obtained by using this software or data. The NLM and the U.S.
+* Government disclaim all warranties, express or implied, including
+* warranties of performance, merchantability or fitness for any particular
+* purpose.
+*
+* ===========================================================================
+*
+* File Name: sequin9.c
+*
+* Author: Jonathan Kans
+*
+* Version Creation Date: 4/20/99
+*
+* $Revision: 6.128 $
+*
+* File Description:
+*
+* Modifications:
+* --------------------------------------------------------------------------
+* Date Name Description of modification
+* ------- ---------- -----------------------------------------------------
+*
+*
+* ==========================================================================
+*/
+
+#include <subutil.h>
+#include <explore.h>
+#include <blast.h>
+#include <alignmgr.h>
+#include <urkptpf.h>
+#include <entrez.h>
+#include <accentr.h>
+#include <urlquery.h>
+#include <vecscnapi.h>
+#include <qblastapi.h>
+#include <dotseq.h>
+#include <edutil.h>
+#include "sequin.h"
+
+extern void HandleProjectAsn (ProjectPtr proj, Uint2 entityID)
+
+{
+ Int2 db = -1;
+ EntrezGlobalsPtr egp;
+ Int4 i;
+ ValNodePtr list;
+ Int4 num;
+ ValNodePtr pip;
+ Int4Ptr uids;
+ ValNodePtr vnp;
+
+ if (proj == NULL) return;
+ if (! useEntrez) return;
+ egp = (EntrezGlobalsPtr) GetAppProperty ("EntrezGlobals");
+ if (egp == NULL) return;
+ pip = proj->data;
+ if (pip == NULL) return;
+ list = (ValNodePtr) pip->data.ptrvalue;
+ if (list == NULL) return;
+ if (pip->choice >= ProjectItem_protent && pip->choice <= ProjectItem_genomeent) {
+ if (egp->retrieveProjectProc == NULL) return;
+ if (! EntrezIsInited ()) {
+ SequinEntrezInit ("Sequin", FALSE, NULL);
+ }
+ egp->retrieveProjectProc (NULL, (Pointer) proj);
+ Update ();
+ return;
+ }
+ if (egp->retrieveDocsProc == NULL) return;
+ switch (pip->choice) {
+ case ProjectItem_pmuid :
+ db = 0;
+ break;
+ case ProjectItem_protuid :
+ db = 1;
+ break;
+ case ProjectItem_nucuid :
+ db = 2;
+ break;
+ case ProjectItem_genomeuid :
+ db = 4;
+ break;
+ case ProjectItem_structuid :
+ db = 3;
+ break;
+ default :
+ break;
+ }
+ if (db == -1) return;
+ if (! EntrezIsInited ()) {
+ SequinEntrezInit ("Sequin", FALSE, NULL);
+ }
+ num = ValNodeLen (list);
+ uids = MemNew ((size_t) (num * sizeof (Int4)));
+ if (uids == NULL) return;
+ for (i = 0, vnp = list; i < 32766 && vnp != NULL; i++, vnp = vnp->next) {
+ uids [i] = vnp->data.intvalue;
+ }
+ if (egp->retrieveDocsProc != NULL) {
+ egp->retrieveDocsProc (NULL, (Int2) num, 0, uids, db);
+ }
+ MemFree (uids);
+ Update ();
+}
+
+/* BioseqViewOrDocSumChoice allows a single callback for each analysis item */
+static Int2 BioseqViewOrDocSumChoice (NewObjectPtr nop)
+
+{
+ Int2 which = 0; /* 1 = bioseq viewer, 2 = docsum window */
+
+ if (nop == NULL) return 0;
+#ifdef WIN_MAC
+ if (bioseqViewUp) {
+ which = 1;
+ } else if (docSumUp) {
+ which = 2;
+ }
+#else
+ if (nop->bspOK) {
+ which = 1;
+ } else if (nop->dsmOK) {
+ which = 2;
+ }
+#endif
+ return which;
+}
+
+/*
+#define TEST_APPLE_EVENT_MESSAGING
+*/
+
+#ifndef TEST_APPLE_EVENT_MESSAGING
+static void AddRestrictionSite (SeqAnnotPtr annot, PackSeqPntPtr pspp, CharPtr name)
+
+{
+ DbtagPtr dbt;
+ ObjectIdPtr oip;
+ RsiteRefPtr rrp;
+ SeqFeatPtr sfp, lastsfp;
+ SeqLocPtr slp;
+
+ if (annot == NULL || pspp == NULL || name == NULL) return;
+ slp = ValNodeNew (NULL);
+ if (slp == NULL) return;
+ slp->choice = SEQLOC_PACKED_PNT;
+ slp->data.ptrvalue = (Pointer) pspp;
+ sfp = SeqFeatNew ();
+ if (sfp == NULL) return;
+
+ sfp->data.choice = SEQFEAT_RSITE;
+ sfp->location = slp;
+ dbt = DbtagNew ();
+ if (dbt != NULL) {
+ dbt->db = StringSave ("REBASE");
+ oip = ObjectIdNew ();
+ if (oip != NULL) {
+ oip->str = StringSave (name);
+ }
+ dbt->tag = oip;
+ }
+ rrp = ValNodeNew (NULL);
+ if (rrp != NULL) {
+ rrp->choice = 2;
+ rrp->data.ptrvalue = dbt;
+ }
+ sfp->data.value.ptrvalue = (Pointer) rrp;
+
+ if (annot->data == NULL) {
+ annot->data = (Pointer) sfp;
+ } else {
+ lastsfp = (SeqFeatPtr) annot->data;
+ while (lastsfp->next != NULL) {
+ lastsfp = lastsfp->next;
+ }
+ lastsfp->next = sfp;
+ }
+}
+
+static void RestrictionSearchProc (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+ SeqAnnotPtr annot;
+ BioseqPtr bsp;
+ ComPatPtr cpp, cpph;
+ ValNodePtr desc;
+ SeqAnnotPtr lastannot;
+ PackSeqPntPtr pspp;
+ Int4 pt;
+ SeqAlignPtr sap;
+ SeqLocPtr slp, slpn;
+
+ if (sep == NULL) return;
+ if (! IS_Bioseq (sep)) return;
+ bsp = (BioseqPtr) sep->data.ptrvalue;
+ if (bsp == NULL) return;
+ if (! ISA_na (bsp->mol)) return;
+
+ desc = ValNodeNew (NULL);
+ desc->choice = Annot_descr_name;
+ desc->data.ptrvalue = StringSave ("cutsites");
+
+ annot = SeqAnnotNew ();
+ annot->type = 1;
+ annot->desc = desc;
+ annot->data = NULL;
+
+ cpph = (ComPatPtr) mydata;
+ cpp = cpph;
+ while (cpp != NULL) {
+ sap = PatternMatchBioseq (bsp, cpp, 0);
+ slp = MatchSa2Sl (&sap);
+ if (slp != NULL) {
+ pspp = PackSeqPntNew ();
+ pspp->id = SeqIdDup (SeqIdFindBest (bsp->id, 0));
+ while (slp != NULL) {
+ pt = SeqLocStart (slp);
+ PackSeqPntPut (pspp, pt);
+ slpn = slp->next;
+ SeqLocFree (slp);
+ slp = slpn;
+ }
+ AddRestrictionSite (annot, pspp, cpp->name);
+ }
+ cpp = cpp->nextpattern;
+ }
+
+ if (annot->data == NULL) {
+ SeqAnnotFree (annot);
+ return;
+ }
+ if (bsp->annot == NULL) {
+ bsp->annot = annot;
+ } else {
+ lastannot = bsp->annot;
+ while (lastannot->next != NULL) {
+ lastannot = lastannot->next;
+ }
+ lastannot->next = annot;
+ }
+}
+#endif
+
+static void SimpleRsiteProc (IteM i)
+
+{
+ BaseFormPtr bfp;
+ BioseqPtr bsp;
+ NewObjectPtr nop;
+ SeqEntryPtr sep = NULL;
+ Int2 which;
+#ifdef TEST_APPLE_EVENT_MESSAGING
+ AsnIoPtr aip;
+ Char tmp [PATH_MAX];
+#else
+ ComPatPtr cpph;
+ Char enzyme [64];
+ Int2 j;
+ Char temp [32];
+ ValNodePtr enzymes;
+#endif
+
+ nop = (NewObjectPtr) GetObjectExtra (i);
+ if (nop == NULL) return;
+#ifdef WIN_MAC
+ bfp = (BaseFormPtr) currentFormDataPtr;
+#else
+ bfp = nop->bfp;
+#endif
+ if (bfp == NULL) return;
+ which = BioseqViewOrDocSumChoice (nop);
+ if (which != 1) return;
+ bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+ if (bsp != NULL) {
+ sep = SeqMgrGetSeqEntryForData (bsp);
+ } else {
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ }
+ if (sep == NULL) return;
+
+#ifdef TEST_APPLE_EVENT_MESSAGING
+ TmpNam (tmp);
+ aip = AsnIoOpen (tmp, "w");
+ if (aip != NULL) {
+ SeqEntryAsnWrite (sep, aip, NULL);
+ AsnIoClose (aip);
+ /* Nlm_SendOpenDocAppleEventEx (tmp, "REST", NULL, TRUE); */
+ Nlm_SendOpenDocAppleEventEx (tmp, NULL, "RsiteFind", TRUE);
+ }
+#else
+ enzymes = NULL;
+ j = 1;
+ sprintf (temp, "ENZ_%d", (int) j);
+ while (GetAppParam ("SEQNCGIS", "ENZYMES", temp, NULL, enzyme, sizeof (enzyme) - 1)) {
+ ValNodeCopyStr (&enzymes, 0, enzyme);
+ j++;
+ sprintf (temp, "ENZ_%d", (int) j);
+ }
+ if (enzymes == NULL) {
+ ValNodeCopyStr (&enzymes, 0, "BamHI");
+ ValNodeCopyStr (&enzymes, 0, "EcoRI");
+ ValNodeCopyStr (&enzymes, 0, "HindIII");
+ }
+ cpph = ReadRENPattern ("ncbiren.dat", FALSE, enzymes);
+ /* PalindromeCheck (cpph); */
+ SeqEntryExplore (sep, (Pointer) cpph, RestrictionSearchProc);
+ ComPatFree (cpph);
+ ValNodeFreeData (enzymes);
+
+ ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+ ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+ Update ();
+#endif
+}
+
+static VQUEUE vsquerylist = NULL;
+
+static void LIBCALLBACK AnnounceCallback (CharPtr requestID, CharPtr seqID, Int2 estimatedSeconds)
+
+{
+ if (StringHasNoText (requestID)) {
+ requestID = "?";
+ }
+ if (StringHasNoText (seqID)) {
+ seqID = "?";
+ }
+ Message (MSG_POST, "Queued rID %s, seqID %s, estimated seconds = %d",
+ requestID, seqID, (int) estimatedSeconds);
+}
+
+static Boolean LIBCALLBACK VecScreenCallback (
+ CharPtr filename,
+ VoidPtr userdata,
+ CharPtr requestID,
+ CharPtr seqID,
+ Boolean success
+)
+
+{
+ if (StringHasNoText (requestID)) {
+ requestID = "?";
+ }
+ if (StringHasNoText (seqID)) {
+ seqID = "?";
+ }
+ if (success) {
+ if (! SequinHandleNetResults (filename)) {
+ /* LaunchGeneralTextViewer (path, "QueueFastaQueryToURL failed"); */
+ }
+ } else {
+ Message (MSG_POST, "Failure of rID '%s', seqID %s", requestID, seqID);
+ }
+ return TRUE;
+}
+
+static void SimpleUniVecScreenProc (IteM i)
+
+{
+ BaseFormPtr bfp;
+ BioseqPtr bsp;
+ NewObjectPtr nop;
+ SeqEntryPtr sep = NULL;
+ Int2 which;
+
+ nop = (NewObjectPtr) GetObjectExtra (i);
+ if (nop == NULL) return;
+#ifdef WIN_MAC
+ bfp = (BaseFormPtr) currentFormDataPtr;
+#else
+ bfp = nop->bfp;
+#endif
+ if (bfp == NULL) return;
+ which = BioseqViewOrDocSumChoice (nop);
+ if (which != 1) return;
+ bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+ if (bsp != NULL) {
+ sep = SeqMgrGetSeqEntryForData (bsp);
+ } else {
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ }
+ if (sep == NULL) return;
+
+ VecScreenAsynchronousRequest ("UniVec", bsp, &vsquerylist, VecScreenCallback, AnnounceCallback, NULL);
+}
+
+static void SimpleUniVecCoreScreenProc (IteM i)
+
+{
+ BaseFormPtr bfp;
+ BioseqPtr bsp;
+ NewObjectPtr nop;
+ SeqEntryPtr sep = NULL;
+ Int2 which;
+
+ nop = (NewObjectPtr) GetObjectExtra (i);
+ if (nop == NULL) return;
+#ifdef WIN_MAC
+ bfp = (BaseFormPtr) currentFormDataPtr;
+#else
+ bfp = nop->bfp;
+#endif
+ if (bfp == NULL) return;
+ which = BioseqViewOrDocSumChoice (nop);
+ if (which != 1) return;
+ bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+ if (bsp != NULL) {
+ sep = SeqMgrGetSeqEntryForData (bsp);
+ } else {
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ }
+ if (sep == NULL) return;
+
+ VecScreenAsynchronousRequest ("UniVec_Core", bsp, &vsquerylist, VecScreenCallback, AnnounceCallback, NULL);
+}
+
+static QBQUEUE qbquerylist = NULL;
+
+static void LIBCALLBACK QBAnnounceCallback (CharPtr requestID, CharPtr seqID, Int2 estimatedSeconds)
+
+{
+ if (StringHasNoText (requestID)) {
+ requestID = "?";
+ }
+ if (StringHasNoText (seqID)) {
+ seqID = "?";
+ }
+ Message (MSG_POST, "Queued rID %s, seqID %s, estimated seconds = %d",
+ requestID, seqID, (int) estimatedSeconds);
+}
+
+static Boolean LIBCALLBACK QBCallback (
+ CharPtr filename,
+ VoidPtr userdata,
+ CharPtr requestID,
+ CharPtr seqID,
+ Boolean success
+)
+
+{
+ if (StringHasNoText (requestID)) {
+ requestID = "?";
+ }
+ if (StringHasNoText (seqID)) {
+ seqID = "?";
+ }
+ if (success) {
+ if (! SequinHandleNetResults (filename)) {
+ /* LaunchGeneralTextViewer (path, "QueueFastaQueryToURL failed"); */
+ }
+ } else {
+ Message (MSG_POST, "Failure of rID '%s', seqID %s", requestID, seqID);
+ }
+ return TRUE;
+}
+
+static void SimpleQBlastProc (IteM i)
+
+{
+ BaseFormPtr bfp;
+ BioseqPtr bsp;
+ NewObjectPtr nop;
+ SeqEntryPtr sep = NULL;
+ Int2 which;
+
+ nop = (NewObjectPtr) GetObjectExtra (i);
+ if (nop == NULL) return;
+#ifdef WIN_MAC
+ bfp = (BaseFormPtr) currentFormDataPtr;
+#else
+ bfp = nop->bfp;
+#endif
+ if (bfp == NULL) return;
+ which = BioseqViewOrDocSumChoice (nop);
+ if (which != 1) return;
+ bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+ if (bsp != NULL) {
+ sep = SeqMgrGetSeqEntryForData (bsp);
+ } else {
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ }
+ if (sep == NULL) return;
+
+ QBlastAsynchronousRequest ("nr", "blastn", bsp, &qbquerylist, QBCallback, QBAnnounceCallback, NULL);
+}
+
+/* Analysis menu can launch external programs or use Web services */
+
+static QUEUE urlquerylist = NULL;
+
+static Int4 pendingqueries = 0;
+
+static Boolean LIBCALLBACK SubmitToNCBIResultProc (CONN conn, VoidPtr userdata, EIO_Status status)
+
+{
+ AsnIoPtr aop;
+ FILE *fp;
+ Char path [PATH_MAX];
+ SeqEntryPtr sep;
+
+ TmpNam (path);
+ fp = FileOpen (path, "wb");
+ QUERY_CopyResultsToFile (conn, fp);
+ FileClose (fp);
+ aop = AsnIoOpen (path, "rb");
+ sep = SeqEntryAsnRead (aop, NULL);
+ AsnIoClose (aop);
+ aop = AsnIoOpen (path, "w");
+ SeqEntryAsnWrite (sep, aop, NULL);
+ AsnIoFlush (aop);
+ AsnIoClose (aop);
+ LaunchGeneralTextViewer (path, "Echo binary transformation of Seq-entry");
+ FileRemove (path);
+ return TRUE;
+}
+
+extern void SubmitToNCBI (IteM i);
+extern void SubmitToNCBI (IteM i)
+
+{
+ AsnIoPtr aop;
+ BaseFormPtr bfp;
+ CONN conn;
+ FILE *fp;
+ Char path [PATH_MAX];
+ Char progname [64];
+ SeqEntryPtr sep;
+
+#ifdef WIN_MAC
+ bfp = currentFormDataPtr;
+#else
+ bfp = GetObjectExtra (i);
+#endif
+ if (bfp == NULL) return;
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ if (sep == NULL) return;
+
+ sprintf (progname, "Sequin/%s", SEQUIN_APPLICATION);
+
+ TmpNam (path);
+
+ aop = AsnIoOpen (path, "wb");
+ SeqEntryAsnWrite (sep, aop, NULL);
+ AsnIoFlush (aop);
+ AsnIoClose (aop);
+
+ conn = QUERY_OpenUrlQuery ("cruncher.nlm.nih.gov", 80,
+ "/cgi-bin/Sequin/testcgi.cgi", "request=echo",
+ progname, 30, eMIME_T_NcbiData, eMIME_AsnBinary,
+ eENCOD_Url,
+ fHCC_UrlDecodeInput | fHCC_UrlEncodeOutput);
+
+ fp = FileOpen (path, "rb");
+ QUERY_CopyFileToQuery (conn, fp);
+ FileClose (fp);
+
+ QUERY_SendQuery (conn);
+
+ QUERY_AddToQueue (&urlquerylist, conn, SubmitToNCBIResultProc, NULL, TRUE);
+
+ pendingqueries++;
+
+ FileRemove (path);
+}
+
+extern void SequinCheckSocketsProc (void)
+
+{
+ Int4 remaining;
+
+ remaining = QUERY_CheckQueue (&urlquerylist);
+ if (remaining < pendingqueries) {
+ Beep ();
+ pendingqueries--;
+ }
+ remaining = VecScreenCheckQueue (&vsquerylist);
+ remaining = QBlastCheckQueue (&qbquerylist);
+}
+
+static Boolean LIBCALLBACK DemoModeResultProc (CONN conn, VoidPtr userdata, EIO_Status status)
+
+{
+ FILE *fp;
+ Char path [PATH_MAX];
+
+ TmpNam (path);
+ fp = FileOpen (path, "w");
+ QUERY_CopyResultsToFile (conn, fp);
+ FileClose (fp);
+ LaunchGeneralTextViewer (path, "QueueFastaQueryToURL results");
+ FileRemove (path);
+ return TRUE;
+}
+
+static Boolean LIBCALLBACK SequinHandleURLResults (CONN conn, VoidPtr userdata, EIO_Status status)
+
+{
+ FILE *fp;
+ Char path [PATH_MAX];
+
+ TmpNam (path);
+ fp = FileOpen (path, "w");
+ QUERY_CopyResultsToFile (conn, fp);
+ FileClose (fp);
+ if (! SequinHandleNetResults (path)) {
+ /* LaunchGeneralTextViewer (path, "QueueFastaQueryToURL failed"); */
+ }
+ FileRemove (path);
+ return TRUE;
+}
+
+static void FinishURLProc (NewObjectPtr nop, CharPtr arguments, CharPtr path)
+
+{
+ CONN conn;
+ FILE *fp;
+ Char progname [64];
+ QueryResultProc resultproc;
+ EMIME_SubType subtype;
+
+ sprintf (progname, "Sequin/%s", SEQUIN_APPLICATION);
+
+ if (nop->demomode) {
+ resultproc = DemoModeResultProc;
+ } else {
+ resultproc = nop->resultproc;
+ }
+ if (nop->format == 1) {
+ subtype = eMIME_Fasta;
+ } else if (nop->format == 2) {
+ subtype = eMIME_AsnText;
+ } else {
+ subtype = eMIME_Unknown;
+ }
+
+ conn = QUERY_OpenUrlQuery (nop->host_machine, nop->host_port,
+ nop->host_path, arguments,
+ progname, nop->timeoutsec,
+ eMIME_T_NcbiData, subtype, eENCOD_Url,
+ fHCC_UrlDecodeInput | fHCC_UrlEncodeOutput);
+ if (conn == NULL) return;
+
+ fp = FileOpen (path, "r");
+ QUERY_CopyFileToQuery (conn, fp);
+ FileClose (fp);
+
+ QUERY_SendQuery (conn);
+
+ QUERY_AddToQueue (&urlquerylist, conn, resultproc, NULL, TRUE);
+
+ pendingqueries++;
+}
+
+static void DoAnalysisProc (NewObjectPtr nop, BaseFormPtr bfp, Int2 which, CharPtr arguments, ResultProc dotheanalysis)
+
+{
+ AsnIoPtr aop;
+ BioseqPtr bsp;
+ Char path1 [PATH_MAX];
+ SeqEntryPtr sep;
+
+ if (nop == NULL || bfp == NULL) return;
+ switch (which) {
+ case 1 :
+ if (BioseqViewCanSaveFasta (bfp->form, nop->fastaNucOK, nop->fastaProtOK, nop->onlyBspTarget)) {
+ TmpNam (path1);
+ switch (nop->format) {
+ case 1 :
+ ExportBioseqViewFasta (bfp->form, path1, nop->fastaNucOK, nop->fastaProtOK, nop->onlyBspTarget);
+ break;
+ case 2 :
+ sep = NULL;
+ if (nop->onlyBspTarget) {
+ bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+ sep = SeqMgrGetSeqEntryForData (bsp);
+ } else {
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ }
+ if (sep != NULL) {
+ aop = AsnIoOpen (path1, "w");
+ SeqEntryAsnWrite (sep, aop, NULL);
+ AsnIoFlush (aop);
+ AsnIoClose (aop);
+ }
+ break;
+ default :
+ break;
+ }
+ if (dotheanalysis != NULL) {
+ dotheanalysis (path1);
+ } else {
+ FinishURLProc (nop, arguments, path1);
+ }
+ FileRemove (path1);
+ } else {
+ ErrPostEx (SEV_ERROR, 0, 0, "BioseqView cannot save fasta format");
+ }
+ break;
+ case 2 :
+ if (DocSumCanSaveFasta (bfp->form, nop->fastaNucOK, nop->fastaProtOK)) {
+ TmpNam (path1);
+ ExportDocSumFasta (bfp->form, path1, nop->fastaNucOK, nop->fastaProtOK);
+ if (dotheanalysis != NULL) {
+ dotheanalysis (path1);
+ } else {
+ FinishURLProc (nop, arguments, path1);
+ }
+ FileRemove (path1);
+ } else {
+ ErrPostEx (SEV_ERROR, 0, 0, "DocSum cannot save fasta format");
+ }
+ break;
+ default :
+ break;
+ }
+}
+
+/* encodes spaces as %20 in URLs */
+static CharPtr StrSaveNoNullEncodeSpaces (CharPtr from)
+
+{
+ Char ch;
+ size_t len = 0;
+ CharPtr p;
+ CharPtr q;
+ CharPtr to;
+
+ if (StringHasNoText (from)) return NULL;
+ p = from;
+ ch = *p;
+ while (ch != '\0') {
+ if (ch == ' ') {
+ len += 3;
+ } else {
+ len++;
+ }
+ p++;
+ ch = *p;
+ }
+ to = MemNew (len + 1);
+ if (to == NULL) return NULL;
+
+ q = to;
+ p = from;
+ ch = *p;
+ while (ch != '\0') {
+ if (ch == ' ') {
+ *q = '%';
+ q++;
+ *q = '2';
+ q++;
+ *q = '0';
+ q++;
+ } else {
+ *q = ch;
+ q++;
+ }
+ p++;
+ ch = *p;
+ }
+ *q = '\0';
+ return to;
+}
+
+typedef struct urlargform {
+ FORM_MESSAGE_BLOCK
+
+ NewObjectPtr nop;
+ BaseFormPtr bfp;
+ ValNodePtr controls;
+ ValNodePtr helps;
+ Int2 which;
+} UrlArgForm, PNTR UrlArgFormPtr;
+
+static void AcceptArgumentFormProc (ButtoN b)
+
+{
+ CharPtr args = NULL;
+ CharPtr arguments = NULL;
+ ButtoN btn;
+ Char ch;
+ Int2 choice;
+ Char cpy [256];
+ GrouP grp;
+ ValNodePtr head = NULL;
+ Int2 i;
+ CharPtr itms;
+ CharPtr last;
+ size_t len;
+ LisT lst;
+ NewObjectPtr nop;
+ Boolean notFirst = FALSE;
+ PopuP pop;
+ ValNodePtr ppt;
+ CharPtr ptr;
+ CharPtr str;
+ Char tmp [256];
+ TexT txt;
+ UrlArgFormPtr ufp;
+ UrlParamPtr upp;
+ Int2 val;
+ ValNodePtr vnp;
+
+ ufp = (UrlArgFormPtr) GetObjectExtra (b);
+ if (ufp == NULL) return;
+ Hide (ufp->form);
+ Update ();
+ nop = ufp->nop;
+ if (nop != NULL) {
+ if (! StringHasNoText (nop->prefix)) {
+ ValNodeCopyStr (&head, 0, nop->prefix);
+ }
+ for (vnp = ufp->controls, ppt = nop->paramlist;
+ vnp != NULL && ppt != NULL;
+ vnp = vnp->next, ppt = ppt->next) {
+ upp = (UrlParamPtr) ppt->data.ptrvalue;
+ if (upp == NULL) continue;
+ choice = vnp->choice;
+ switch (upp->type) {
+ case 1 :
+ txt = (TexT) vnp->data.ptrvalue;
+ str = SaveStringFromText (txt);
+ if (str != NULL) {
+ sprintf (tmp, "%s=%s", upp->param, str);
+ ValNodeCopyStr (&head, ppt->choice, tmp);
+ MemFree (str);
+ }
+ break;
+ case 2 :
+ btn = (ButtoN) vnp->data.ptrvalue;
+ if (GetStatus (btn)) {
+ sprintf (tmp, "%s=TRUE", upp->param);
+ } else {
+ sprintf (tmp, "%s=FALSE", upp->param);
+ }
+ ValNodeCopyStr (&head, ppt->choice, tmp);
+ break;
+ case 3 :
+ pop = (PopuP) vnp->data.ptrvalue;
+ val = GetValue (pop);
+ if (val > 0) {
+ i = 0;
+ itms = upp->choices;
+ StringNCpy_0 (tmp, itms, sizeof (tmp));
+ last = tmp;
+ ptr = last;
+ ch = *ptr;
+ while (ch != '\0') {
+ if (ch == ',') {
+ *ptr = '\0';
+ i++;
+ if (val == i) {
+ sprintf (cpy, "%s=%s", upp->param, last);
+ ValNodeCopyStr (&head, ppt->choice, cpy);
+ }
+ ptr++;
+ last = ptr;
+ ch = *ptr;
+ } else {
+ ptr++;
+ ch = *ptr;
+ }
+ }
+ if (! StringHasNoText (last)) {
+ i++;
+ if (val == i) {
+ sprintf (cpy, "%s=%s", upp->param, last);
+ ValNodeCopyStr (&head, ppt->choice, cpy);
+ }
+ }
+ }
+ break;
+ case 4 :
+ grp = (GrouP) vnp->data.ptrvalue;
+ val = GetValue (grp);
+ if (val > 0) {
+ i = 0;
+ itms = upp->choices;
+ StringNCpy_0 (tmp, itms, sizeof (tmp));
+ last = tmp;
+ ptr = last;
+ ch = *ptr;
+ while (ch != '\0') {
+ if (ch == ',') {
+ *ptr = '\0';
+ i++;
+ if (val == i) {
+ sprintf (cpy, "%s=%s", upp->param, last);
+ ValNodeCopyStr (&head, ppt->choice, cpy);
+ }
+ ptr++;
+ last = ptr;
+ ch = *ptr;
+ } else {
+ ptr++;
+ ch = *ptr;
+ }
+ }
+ if (! StringHasNoText (last)) {
+ i++;
+ if (val == i) {
+ sprintf (cpy, "%s=%s", upp->param, last);
+ ValNodeCopyStr (&head, ppt->choice, cpy);
+ }
+ }
+ }
+ break;
+ case 5 :
+ lst = (LisT) vnp->data.ptrvalue;
+ val = GetValue (lst);
+ if (val > 0) {
+ i = 0;
+ itms = upp->choices;
+ StringNCpy_0 (tmp, itms, sizeof (tmp));
+ last = tmp;
+ ptr = last;
+ ch = *ptr;
+ while (ch != '\0') {
+ if (ch == ',') {
+ *ptr = '\0';
+ i++;
+ if (val == i) {
+ sprintf (cpy, "%s=%s", upp->param, last);
+ ValNodeCopyStr (&head, ppt->choice, cpy);
+ }
+ ptr++;
+ last = ptr;
+ ch = *ptr;
+ } else {
+ ptr++;
+ ch = *ptr;
+ }
+ }
+ if (! StringHasNoText (last)) {
+ i++;
+ if (val == i) {
+ sprintf (cpy, "%s=%s", upp->param, last);
+ ValNodeCopyStr (&head, ppt->choice, cpy);
+ }
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ }
+ head = SortValNode (head, SortByVnpChoice);
+ if (! StringHasNoText (nop->suffix)) {
+ ValNodeCopyStr (&head, 0, nop->suffix);
+ }
+ for (len = 0, vnp = head; vnp != NULL; vnp = vnp->next) {
+ len += StringLen ((CharPtr) vnp->data.ptrvalue) + 1;
+ }
+ if (len > 0) {
+ arguments = MemNew (len + 5);
+ if (arguments != NULL) {
+ vnp = head;
+ notFirst = FALSE;
+ while (vnp != NULL) {
+ if (notFirst) {
+ StringCat (arguments, "&");
+ }
+ StringCat (arguments, (CharPtr) vnp->data.ptrvalue);
+ notFirst = TRUE;
+ vnp = vnp->next;
+ }
+ }
+ }
+ args = /* StrSaveNoNullEncodeSpaces */ StringSave (arguments);
+ MemFree (arguments);
+ DoAnalysisProc (nop, ufp->bfp, ufp->which, args, NULL);
+ MemFree (args);
+ }
+ Remove (ufp->form);
+}
+
+static void ShowArgumentHelp (ButtoN b)
+
+{
+ NewObjectPtr nop;
+ ValNodePtr ppt;
+ CharPtr str;
+ UrlArgFormPtr ufp;
+ UrlParamPtr upp;
+ ValNodePtr vnp;
+
+ ufp = (UrlArgFormPtr) GetObjectExtra (b);
+ if (ufp == NULL) return;
+ nop = ufp->nop;
+ if (nop == NULL) return;
+ for (vnp = ufp->helps, ppt = nop->paramlist;
+ vnp != NULL && ppt != NULL;
+ vnp = vnp->next, ppt = ppt->next) {
+ upp = (UrlParamPtr) ppt->data.ptrvalue;
+ if (upp == NULL) continue;
+ if ((Pointer) b == (Pointer) vnp->data.ptrvalue) {
+ str = upp->help;
+ Message (MSG_OK, "%s", str);
+ return;
+ }
+ }
+ Beep ();
+}
+
+static void ArgumentFormMessage (ForM f, Int2 mssg)
+
+{
+ UrlArgFormPtr ufp;
+
+ ufp = (UrlArgFormPtr) GetObjectExtra (f);
+ if (ufp != NULL) {
+ switch (mssg) {
+ case VIB_MSG_CLOSE :
+ Remove (f);
+ break;
+ default :
+ if (ufp->appmessage != NULL) {
+ ufp->appmessage (f, mssg);
+ }
+ break;
+ }
+ }
+}
+
+static void CleanupArgumentForm (GraphiC g, VoidPtr data)
+
+{
+ UrlArgFormPtr ufp;
+
+ ufp = (UrlArgFormPtr) data;
+ if (ufp != NULL) {
+ ValNodeFree (ufp->controls);
+ ValNodeFree (ufp->helps);
+ }
+ StdCleanupFormProc (g, data);
+}
+
+static ValNodePtr RearrangeParamList (ValNodePtr paramlist)
+
+{
+ ValNodePtr curr;
+ CharPtr group;
+ ValNodePtr head = NULL;
+ ValNodePtr list;
+ ValNodePtr next;
+ ValNodePtr PNTR prev;
+ ValNodePtr ppt;
+ UrlParamPtr upp;
+
+ ppt = paramlist;
+ while (ppt != NULL) {
+ list = ppt->next;
+ ppt->next = NULL;
+ ValNodeLink (&head, ppt);
+ upp = (UrlParamPtr) ppt->data.ptrvalue;
+ if (upp == NULL) {
+ ppt = list;
+ continue;
+ }
+ group = upp->group;
+ curr = list;
+ prev = &list;
+ while (curr != NULL) {
+ next = curr->next;
+ upp = (UrlParamPtr) curr->data.ptrvalue;
+ if (upp == NULL) {
+ prev = &(curr->next);
+ curr = next;
+ continue;
+ }
+ if (StringICmp (upp->group, group) == 0) {
+ *prev = next;
+ curr->next = NULL;
+ ValNodeLink (&head, curr);
+ } else {
+ prev = &(curr->next);
+ }
+ curr = next;
+ }
+ ppt = list;
+ }
+ return head;
+}
+
+static void BuildArgumentForm (NewObjectPtr nop, BaseFormPtr bfp, Int2 which)
+
+{
+ ButtoN b;
+ ButtoN btn;
+ GrouP c;
+ Char ch;
+ CharPtr def;
+ Int2 delta;
+ TexT first = NULL;
+ GrouP g;
+ GrouP grp;
+ GrouP h;
+ ValNodePtr hlp;
+ Int2 i;
+ CharPtr itms;
+ CharPtr last;
+ CharPtr lastGroup = " ";
+ LisT lst;
+ GrouP m;
+ Int2 max;
+ Int2 min;
+ ValNodePtr moveMe = NULL;
+ Nlm_Handle obj1, obj2;
+ PopuP pop;
+ PrompT prmpt;
+ ValNodePtr ppt;
+ CharPtr ptr;
+ RecT r;
+ StdEditorProcsPtr sepp;
+ CharPtr str;
+ Char tmp [128];
+ TexT txt;
+ UrlArgFormPtr ufp;
+ UrlParamPtr upp;
+ Int2 val;
+ ValNodePtr vnp;
+ WindoW w;
+
+ if (nop == NULL || bfp == NULL) return;
+ ufp = (UrlArgFormPtr) MemNew (sizeof (UrlArgForm));
+ if (ufp == NULL) return;
+
+ nop->paramlist = RearrangeParamList (nop->paramlist);
+
+ w = FixedWindow (-50, -33, -10, -10, "Arguments", NULL);
+ SetObjectExtra (w, ufp, CleanupArgumentForm);
+ ufp->form = (ForM) w;
+ ufp->formmessage = ArgumentFormMessage;
+
+ sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
+ if (sepp != NULL) {
+ SetActivate (w, sepp->activateForm);
+ ufp->appmessage = sepp->handleMessages;
+ }
+
+ ufp->bfp = bfp;
+ ufp->nop = nop;
+ ufp->which = which;
+
+ m = HiddenGroup (w, 1, 0, NULL);
+
+ g = NULL;
+ for (ppt = nop->paramlist;
+ ppt != NULL;
+ ppt = ppt->next) {
+ upp = (UrlParamPtr) ppt->data.ptrvalue;
+ if (upp == NULL) continue;
+ if (StringICmp (upp->group, lastGroup) != 0) {
+ if (StringHasNoText (upp->group)) {
+ if (StringHasNoText (lastGroup)) {
+ g = HiddenGroup (m, 3, 0, NULL);
+ } else {
+ g = NormalGroup (m, 3, 0, "", programFont, NULL);
+ }
+ } else {
+ g = NormalGroup (m, 3, 0, upp->group, programFont, NULL);
+ }
+ lastGroup = upp->group;
+ }
+ if (g == NULL) {
+ g = HiddenGroup (m, 3, 0, NULL);
+ }
+ switch (upp->type) {
+ case 1 :
+ str = upp->prompt;
+ StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
+ def = upp->dfault;
+ if (StringHasNoText (def)) {
+ def = "";
+ }
+ txt = DialogText (g, def, 10, NULL);
+ if (first == NULL) {
+ first = txt;
+ }
+ ValNodeAddPointer (&(ufp->controls), 1, (Pointer) txt);
+ ValNodeAddPointer (&moveMe, 0, (Pointer) txt);
+ b = PushButton (g, "?", ShowArgumentHelp);
+ SetObjectExtra (b, ufp, NULL);
+ ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
+ break;
+ case 2 :
+ str = upp->prompt;
+ btn = CheckBox (g, str, NULL);
+ def = upp->dfault;
+ if (StringICmp (def, "TRUE") == 0) {
+ SetStatus (btn, TRUE);
+ }
+ prmpt = StaticPrompt (g, "", 0, 0, programFont, 'l');
+ ValNodeAddPointer (&moveMe, 0, (Pointer) prmpt);
+ ValNodeAddPointer (&(ufp->controls), 2, (Pointer) btn);
+ b = PushButton (g, "?", ShowArgumentHelp);
+ SetObjectExtra (b, ufp, NULL);
+ ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
+ break;
+ case 3 :
+ str = upp->prompt;
+ StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
+ h = HiddenGroup (g, 1, 0, NULL);
+ pop = PopupList (h, TRUE, NULL);
+ def = upp->dfault;
+ val = 0;
+ i = 0;
+ itms = upp->choices;
+ StringNCpy_0 (tmp, itms, sizeof (tmp));
+ last = tmp;
+ ptr = last;
+ ch = *ptr;
+ while (ch != '\0') {
+ if (ch == ',') {
+ *ptr = '\0';
+ PopupItem (pop, last);
+ i++;
+ if (StringICmp (def, last) == 0) {
+ val = i;
+ }
+ ptr++;
+ last = ptr;
+ ch = *ptr;
+ } else {
+ ptr++;
+ ch = *ptr;
+ }
+ }
+ if (! StringHasNoText (last)) {
+ PopupItem (pop, last);
+ i++;
+ if (StringICmp (def, last) == 0) {
+ val = i;
+ }
+ }
+ if (val > 0) {
+ SetValue (pop, val);
+ }
+ ValNodeAddPointer (&(ufp->controls), 3, (Pointer) pop);
+ ValNodeAddPointer (&moveMe, 0, (Pointer) pop);
+ b = PushButton (g, "?", ShowArgumentHelp);
+ SetObjectExtra (b, ufp, NULL);
+ ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
+ break;
+ case 4 :
+ str = upp->prompt;
+ StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
+ h = HiddenGroup (g, 1, 0, NULL);
+ grp = HiddenGroup (h, -3, 0, NULL);
+ def = upp->dfault;
+ val = 0;
+ i = 0;
+ itms = upp->choices;
+ StringNCpy_0 (tmp, itms, sizeof (tmp));
+ last = tmp;
+ ptr = last;
+ ch = *ptr;
+ while (ch != '\0') {
+ if (ch == ',') {
+ *ptr = '\0';
+ RadioButton (grp, last);
+ i++;
+ if (StringICmp (def, last) == 0) {
+ val = i;
+ }
+ ptr++;
+ last = ptr;
+ ch = *ptr;
+ } else {
+ ptr++;
+ ch = *ptr;
+ }
+ }
+ if (! StringHasNoText (last)) {
+ RadioButton (grp, last);
+ i++;
+ if (StringICmp (def, last) == 0) {
+ val = i;
+ }
+ }
+ if (val > 0) {
+ SetValue (grp, val);
+ }
+ ValNodeAddPointer (&(ufp->controls), 4, (Pointer) grp);
+ ValNodeAddPointer (&moveMe, 0, (Pointer) grp);
+ b = PushButton (g, "?", ShowArgumentHelp);
+ SetObjectExtra (b, ufp, NULL);
+ ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
+ break;
+ case 5 :
+ str = upp->prompt;
+ StaticPrompt (g, str, 0, dialogTextHeight, programFont, 'l');
+ h = HiddenGroup (g, 1, 0, NULL);
+ lst = SingleList (h, 10, 3, NULL);
+ def = upp->dfault;
+ val = 0;
+ i = 0;
+ itms = upp->choices;
+ StringNCpy_0 (tmp, itms, sizeof (tmp));
+ last = tmp;
+ ptr = last;
+ ch = *ptr;
+ while (ch != '\0') {
+ if (ch == ',') {
+ *ptr = '\0';
+ ListItem (lst, last);
+ i++;
+ if (StringICmp (def, last) == 0) {
+ val = i;
+ }
+ ptr++;
+ last = ptr;
+ ch = *ptr;
+ } else {
+ ptr++;
+ ch = *ptr;
+ }
+ }
+ if (! StringHasNoText (last)) {
+ ListItem (lst, last);
+ i++;
+ if (StringICmp (def, last) == 0) {
+ val = i;
+ }
+ }
+ if (val > 0) {
+ SetValue (lst, val);
+ }
+ ValNodeAddPointer (&(ufp->controls), 5, (Pointer) lst);
+ ValNodeAddPointer (&moveMe, 0, (Pointer) lst);
+ b = PushButton (g, "?", ShowArgumentHelp);
+ SetObjectExtra (b, ufp, NULL);
+ ValNodeAddPointer (&(ufp->helps), 0, (Pointer) b);
+ break;
+ default :
+ break;
+ }
+ }
+
+ min = 0;
+ max = 0;
+ for (vnp = moveMe; vnp != NULL; vnp = vnp->next) {
+ obj1 = (Nlm_Handle) vnp->data.ptrvalue;
+ GetPosition (obj1, &r);
+ min = MAX (min, r.left);
+ }
+ for (vnp = moveMe; vnp != NULL; vnp = vnp->next) {
+ obj1 = (Nlm_Handle) vnp->data.ptrvalue;
+ GetPosition (obj1, &r);
+ delta = min - r.left;
+ OffsetRect (&r, delta, 0);
+ SetPosition (obj1, &r);
+ AdjustPrnt (obj1, &r, FALSE);
+ max = MAX (max, r.right);
+ }
+ max += 3;
+ for (vnp = moveMe, hlp = ufp->helps;
+ vnp != NULL && hlp != NULL;
+ vnp = vnp->next, hlp = hlp->next) {
+ obj2 = (Nlm_Handle) hlp->data.ptrvalue;
+ GetPosition (obj2, &r);
+ delta = max - r.left;
+ OffsetRect (&r, delta, 0);
+ SetPosition (obj2, &r);
+ AdjustPrnt (obj2, &r, TRUE);
+ }
+
+ c = HiddenGroup (w, 2, 0, NULL);
+ SetGroupSpacing (c, 10, 3);
+ b = PushButton (c, "Accept", AcceptArgumentFormProc);
+ SetObjectExtra (b, ufp, NULL);
+ PushButton (c, "Cancel", StdCancelButtonProc);
+
+ AlignObjects (ALIGN_CENTER, (HANDLE) m, (HANDLE) c, NULL);
+ RealizeWindow (w);
+ Show (w);
+ Select (w);
+ if (first != NULL) {
+ Select (first);
+ }
+}
+
+static void DoURLProc (IteM i)
+
+{
+ CharPtr args = NULL;
+ BaseFormPtr bfp;
+ size_t len;
+ NewObjectPtr nop;
+ Int2 which;
+
+ nop = (NewObjectPtr) GetObjectExtra (i);
+ if (nop == NULL) return;
+#ifdef WIN_MAC
+ bfp = (BaseFormPtr) currentFormDataPtr;
+#else
+ bfp = nop->bfp;
+#endif
+ if (bfp == NULL) return;
+ which = BioseqViewOrDocSumChoice (nop);
+ if (nop->paramlist == NULL) {
+ len = StringLen (nop->prefix) + StringLen (nop->suffix);
+ if (len > 0) {
+ args = MemNew (sizeof (Char) * (len + 2));
+ StringCpy (args, nop->prefix);
+ if (! StringHasNoText (nop->suffix)) {
+ StringCat (args, "&");
+ StringCat (args, nop->suffix);
+ }
+ }
+ DoAnalysisProc (nop, bfp, which, args, NULL);
+ } else {
+ BuildArgumentForm (nop, bfp, which);
+ }
+}
+
+extern void EnableAnalysisItems (BaseFormPtr bfp, Boolean isDocSum)
+
+{
+ Boolean hasFastaNuc;
+ Boolean hasFastaProt;
+ NewObjectPtr nop;
+
+ if (bfp == NULL) return;
+#ifdef WIN_MAC
+ nop = (NewObjectPtr) macUserDataPtr;
+#else
+ nop = (NewObjectPtr) bfp->userDataPtr;
+#endif
+ if (isDocSum) {
+ } else {
+ }
+ while (nop != NULL) {
+ if (nop->kind == 1) {
+ /* annotate menu item, ignore it */
+ } else if (isDocSum) {
+ if (nop->dsmOK) {
+ hasFastaNuc = DocSumCanSaveFasta (bfp->form, TRUE, FALSE);
+ hasFastaProt = DocSumCanSaveFasta (bfp->form, FALSE, TRUE);
+ if (nop->fastaNucOK && hasFastaNuc) {
+ SafeEnable (nop->item);
+ } else if (nop->fastaProtOK && hasFastaProt) {
+ SafeEnable (nop->item);
+ } else {
+ SafeDisable (nop->item);
+ }
+ } else {
+ SafeDisable (nop->item);
+ }
+ } else {
+ if (nop->bspOK) {
+ hasFastaNuc = BioseqViewCanSaveFasta (bfp->form, TRUE, FALSE, nop->onlyBspTarget);
+ hasFastaProt = BioseqViewCanSaveFasta (bfp->form, FALSE, TRUE, nop->onlyBspTarget);
+ if (nop->fastaNucOK && hasFastaNuc) {
+ SafeEnable (nop->item);
+ } else if (nop->fastaProtOK && hasFastaProt) {
+ SafeEnable (nop->item);
+ } else {
+ SafeDisable (nop->item);
+ }
+ } else {
+ SafeDisable (nop->item);
+ }
+ }
+ nop = nop->next;
+ }
+}
+
+static VoidPtr LinkNewObjectLists (NewObjectPtr list1, NewObjectPtr list2)
+
+{
+ NewObjectPtr nop;
+
+ if (list1 == NULL) return list2;
+ nop = list1;
+ while (nop->next != NULL) {
+ nop = nop->next;
+ }
+ nop->next = list2;
+ return list1;
+}
+
+static void CleanupAnalysisExtraProc (GraphiC g, VoidPtr data)
+
+{
+ NewObjectPtr nop;
+ ValNodePtr ppt;
+ UrlParamPtr upp;
+
+ nop = (NewObjectPtr) data;
+ if (nop != NULL) {
+ MemFree (nop->host_machine);
+ MemFree (nop->host_path);
+ for (ppt = nop->paramlist; ppt != NULL; ppt = ppt->next) {
+ upp = (UrlParamPtr) ppt->data.ptrvalue;
+ if (upp == NULL) continue;
+ MemFree (upp->param);
+ MemFree (upp->prompt);
+ MemFree (upp->dfault);
+ MemFree (upp->choices);
+ MemFree (upp->group);
+ MemFree (upp->help);
+ }
+ ValNodeFreeData (nop->paramlist);
+ MemFree (nop->prefix);
+ MemFree (nop->suffix);
+ }
+ MemFree (data);
+}
+
+typedef struct sbstruc {
+ CharPtr name;
+ MenU menu;
+} Sbstruc, PNTR SbstrucPtr;
+
+static ValNodePtr analysissubmenulist = NULL;
+
+static void AddAnalysisItem (MenU m, BaseFormPtr bfp,
+ Boolean bspviewOK, Boolean docsumOK,
+ Boolean nucOK, Boolean protOK, Boolean onlyBspTarget,
+ CharPtr host_machine, Uint2 host_port,
+ CharPtr host_path, CharPtr program,
+ Uint2 timeoutsec, Int2 format, Boolean demomode,
+ QueryResultProc resultproc, ValNodePtr paramlist,
+ CharPtr prefix, CharPtr suffix,
+ CharPtr title, CharPtr submenu,
+ ItmActnProc actn, NewObjectPtr PNTR head)
+
+{
+ IteM i;
+ NewObjectPtr last;
+ size_t len;
+ NewObjectPtr nop;
+ SbstrucPtr sbp;
+ CharPtr tmp;
+ ValNodePtr vnp;
+ MenU x;
+
+ if (m == NULL || actn == NULL) return;
+ x = NULL;
+ if (! StringHasNoText (submenu)) {
+ vnp = analysissubmenulist;
+ while (vnp != NULL && x == NULL) {
+ sbp = (SbstrucPtr) vnp->data.ptrvalue;
+ if (sbp != NULL && StringICmp (sbp->name, submenu) == 0) {
+ x = sbp->menu;
+ }
+ vnp = vnp->next;
+ }
+ if (x == NULL) {
+ sbp = (SbstrucPtr) MemNew (sizeof (Sbstruc));
+ if (sbp != NULL) {
+ sbp->name = StringSave (submenu);
+ sbp->menu = SubMenu (m, sbp->name);
+ x = sbp->menu;
+ ValNodeAddPointer (&analysissubmenulist, 0, (VoidPtr) sbp);
+ }
+ }
+ }
+ if (x == NULL) {
+ x = m;
+ }
+ i = CommandItem (x, title, actn);
+ nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
+ if (nop != NULL) {
+ nop->kind = 2; /* analysis menu item */
+ nop->bfp = bfp;
+ nop->item = i;
+ nop->bspOK = bspviewOK;
+ nop->dsmOK = docsumOK;
+ nop->fastaNucOK = nucOK;
+ nop->fastaProtOK = protOK;
+ nop->onlyBspTarget = onlyBspTarget;
+ nop->host_machine = /* StrSaveNoNullEncodeSpaces */ StringSave (host_machine);
+ nop->host_port = host_port;
+ len = StringLen (host_path);
+ tmp = MemNew (len + StringLen (program) + 5);
+ if (tmp != NULL) {
+ StringCpy (tmp, host_path);
+ if (len > 1 && tmp [len - 1] != '/') {
+ StringCat (tmp, "/");
+ }
+ StringCat (tmp, program);
+ }
+ nop->host_path = /* StrSaveNoNullEncodeSpaces */ StringSave (tmp);
+ MemFree (tmp);
+ nop->query = NULL;
+ /*
+ nop->host_path = StrSaveNoNullEncodeSpaces (host_path);
+ nop->query = StrSaveNoNullEncodeSpaces (program);
+ */
+ nop->timeoutsec = timeoutsec;
+ nop->format = format;
+ nop->demomode = demomode;
+ nop->resultproc = resultproc;
+ nop->paramlist = paramlist;
+ nop->prefix = StringSaveNoNull (prefix);
+ nop->suffix = StringSaveNoNull (suffix);
+ }
+ SetObjectExtra (i, (Pointer) nop, CleanupAnalysisExtraProc);
+ if (head == NULL) return;
+ last = *head;
+ if (last != NULL) {
+ while (last->next != NULL) {
+ last = last->next;
+ }
+ last->next = nop;
+ } else {
+ *head = nop;
+ }
+}
+
+/* Sample seqncgis.cnf/seqncgis.ini/.seqncgisrc/sequincgi.cfg config file.
+ PATH can contain query (separated by ? symbol), or separate QUERY item can
+ be used, or multiple QUERY and TITLE items can also be used.
+
+[SERVICES]
+PATH=mydisk:Common Files:services:
+
+[ORDER]
+ORDER_1=tRNAscan
+ORDER_2=Seg
+
+[tRNAscan]
+PROGRAM=testcgi.cgi?request=trnascan
+HOST=www.myserver.myschool.edu
+PORT=80
+PATH=/MyServices/cgi-bin/testcgi.cgi
+SUBMENU=Search
+FORMATIN=FASTA
+FLAGS=SEQ,NUC,TRG
+TIMEOUT=30
+
+[Seg]
+PROGRAM=segify
+HOST=www.myserver.myschool.edu
+PORT=80
+PATH=/MyServices/cgi-bin/testcgi.cgi
+FORMATIN=fasta
+FLAGS=SEQ,DOC,PRT,TRG
+SUBMENU=Secondary structure prediction
+PROMPT_1=Window Size
+PARAM_1=window
+DESCRIPTION_1=window size for determining low-complexity segments
+TYPE_1=text
+DEFAULT_1=12
+REQUIRED_1=FALSE
+IMPORTANCE_1=
+GROUP_1=Algorithm
+HELP_1=window size for determining low-complexity segments
+PROMPT_2=Trigger Complexity
+PARAM_2=trigger
+DESCRIPTION_2=trigger complexity for determining low-complexity segments
+TYPE_2=text
+DEFAULT_2=2.2
+REQUIRED_2=FALSE
+IMPORTANCE_2=
+GROUP_2=Algorithm
+HELP_2=trigger complexity for determining low-complexity segments
+...
+
+[ENZYMES]
+ENZ_1=BamHI
+ENZ_2=EcoRI
+ENZ_3=HindIII
+
+*/
+
+static Int2 GetServiceParam (ValNodePtr head, CharPtr type, CharPtr buf, Int2 buflen)
+
+{
+ size_t len;
+ Boolean seenBracket = FALSE;
+ CharPtr str;
+ ValNodePtr vnp;
+
+ if (buf == NULL || buflen <= 0) return 0;
+ *buf = '\0';
+ len = StringLen (type);
+ for (vnp = head; vnp != NULL; vnp = vnp->next) {
+ str = (CharPtr) vnp->data.ptrvalue;
+ if (str != NULL) {
+ if (str [0] == '[') {
+ if (seenBracket) return 0;
+ seenBracket = TRUE;
+ } else if (StringNICmp (str, type, len) == 0) {
+ str += len;
+ StringNCpy_0 (buf, str, buflen);
+ return (Int2) StringLen (buf);
+ }
+ }
+ }
+ return 0;
+}
+
+static ValNodePtr GetConfigParamAndPromptLists (CharPtr sect)
+
+{
+ Int2 i;
+ ValNodePtr paramlist = NULL;
+ Uint1 paramtype;
+ Char title [512];
+ Char tmp [32];
+ UrlParamPtr upp;
+
+ if (sect == NULL) return NULL;
+ i = 1;
+ sprintf (tmp, "PARAM_%d", (int) i);
+ while (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
+ upp = (UrlParamPtr) MemNew (sizeof (UrlParamData));
+ if (upp == NULL) continue;
+ upp->param = StringSave (title);
+ sprintf (tmp, "TYPE_%d", (int) i);
+ paramtype = 1;
+ if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
+ if (StringICmp (title, "text") == 0) {
+ paramtype = 1;
+ } else if (StringICmp (title, "checkbox") == 0) {
+ paramtype = 2;
+ } else if (StringICmp (title, "popup") == 0) {
+ paramtype = 3;
+ } else if (StringICmp (title, "radio") == 0) {
+ paramtype = 4;
+ } else if (StringICmp (title, "list") == 0) {
+ paramtype = 5;
+ }
+ }
+ upp->type = paramtype;
+ sprintf (tmp, "PROMPT_%d", (int) i);
+ if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
+ upp->prompt = StringSave (title);
+ } else {
+ upp->prompt = StringSave (upp->param);
+ }
+ sprintf (tmp, "DEFAULT_%d", (int) i);
+ if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
+ upp->dfault = StringSave (title);
+ } else {
+ upp->dfault = StringSave (" ");
+ }
+ sprintf (tmp, "CHOICES_%d", (int) i);
+ if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
+ upp->choices = StringSave (title);
+ } else {
+ upp->choices = StringSave (" ");
+ }
+ sprintf (tmp, "GROUP_%d", (int) i);
+ if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
+ upp->group = StringSave (title);
+ } else {
+ upp->group = StringSave (" ");
+ }
+ sprintf (tmp, "HELP_%d", (int) i);
+ if (GetAppParam ("SEQNCGIS", sect, tmp, NULL, title, sizeof (title) - 1)) {
+ upp->help = StringSave (title);
+ } else {
+ upp->help = StringSave (" ");
+ }
+ ValNodeAddPointer (&paramlist, i, (Pointer) upp);
+ i++;
+ sprintf (tmp, "PARAM_%d", (int) i);
+ }
+ return paramlist;
+}
+
+static ValNodePtr GetServiceParamAndPromptLists (ValNodePtr list)
+
+{
+ Int2 i;
+ ValNodePtr paramlist = NULL;
+ Uint1 paramtype;
+ Char title [512];
+ Char tmp [32];
+ UrlParamPtr upp;
+
+ if (list == NULL) return NULL;
+ i = 1;
+ sprintf (tmp, "PARAM_%d=", (int) i);
+ while (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
+ upp = (UrlParamPtr) MemNew (sizeof (UrlParamData));
+ if (upp == NULL) continue;
+ upp->param = StringSave (title);
+ sprintf (tmp, "TYPE_%d", (int) i);
+ paramtype = 1;
+ if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
+ if (StringICmp (title, "text") == 0) {
+ paramtype = 1;
+ } else if (StringICmp (title, "checkbox") == 0) {
+ paramtype = 2;
+ } else if (StringICmp (title, "popup") == 0) {
+ paramtype = 3;
+ } else if (StringICmp (title, "radio") == 0) {
+ paramtype = 4;
+ } else if (StringICmp (title, "list") == 0) {
+ paramtype = 5;
+ }
+ }
+ upp->type = paramtype;
+ sprintf (tmp, "PROMPT_%d=", (int) i);
+ if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
+ upp->prompt = StringSave (title);
+ } else {
+ upp->prompt = StringSave (upp->param);
+ }
+ sprintf (tmp, "DEFAULT_%d=", (int) i);
+ if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
+ upp->dfault = StringSave (title);
+ } else {
+ upp->dfault = StringSave (" ");
+ }
+ sprintf (tmp, "CHOICES_%d=", (int) i);
+ if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
+ upp->choices = StringSave (title);
+ } else {
+ upp->choices = StringSave (" ");
+ }
+ sprintf (tmp, "GROUP_%d=", (int) i);
+ if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
+ upp->group = StringSave (title);
+ } else {
+ upp->group = StringSave (" ");
+ }
+ sprintf (tmp, "HELP_%d=", (int) i);
+ if (GetServiceParam (list, tmp, title, sizeof (title) - 1)) {
+ upp->help = StringSave (title);
+ } else {
+ upp->help = StringSave (" ");
+ }
+ ValNodeAddPointer (&paramlist, i, (Pointer) upp);
+ i++;
+ sprintf (tmp, "PARAM_%d=", (int) i);
+ }
+ return paramlist;
+}
+
+static void ReadAnalysisConfigFile (CharPtr sect, MenU m, BaseFormPtr bfp,
+ Boolean bspviewOK, Boolean docsumOK,
+ NewObjectPtr PNTR head)
+
+{
+ Boolean demomode = FALSE;
+ Int2 format = 1;
+ Char host [128];
+ Boolean nucOK = FALSE;
+ Boolean onlyBspTarget = FALSE;
+ ValNodePtr paramlist = NULL;
+ Char program [128];
+ Char path [256];
+ Uint2 port = 80;
+ Char prefix [128];
+ Boolean protOK = FALSE;
+ Char submenu [128];
+ Char suffix [128];
+ Uint2 timeoutsec = 30;
+ Char title [128];
+ Char tmp [32];
+ unsigned int val;
+
+ if (! GetAppParam ("SEQNCGIS", sect, "TITLE", NULL, title, sizeof (title) - 1)) {
+ StringNCpy_0 (title, sect, sizeof (title));
+ }
+ if (GetAppParam ("SEQNCGIS", sect, "HOST", NULL, host, sizeof (host) - 1)) {
+ if (GetAppParam ("SEQNCGIS", sect, "FLAGS", NULL, tmp, sizeof (tmp) - 1)) {
+ if (StringStr (tmp, "SEQ") == NULL) {
+ bspviewOK = FALSE;
+ }
+ if (StringStr (tmp, "DOC") == NULL) {
+ docsumOK = FALSE;
+ }
+ if (StringStr (tmp, "NUC") != NULL) {
+ nucOK = TRUE;
+ }
+ if (StringStr (tmp, "PRT") != NULL) {
+ protOK = TRUE;
+ }
+ if (StringStr (tmp, "TRG") != NULL) {
+ onlyBspTarget = TRUE;
+ }
+ }
+
+ if ((! bspviewOK) && (! docsumOK)) return;
+
+ if (GetAppParam ("SEQNCGIS", sect, "PORT", NULL, tmp, sizeof (tmp) - 1) &&
+ sscanf (tmp, "%u", &val) == 1) {
+ port = (Uint2) val;
+ } else {
+ port = 80;
+ }
+ if (GetAppParam ("SEQNCGIS", sect, "FORMATIN", NULL, tmp, sizeof (tmp) - 1)) {
+ if (StringICmp (tmp, "FASTA") == 0) {
+ format = 1;
+ } else if (StringICmp (tmp, "ASN.1") == 0) {
+ format = 2;
+ }
+ }
+ if (GetAppParam ("SEQNCGIS", sect, "TIMEOUT", NULL, tmp, sizeof (tmp) - 1) &&
+ sscanf (tmp, "%u", &val) == 1) {
+ timeoutsec = (Uint2) val;
+ } else {
+ timeoutsec = 30;
+ }
+ submenu [0] = '\0';
+ GetAppParam ("SEQNCGIS", sect, "SUBMENU", NULL, submenu, sizeof (submenu) - 1);
+ if (GetAppParam ("SEQNCGIS", sect, "DEMO", NULL, tmp, sizeof (tmp) - 1)) {
+ if (StringICmp (tmp, "TRUE") == 0) {
+ demomode = TRUE;
+ }
+ }
+
+ if (GetAppParam ("SEQNCGIS", sect, "PATH", NULL, path, sizeof (path) - 1)) {
+ if (GetAppParam ("SEQNCGIS", sect, "PROGRAM", NULL, program, sizeof (program) - 1)) {
+ paramlist = GetConfigParamAndPromptLists (sect);
+ prefix [0] = '\0';
+ GetAppParam ("SEQNCGIS", sect, "PREFIX", NULL, prefix, sizeof (prefix) - 1);
+ suffix [0] = '\0';
+ GetAppParam ("SEQNCGIS", sect, "SUFFIX", NULL, suffix, sizeof (suffix) - 1);
+ AddAnalysisItem (m, bfp, bspviewOK, docsumOK,
+ nucOK, protOK, onlyBspTarget,
+ host, port, path, program, timeoutsec, format, demomode,
+ SequinHandleURLResults, paramlist, prefix, suffix,
+ title, submenu, DoURLProc, head);
+ }
+ }
+ }
+}
+
+static void ReadServiceConfigFile (CharPtr pathbase, ValNodePtr config,
+ MenU m, BaseFormPtr bfp,
+ Boolean bspviewOK, Boolean docsumOK,
+ NewObjectPtr PNTR head)
+
+{
+ Char ch;
+ ValNodePtr choicelist = NULL;
+ Boolean demomode = FALSE;
+ ValNodePtr dfaultlist = NULL;
+ Int2 format = 1;
+ FILE *fp;
+ Boolean goOn = TRUE;
+ ValNodePtr helplist = NULL;
+ Char host [128];
+ Boolean keepGoing;
+ ValNodePtr list = NULL;
+ Boolean nucOK = FALSE;
+ Boolean onlyBspTarget = FALSE;
+ ValNodePtr paramlist = NULL;
+ Char program [128];
+ ValNodePtr promptlist = NULL;
+ Char path [PATH_MAX];
+ Uint2 port = 80;
+ Char prefix [128];
+ Boolean protOK = FALSE;
+ CharPtr ptr;
+ Boolean seenBracket;
+ Char str [256];
+ Char submenu [128];
+ Char suffix [128];
+ Uint2 timeoutsec = 30;
+ Char title [128];
+ Char tmp [32];
+ unsigned int val;
+ ValNodePtr vnp;
+
+ if (path == NULL || config == NULL || config->data.ptrvalue == NULL) return;
+ StringNCpy_0 (path, pathbase, sizeof (path));
+ FileBuildPath (path, NULL, (CharPtr) config->data.ptrvalue);
+ fp = FileOpen (path, "r");
+ if (fp == NULL) return;
+ while (fgets (str, sizeof (str), fp) != NULL) {
+ ptr = str;
+ ch = *ptr;
+ while (ch != '\0' && ch != '\n' && ch != '\r') {
+ ptr++;
+ ch = *ptr;
+ }
+ *ptr = '\0';
+ ValNodeCopyStr (&list, 1, str);
+ }
+ FileClose (fp);
+ while (goOn) {
+ goOn = FALSE;
+ title [0] = '\0';
+ if (GetServiceParam (list, "TITLE=", tmp, sizeof (tmp) - 1)) {
+ StringNCpy_0 (title, tmp, sizeof (title));
+ }
+ if (StringHasNoText (title)) {
+ if (GetServiceParam (list, "[", title, sizeof (title) - 1)) {
+ ptr = StringChr (title, ']');
+ if (ptr != NULL) {
+ *ptr = '\0';
+ }
+ }
+ }
+ if (title [0] != '\0' && GetServiceParam (list, "HOST=", host, sizeof (host) - 1)) {
+ if (GetServiceParam (list, "FLAGS=", tmp, sizeof (tmp) - 1)) {
+ if (StringStr (tmp, "SEQ") == NULL) {
+ bspviewOK= FALSE;
+ }
+ if (StringStr (tmp, "DOC") == NULL) {
+ docsumOK= FALSE;
+ }
+ if (StringStr (tmp, "NUC") != NULL) {
+ nucOK= TRUE;
+ }
+ if (StringStr (tmp, "PRT") != NULL) {
+ protOK= TRUE;
+ }
+ if (StringStr (tmp, "TRG") != NULL) {
+ onlyBspTarget= TRUE;
+ }
+ }
+
+ if (bspviewOK || docsumOK) {
+
+ if (GetServiceParam (list, "PORT=", tmp, sizeof (tmp) - 1) &&
+ sscanf (tmp, "%u", &val) == 1) {
+ port = (Uint2) val;
+ } else {
+ port = 80;
+ }
+ if (GetServiceParam (list, "FORMATIN=", tmp, sizeof (tmp) - 1)) {
+ if (StringICmp (tmp, "FASTA") == 0) {
+ format = 1;
+ } else if (StringICmp (tmp, "ASN.1") == 0) {
+ format = 2;
+ }
+ }
+ if (GetServiceParam (list, "TIMEOUT=", tmp, sizeof (tmp) - 1) &&
+ sscanf (tmp, "%u", &val) == 1) {
+ timeoutsec = (Uint2) val;
+ } else {
+ timeoutsec = 30;
+ }
+ submenu [0] = '\0';
+ GetServiceParam (list, "SUBMENU=", submenu, sizeof (submenu) - 1);
+ if (GetServiceParam (list, "DEMO=", tmp, sizeof (tmp) - 1)) {
+ if (StringICmp (tmp, "TRUE") == 0) {
+ demomode = TRUE;
+ }
+ }
+
+ if (GetServiceParam (list, "PATH=", path, sizeof (path) - 1)) {
+ if (GetServiceParam (list, "PROGRAM=", program, sizeof (program) - 1)) {
+ paramlist = GetServiceParamAndPromptLists (list);
+ prefix [0] = '\0';
+ GetServiceParam (list, "PREFIX=", prefix, sizeof (prefix) - 1);
+ suffix [0] = '\0';
+ GetServiceParam (list, "SUFFIX=", suffix, sizeof (suffix) - 1);
+ AddAnalysisItem (m, bfp, bspviewOK, docsumOK,
+ nucOK, protOK, onlyBspTarget,
+ host, port, path, program, timeoutsec, format, demomode,
+ SequinHandleURLResults, paramlist, prefix, suffix,
+ title, submenu, DoURLProc, head);
+ }
+ }
+
+ }
+ }
+
+ seenBracket = FALSE;
+ keepGoing = TRUE;
+ for (vnp = list; vnp != NULL && keepGoing; vnp = vnp->next) {
+ ptr = (CharPtr) vnp->data.ptrvalue;
+ if (ptr != NULL) {
+ if (ptr [0] == '[') {
+ if (seenBracket) {
+ keepGoing = FALSE;
+ } else {
+ seenBracket = TRUE;
+ }
+ }
+ if (keepGoing) {
+ vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
+ }
+ }
+ }
+
+ }
+
+ ValNodeFreeData (list);
+}
+
+extern MenU CreateAnalysisMenu (WindoW w, BaseFormPtr bfp, Boolean bspviewOK, Boolean docsumOK)
+
+{
+ NewObjectPtr first;
+ ValNodePtr head1 = NULL, head2 = NULL;
+ Int2 i;
+ size_t len;
+ MenU m;
+ Char path1 [PATH_MAX];
+ Char path2 [PATH_MAX];
+ CharPtr ptr;
+ SbstrucPtr sbp;
+ Char sect [256];
+ Char temp [32];
+ ValNodePtr vnp;
+
+ ProgramPath (path1, sizeof (path1));
+ ptr = StringRChr (path1, DIRDELIMCHR);
+ if (ptr != NULL) {
+ ptr++;
+ *ptr = '\0';
+ }
+ FileBuildPath (path1, "services", NULL);
+ head1 = DirCatalog (path1);
+
+ if (GetAppParam ("SEQNCGIS", "SERVICES", "PATH", NULL, path2, sizeof (path2) - 1)) {
+ len = StringLen (path2);
+ if (path2 [len - 1] != DIRDELIMCHR) {
+ StringCat (path2, DIRDELIMSTR);
+ }
+ if (StringCmp (path1, path2) != 0) {
+ head2 = DirCatalog (path2);
+ }
+ }
+
+ if ((! extraServices) && (! indexerVersion) && (! genomeCenter) &&
+ head1 == NULL && head2 == NULL) {
+ if (! GetAppParam ("SEQNCGIS", "ORDER", NULL, NULL, sect, sizeof (sect) - 1)) {
+ return NULL;
+ }
+ }
+ m = PulldownMenu (w, "Analysis");
+ if (m == NULL) return NULL;
+ analysissubmenulist = NULL;
+ first = NULL;
+ if (bspviewOK) {
+ AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
+ NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
+ "Restriction Search", "Search",
+ SimpleRsiteProc, &first);
+ if (indexerVersion) {
+ AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
+ NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
+ "Vector Screen - UniVec", "Search",
+ SimpleUniVecScreenProc, &first);
+ AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
+ NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
+ "Vector Screen - UniVec Core", "Search",
+ SimpleUniVecCoreScreenProc, &first);
+ AddAnalysisItem (m, bfp, bspviewOK, FALSE, TRUE, FALSE, TRUE,
+ NULL, 0, NULL, NULL, 0, 0, FALSE, NULL, NULL, NULL, NULL,
+ "QBlast Test", "Search",
+ SimpleQBlastProc, &first);
+ }
+ }
+ if (bspviewOK || docsumOK) {
+ if (useEntrez) {
+ i = 1;
+ sprintf (temp, "ORDER_%d", (int) i);
+ while (GetAppParam ("SEQNCGIS", "ORDER", temp, NULL, sect, sizeof (sect) - 1)) {
+ ReadAnalysisConfigFile (sect, m, bfp, bspviewOK, docsumOK, &first);
+ i++;
+ sprintf (temp, "ORDER_%d", (int) i);
+ }
+ for (vnp = head1; vnp != NULL; vnp = vnp->next) {
+ if (vnp->choice == 0) {
+ ReadServiceConfigFile (path1, vnp, m, bfp, bspviewOK, docsumOK, &first);
+ }
+ }
+ for (vnp = head2; vnp != NULL; vnp = vnp->next) {
+ if (vnp->choice == 0) {
+ ReadServiceConfigFile (path2, vnp, m, bfp, bspviewOK, docsumOK, &first);
+ }
+ }
+ }
+ }
+ if (bspviewOK) {
+ }
+ if (docsumOK) {
+ }
+#ifdef WIN_MAC
+ macUserDataPtr = LinkNewObjectLists (macUserDataPtr, first);
+#else
+ bfp->userDataPtr = LinkNewObjectLists (bfp->userDataPtr, first);
+#endif
+ for (vnp = analysissubmenulist; vnp != NULL; vnp = vnp->next) {
+ sbp = (SbstrucPtr) vnp->data.ptrvalue;
+ if (sbp != NULL) {
+ sbp->name = MemFree (sbp->name);
+ }
+ }
+ analysissubmenulist = ValNodeFreeData (analysissubmenulist);
+ ValNodeFreeData (head1);
+ ValNodeFreeData (head2);
+ return m;
+}
+
+/* NEW UPDATE SEQUENCE SECTION */
+
+
+typedef struct sq_spin {
+ Int4 n1;
+ Int4 n2;
+ Int4 n3;
+ Int4 n4;
+ Int4 n5;
+} SQN_n, PNTR SQN_nPtr;
+
+#define SQN_LEFT 1
+#define SQN_RIGHT 2
+#define SQN_MIDDLE 3
+
+#define SQN_MAXGAP 4
+
+#define SQN_WINDOW 30 /* window in which to search for missing pieces */
+
+static int LIBCALLBACK Sqn_CompareSpins (VoidPtr ptr1, VoidPtr ptr2)
+{
+ SQN_nPtr spin1;
+ SQN_nPtr spin2;
+
+ spin1 = *((SQN_nPtr PNTR) ptr1);
+ spin2 = *((SQN_nPtr PNTR) ptr2);
+ if (spin1 == NULL || spin2 == NULL)
+ return 0;
+ if (spin1->n3 > spin2->n3)
+ return -1;
+ if (spin1->n3 < spin2->n3)
+ return 1;
+ if (spin1->n2 < spin2->n2)
+ return -1;
+ if (spin1->n2 > spin2->n2)
+ return 1;
+ return 0;
+}
+
+static void Sqn_RemoveInconsistentAlnsFromSet (SeqAlignPtr sap, Int4 fuzz, Int4 n)
+{
+ AMAlignIndexPtr amaip;
+ Boolean conflict;
+ Int4 curr;
+ Int4 i;
+ Int4 indextype;
+ SeqAlignPtr salp;
+ SeqAlignPtr salp_head;
+ SeqAlignPtr salp_prev;
+ SQN_nPtr PNTR spin;
+ Int4 start;
+ Int4 stop;
+ Int4 strand;
+
+ if (sap == NULL || sap->saip == NULL || sap->saip->indextype != INDEX_PARENT)
+ return;
+ if (n > 2)
+ return;
+ amaip = (AMAlignIndexPtr)(sap->saip);
+ indextype = amaip->mstype;
+ /* make sure that everything is on the plus strand of the nth sequence */
+ for (i=0; i<amaip->numsaps; i++)
+ {
+ salp = amaip->saps[i];
+ strand = AlnMgrGetNthStrand(salp, n);
+ if (strand == Seq_strand_minus)
+ {
+ SAIndexFree(salp->saip);
+ salp->saip = NULL;
+ salp->next = NULL;
+ SeqAlignListReverseStrand(salp);
+ AlnMgrIndexSingleChildSeqAlign(salp);
+ }
+ }
+ /* spin structure: n1 = which alignment, n2 = start on first row, n3 =
+ alignment length on 1st row, n4 = start on 2nd row, n5 = 2nd strand */
+ spin = (SQN_nPtr PNTR)MemNew((amaip->numsaps)*sizeof(SQN_nPtr));
+ for (i=0; i<amaip->numsaps; i++)
+ {
+ spin[i] = (SQN_nPtr)MemNew(sizeof(SQN_n));
+ salp = amaip->saps[i];
+ spin[i]->n1 = i;
+ AlnMgrGetNthSeqRangeInSA(salp, n, &start, &stop);
+ spin[i]->n3 = stop - start;
+ spin[i]->n2 = start;
+ AlnMgrGetNthSeqRangeInSA(salp, 3-n, &start, &stop);
+ spin[i]->n4 = start;
+ strand = AlnMgrGetNthStrand(salp, 3-n);
+ if (strand == Seq_strand_minus)
+ spin[i]->n5 = -1;
+ else
+ spin[i]->n5 = 1;
+ }
+ HeapSort((Pointer)spin, (size_t)(amaip->numsaps), sizeof(SQN_nPtr), Sqn_CompareSpins);
+ strand = spin[0]->n5;
+ for (i=1; i<amaip->numsaps; i++)
+ {
+ if (spin[i]->n5 != strand)
+ {
+ salp = amaip->saps[spin[i]->n1];
+ salp->next = NULL;
+ SeqAlignFree(salp);
+ amaip->saps[spin[i]->n1] = NULL;
+ spin[i]->n1 = -1;
+ }
+ }
+ for (curr=0; curr<amaip->numsaps; curr++)
+ {
+ if (spin[curr]->n1 != -1)
+ {
+ for (i=curr+1; i<amaip->numsaps; i++)
+ {
+ if (spin[i]->n1 != -1)
+ {
+ conflict = FALSE;
+ /* check first for conflict on first row */
+ if (spin[i]->n2 + spin[i]->n3 - 1 > spin[curr]->n2 + fuzz)
+ {
+ if (spin[i]->n2 < spin[curr]->n2)
+ conflict = TRUE;
+ }
+ if (spin[i]->n2 < spin[curr]->n2 + spin[curr]->n3 - 1 - fuzz)
+ {
+ if (spin[i]->n2 + spin[i]->n3 - 1 > spin[curr]->n2 + spin[curr]->n3 - 1)
+ conflict = TRUE;
+ }
+ if (spin[i]->n2 >= spin[curr]->n2)
+ {
+ if (spin[i]->n2 + spin[i]->n3 - 1 <= spin[curr]->n2 + spin[curr]->n3 - 1)
+ conflict = TRUE;
+ }
+ /* then check for conflict and consistency on second row */
+ if (spin[i]->n2 + spin[i]->n3 - 1 < spin[curr]->n2 + fuzz)
+ {
+ if (strand == 1)
+ {
+ if (spin[i]->n4 + spin[i]->n3 - 1 > spin[curr]->n4 + fuzz)
+ conflict = TRUE;
+ } else if (strand == -1)
+ {
+ if (spin[curr]->n4 + spin[curr]->n3 - 1 - fuzz > spin[i]->n4)
+ conflict = TRUE;
+ }
+ } else
+ {
+ if (strand == 1)
+ {
+ if (spin[i]->n4 < spin[curr]->n4 + spin[curr]->n3 - fuzz)
+ conflict = TRUE;
+ } else if (strand == -1)
+ {
+ if (spin[i]->n4 + spin[i]->n3 - 1 - fuzz > spin[curr]->n4)
+ conflict = TRUE;
+ }
+ }
+ if (conflict)
+ {
+ salp = amaip->saps[spin[i]->n1];
+ salp->next = NULL;
+ SeqAlignFree(salp);
+ amaip->saps[spin[i]->n1] = NULL;
+ spin[i]->n1 = -1;
+ }
+ }
+ }
+ }
+ }
+ salp_head = salp_prev = NULL;
+ for (i=0; i<amaip->numsaps; i++)
+ {
+ MemFree(spin[i]);
+ if (amaip->saps[i] != NULL)
+ {
+ amaip->saps[i]->next = NULL;
+ if (salp_prev != NULL)
+ {
+ salp_prev->next = amaip->saps[i];
+ salp_prev = salp_prev->next;
+ } else
+ salp_head = salp_prev = amaip->saps[i];
+ }
+ }
+ sap->segs = (Pointer)(salp_head);
+ if (indextype == AM_LITE)
+ {
+ AMAlignIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexLite(sap);
+ } else
+ AlnMgrReIndexSeqAlign(sap);
+ MemFree(spin);
+}
+
+static void Sqn_GetNthSeqRangeInSASet(SeqAlignPtr sap, Int4 n, Int4Ptr start, Int4Ptr stop)
+{
+ SeqAlignPtr salp;
+ Int4 start_tmp;
+ Int4 stop_tmp;
+ Int4 tmp1;
+ Int4 tmp2;
+
+ if (sap == NULL || sap->saip == NULL || sap->saip->indextype != INDEX_PARENT)
+ return;
+ salp = (SeqAlignPtr)(sap->segs);
+ start_tmp = stop_tmp = -1;
+ while (salp != NULL)
+ {
+ if (n > salp->dim)
+ {
+ if (start)
+ *start = -1;
+ if (stop)
+ *stop = -1;
+ return;
+ }
+ AlnMgrGetNthSeqRangeInSA(salp, n, &tmp1, &tmp2);
+ if (tmp1 < start_tmp || start_tmp == -1)
+ start_tmp = tmp1;
+ if (tmp2 > stop_tmp)
+ stop_tmp = tmp2;
+ salp = salp->next;
+ }
+ if (start)
+ *start = start_tmp;
+ if (stop)
+ *stop = stop_tmp;
+}
+
+static SeqAlignPtr Sqn_FindBestAlnByDotPlot(SeqLocPtr slp1, SeqLocPtr slp2)
+{
+ DOTDiagPtr ddp;
+ DenseSegPtr dsp;
+ Int4 i;
+ DOTMainDataPtr mip;
+ SeqAlignPtr sap;
+ SeqAlignPtr sap_head;
+ SeqAlignPtr sap_prev;
+ ScorePtr scp;
+ Int4 start1;
+ Int4 start2;
+ Uint1 strand;
+
+ ErrSetMessageLevel(SEV_MAX);
+ mip = DOT_CreateAndStorebyLoc (slp1, slp2, 6, 10);
+ ErrSetMessageLevel(SEV_WARNING);
+ sap = sap_head = sap_prev = NULL;
+ if (mip == NULL || mip->hitlist == NULL)
+ return NULL;
+ i = 0;
+ ddp = mip->hitlist[i];
+ start1 = SeqLocStart(slp1);
+ start2 = SeqLocStart(slp2);
+ strand = SeqLocStrand(slp2);
+ /* copy each ddp (a single ungapped alignment) into a one-segment dense-seg alignment */
+ while (ddp != NULL && i < mip->index)
+ {
+ ddp = mip->hitlist[i];
+ i++;
+ sap = SeqAlignNew();
+ dsp = DenseSegNew();
+ sap->type = SAT_PARTIAL;
+ sap->segtype = SAS_DENSEG;
+ sap->dim = 2;
+ dsp->dim = 2;
+ dsp->numseg = 1;
+ dsp->ids = SeqIdDup(SeqLocId(slp1));
+ dsp->ids->next = SeqIdDup(SeqLocId(slp2));
+ dsp->strands = (Uint1Ptr)MemNew(2*sizeof(Uint1));
+ dsp->strands[0] = SeqLocStrand(slp1);
+ dsp->strands[1] = SeqLocStrand(slp2);
+ dsp->starts = (Int4Ptr)MemNew(2*sizeof(Int4));
+ dsp->lens = (Int4Ptr)MemNew(sizeof(Int4));
+ dsp->starts[0] = ddp->q_start;
+ if (dsp->strands[1] == Seq_strand_minus)
+ dsp->starts[1] = ddp->s_start - ddp->length + 1;
+ else
+ dsp->starts[1] = ddp->s_start;
+ if (ddp->length > SeqLocLen(slp2))
+ dsp->lens[0] = SeqLocLen(slp2);
+ else
+ dsp->lens[0] = ddp->length - 1;
+ scp = ScoreNew();
+ scp->id = ObjectIdNew();
+ scp->id->str = StringSave("score");
+ scp->choice = 1;
+ scp->value.intvalue = ddp->score;
+ dsp->scores = scp;
+ sap->segs = (Pointer)(dsp);
+ if (sap_head != NULL)
+ {
+ sap_prev->next = sap;
+ sap_prev = sap;
+ } else
+ sap_head = sap_prev = sap;
+ }
+ if (sap_head == NULL)
+ return NULL;
+ AlnMgrIndexLite(sap_head);
+ Sqn_RemoveInconsistentAlnsFromSet(sap_head, 6, 1);
+ sap = (SeqAlignPtr)(sap_head->segs);
+ sap_head->segs = NULL;
+ SeqAlignFree(sap_head);
+ MemFree(mip->matrix);
+ MemFree(mip->qseq);
+ MemFree(mip->sseq);
+ MemFree(mip->qname);
+ MemFree(mip->sname);
+ i = 0;
+ while (ddp != NULL && i < mip->index)
+ {
+ ddp = mip->hitlist[i];
+ MemFree(ddp);
+ i++;
+ }
+ MemFree(mip->hitlist);
+ return sap;
+}
+
+static SeqAlignPtr Sqn_FindPiece(BioseqPtr bsp1, BioseqPtr bsp2, Int4 start1, Int4 stop1, Int4 start2, Int4 stop2, Uint1 strand, Int4 which_side)
+{
+ AMAlignIndexPtr amaip;
+ DenseSegPtr dsp;
+ Int4 i;
+ Int4 nstart1;
+ Int4 nstart2;
+ Int4 nstop1;
+ Int4 nstop2;
+ BLAST_OptionsBlkPtr options;
+ CharPtr program;
+ SeqAlignPtr sap;
+ SeqAlignPtr sap_head;
+ SeqAlignPtr sap_new;
+ SeqAlignPtr sap_prev = NULL;
+ SeqLocPtr slp1;
+ SeqLocPtr slp2;
+
+ if (stop1 - start1 < 7 || stop2 - start2 < 7) /* can't do these by BLAST -- wordsize can't go that small */
+ return NULL;
+ if (ISA_aa(bsp1->mol))
+ {
+ if (ISA_aa(bsp2->mol))
+ program = StringSave("blastp");
+ else
+ return NULL;
+ } else if (ISA_na(bsp1->mol))
+ {
+ if (ISA_na(bsp2->mol))
+ program = StringSave("blastn");
+ else
+ return NULL;
+ }
+ options = BLASTOptionNew(program, TRUE);
+ options->gapped_calculation = TRUE;
+ options->expect_value = 10;
+ options->gap_x_dropoff_final = 100;
+ options->gap_open = 5;
+ options->gap_extend = 1;
+ options->penalty = -1;
+ options->wordsize = 7;
+ slp1 = SeqLocIntNew(start1, stop1, Seq_strand_plus, bsp1->id);
+ slp2 = SeqLocIntNew(start2, stop2, strand, bsp2->id);
+ sap = BlastTwoSequencesByLoc(slp1, slp2, program, options);
+ BLASTOptionDelete(options);
+ MemFree(program);
+ if (sap == NULL)
+ {
+ sap = SeqAlignNew();
+ dsp = DenseSegNew();
+ dsp->numseg = 1;
+ dsp->starts = (Int4Ptr)MemNew(2*sizeof(Int4));
+ dsp->lens = (Int4Ptr)MemNew(sizeof(Int4));
+ dsp->strands = (Uint1Ptr)MemNew(2*sizeof(Uint1));
+ dsp->dim = 2;
+ dsp->ids = SeqIdDup(bsp1->id);
+ dsp->ids->next = SeqIdDup(bsp2->id);
+ dsp->lens[0] = MIN(stop1-start1+1, stop2-start2+1);
+ dsp->strands[0] = dsp->strands[1] = Seq_strand_plus;
+ if (which_side == SQN_LEFT || which_side == SQN_MIDDLE)
+ {
+ dsp->starts[0] = stop1 - dsp->lens[0] + 1;
+ dsp->starts[1] = stop2 - dsp->lens[0] + 1;
+ } else if (which_side == SQN_RIGHT)
+ {
+ dsp->starts[0] = start1;
+ dsp->starts[1] = start2;
+ }
+ sap->segs = (Pointer)dsp;
+ sap->segtype = SAS_DENSEG;
+ return sap;
+ }
+ SeqLocFree(slp1);
+ SeqLocFree(slp2);
+ if (sap == NULL)
+ return NULL;
+ AlnMgrIndexLite(sap);
+ Sqn_RemoveInconsistentAlnsFromSet(sap, 20, 1);
+ amaip = (AMAlignIndexPtr)(sap->saip);
+ AlnMgrSortAlnSetByNthRowPos(sap, 1);
+ Sqn_GetNthSeqRangeInSASet(sap, 1, &nstart1, &nstop1);
+ Sqn_GetNthSeqRangeInSASet(sap, 2, &nstart2, &nstop2);
+ strand = AlnMgrGetNthStrand(amaip->saps[0], 2);
+ sap_head = NULL;
+ if (strand != Seq_strand_minus)
+ {
+ if (nstart1 > start1+20 && nstart2 > start2+20)
+ {
+ slp1 = SeqLocIntNew(start1, nstart1, Seq_strand_plus, bsp1->id);
+ slp2 = SeqLocIntNew(start2, nstart2, strand, bsp2->id);
+ sap_head = Sqn_FindBestAlnByDotPlot(slp1, slp2);
+ SeqLocFree(slp1);
+ SeqLocFree(slp2);
+ }
+ } else
+ {
+ if (nstart1 > start1+20 && nstop2 < stop2 - 20)
+ {
+ slp1 = SeqLocIntNew(start1, nstart1, Seq_strand_plus, bsp1->id);
+ slp2 = SeqLocIntNew(nstop2, stop2, strand, bsp2->id);
+ sap_head = Sqn_FindBestAlnByDotPlot(slp1, slp2);
+ SeqLocFree(slp1);
+ SeqLocFree(slp2);
+ }
+ }
+ for (i=0; i<amaip->numsaps-1; i++)
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 1, NULL, &nstart1);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 1, &nstop1, NULL);
+ if (strand != Seq_strand_minus)
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, NULL, &nstart2);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, &nstop2, NULL);
+ } else
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, &nstop2, NULL);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, NULL, &nstart2);
+ }
+ }
+ Sqn_GetNthSeqRangeInSASet(sap, 1, &nstart1, &nstop1);
+ Sqn_GetNthSeqRangeInSASet(sap, 2, &nstart2, &nstop2);
+ if (strand != Seq_strand_minus)
+ {
+ if (nstop1 < stop1-20 && nstop2 < stop2-20) /* missing piece at the end */
+ {
+ slp1 = SeqLocIntNew(nstop1, stop1, Seq_strand_plus, bsp1->id);
+ slp2 = SeqLocIntNew(nstop2, stop2, strand, bsp2->id);
+ sap_new = Sqn_FindBestAlnByDotPlot(slp1, slp2);
+ SeqLocFree(slp1);
+ SeqLocFree(slp2);
+ if (sap_new != NULL)
+ {
+ if (sap_head != NULL)
+ {
+ sap_prev->next = sap_new;
+ sap_prev = sap_new;
+ } else
+ sap_head = sap_prev = sap_new;
+ }
+ }
+ } else
+ {
+ if (nstop1 < stop1-20 && nstart2 > start2 + 20)
+ {
+ slp1 = SeqLocIntNew(nstop1, stop1, Seq_strand_plus, bsp1->id);
+ slp2 = SeqLocIntNew(start2, nstart2, strand, bsp2->id);
+ sap_new = Sqn_FindBestAlnByDotPlot(slp1, slp2);
+ SeqLocFree(slp1);
+ SeqLocFree(slp2);
+ if (sap_new != NULL)
+ {
+ if (sap_head != NULL)
+ {
+ sap_prev->next = sap_new;
+ sap_prev = sap_new;
+ } else
+ sap_head = sap_prev = sap_new;
+ }
+ }
+ }
+ sap_new = (SeqAlignPtr)(sap->segs);
+ while (sap_new->next != NULL)
+ {
+ sap_new = sap_new->next;
+ }
+ sap_new->next = sap_head;
+ sap_head = (SeqAlignPtr)(sap->segs);
+ sap->segs = NULL;
+ SeqAlignFree(sap);
+ return sap_head;
+}
+
+static void Sqn_ExtendAlnRight(SeqAlignPtr sap, Int4 which_row, Int4 start, Int4 stop)
+{
+ DenseSegPtr dsp;
+ Int4 i;
+ Int4Ptr lens;
+ Int4Ptr starts;
+ Uint1Ptr strands;
+
+ if (sap == NULL)
+ return;
+ if (which_row > 2)
+ return;
+ dsp = (DenseSegPtr)(sap->segs);
+ if (dsp->starts[2*(dsp->numseg-1) + which_row - 1] == -1 || dsp->starts[2*(dsp->numseg-1) + (2-which_row)] != -1)
+ {
+ starts = (Int4Ptr)MemNew((dsp->numseg+1)*2*sizeof(Int4));
+ strands = (Uint1Ptr)MemNew((dsp->numseg+1)*2*sizeof(Uint1));
+ lens = (Int4Ptr)MemNew((dsp->numseg+1)*sizeof(Int4));
+ for (i=0; i<dsp->numseg; i++)
+ {
+ lens[i] = dsp->lens[i];
+ }
+ for (i=0; i<=(dsp->dim)*(dsp->numseg-1)+1; i++)
+ {
+ starts[i] = dsp->starts[i];
+ strands[i] = dsp->strands[i];
+ }
+ lens[dsp->numseg] = stop - start + 1;
+ if (dsp->strands[which_row-1] != Seq_strand_minus)
+ starts[(dsp->dim)*(dsp->numseg) + which_row - 1] = start;
+ else
+ starts[(dsp->dim)*(dsp->numseg) + which_row - 1] = stop;
+ starts[(dsp->dim)*(dsp->numseg) + (2-which_row)] = -1;
+ strands[(dsp->dim)*(dsp->numseg) + which_row - 1] = dsp->strands[which_row-1];
+ strands[(dsp->dim)*(dsp->numseg) + (2-which_row)] = dsp->strands[2-which_row];
+ MemFree(dsp->starts);
+ MemFree(dsp->lens);
+ MemFree(dsp->strands);
+ dsp->numseg++;
+ dsp->starts = starts;
+ dsp->strands = strands;
+ dsp->lens = lens;
+ } else
+ {
+ dsp->lens[dsp->numseg-1] += stop - start + 1;
+ if (dsp->strands[which_row-1] == Seq_strand_minus)
+ dsp->starts[(dsp->dim)*(dsp->numseg-1) + which_row - 1] = stop;
+ }
+ SAIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign(sap);
+}
+
+static SeqAlignPtr Sqn_CreateContinuousAln(SeqAlignPtr PNTR saps, Int4 numsaps)
+{
+ DenseSegPtr dsp;
+ DenseSegPtr dsp_tmp;
+ Int4 i;
+ Int4 j;
+ Int4 n1;
+ Int4 n2;
+ Int4 numseg;
+ SeqAlignPtr salp;
+ Int4 start1;
+ Int4 start2;
+ Int4 stop1;
+ Int4 stop2;
+ Uint1 strand;
+
+ for (i=0; i<numsaps-1; i++)
+ {
+ AlnMgrGetNthSeqRangeInSA(saps[i], 1, &start1, &stop1);
+ AlnMgrGetNthSeqRangeInSA(saps[i+1], 1, &start2, &stop2);
+ if (start2 - stop1 > 1)
+ Sqn_ExtendAlnRight(saps[i], 1, stop1+1, start2-1);
+ AlnMgrGetNthSeqRangeInSA(saps[i], 2, &start1, &stop1);
+ AlnMgrGetNthSeqRangeInSA(saps[i+1], 2, &start2, &stop2);
+ strand = AlnMgrGetNthStrand(saps[i], 2);
+ if (strand == Seq_strand_minus)
+ {
+ if (stop2 - start1 > 1)
+ Sqn_ExtendAlnRight(saps[i], 2, stop2+1, start1-1);
+ } else
+ {
+ if (start2 - stop1 > 1)
+ Sqn_ExtendAlnRight(saps[i], 2, stop1+1, start2-1);
+ }
+ }
+ numseg = 0;
+ for (i=0; i<numsaps; i++)
+ {
+ dsp_tmp = (DenseSegPtr)(saps[i]->segs);
+ numseg += dsp_tmp->numseg;
+ }
+ dsp = DenseSegNew();
+ dsp->dim = 2;
+ dsp->numseg = numseg;
+ dsp->starts = (Int4Ptr)MemNew(2*numseg*sizeof(Int4));
+ dsp->lens = (Int4Ptr)MemNew(numseg*sizeof(Int4));
+ dsp->strands = (Uint1Ptr)MemNew(2*numseg*sizeof(Uint1));
+ n1 = n2 = 0;
+ for (i=0; i<numsaps; i++)
+ {
+ dsp_tmp = (DenseSegPtr)(saps[i]->segs);
+ if (dsp->ids == NULL)
+ dsp->ids = SeqIdDupList(dsp_tmp->ids);
+ for (j=0; j<2*dsp_tmp->numseg; j++)
+ {
+ dsp->starts[n1+j] = dsp_tmp->starts[j];
+ dsp->strands[n1+j] = dsp_tmp->strands[j];
+ }
+ for (j=0; j<dsp_tmp->numseg; j++)
+ {
+ dsp->lens[n2+j] = dsp_tmp->lens[j];
+ }
+ n1 += 2*dsp_tmp->numseg;
+ n2 += dsp_tmp->numseg;
+ }
+ salp = SeqAlignNew();
+ salp->type = SAT_PARTIAL;
+ salp->segtype = SAS_DENSEG;
+ salp->dim = 2;
+ salp->segs = (Pointer)(dsp);
+ AlnMgrIndexSingleChildSeqAlign(salp);
+ return salp;
+}
+
+static SeqAlignPtr Sqn_CleanUpAlignments(SeqAlignPtr sap, Int4 len1, Int4 len2)
+{
+ AMAlignIndexPtr amaip;
+ Int4 diff;
+ DenseSegPtr dsp;
+ Int4 i;
+ Int4 numseg;
+ Int4 start1;
+ Int4 start2;
+ Int4 stop1;
+ Int4 stop2;
+ Uint1 strand;
+ Int4 tmp;
+
+ if (sap == NULL)
+ return NULL;
+ AlnMgrSortAlnSetByNthRowPos(sap, 1);
+ amaip = (AMAlignIndexPtr)(sap->saip);
+ strand = AlnMgrGetNthStrand(amaip->saps[0], 2);
+ numseg = 0;
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[0], 1, &start1, NULL);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[0], 2, &start2, &stop2);
+ if (strand != Seq_strand_minus)
+ diff = start2;
+ else
+ diff = len2 - stop2;
+ if (start1 > 0 && diff > 0)
+ numseg += 2;
+ for (i=0; i<amaip->numsaps-1; i++)
+ {
+ dsp = (DenseSegPtr)(amaip->saps[i]->segs);
+ numseg += dsp->numseg;
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 1, NULL, &start1);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 1, &stop1, &tmp);
+ if (stop1 < start1+1)
+ AlnMgrTruncateSAP(amaip->saps[i+1], start1+1, tmp, 1);
+ if (strand != Seq_strand_minus)
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, NULL, &start2);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, &stop2, &tmp);
+ if (stop2 < start2+1)
+ AlnMgrTruncateSAP(amaip->saps[i+1], start2+1, tmp, 2);
+ } else
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, &stop2, &tmp);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, NULL, &start2);
+ if (stop2 < start2 + 1)
+ AlnMgrTruncateSAP(amaip->saps[i], start2+1, tmp, 2);
+ }
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 1, NULL, &start1);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 1, &stop1, &tmp);
+ if (strand != Seq_strand_minus)
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, NULL, &start2);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, &stop2, &tmp);
+ } else
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, &stop2, &tmp);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, NULL, &start2);
+ }
+ if (stop1 > start1+1)
+ numseg++;
+ if (stop2 > start2+1)
+ numseg++;
+ }
+ dsp = (DenseSegPtr)(amaip->saps[amaip->numsaps-1]->segs);
+ numseg += dsp->numseg;
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[amaip->numsaps-1], 1, NULL, &stop1);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[amaip->numsaps-1], 2, &start2, &stop2);
+ if (strand != Seq_strand_minus)
+ diff = len2 - stop2;
+ else
+ diff = start2;
+ if (stop1 < len1 && diff > 0)
+ numseg += 2;
+ AlnMgrSortAlnSetByNthRowPos(sap, 1);
+ return (Sqn_CreateContinuousAln(amaip->saps, amaip->numsaps));
+}
+
+static FloatHi act_get_eval(Int4 exp)
+{
+ FloatHi eval;
+ Int4 i;
+
+ eval = 1;
+ for (i=1; i<=exp; i++)
+ {
+ eval = eval/10;
+ }
+ return eval;
+}
+
+static void SQN_AddToAln(SeqAlignPtr sap, Int4 offset, Int2 which_end, Uint1 strand)
+{
+ DenseSegPtr dsp;
+ Int4Ptr lens;
+ Int4 i;
+ Int4 j;
+ Int4Ptr starts;
+ Uint1Ptr strands;
+
+ if (sap == NULL || offset == 0)
+ return;
+ dsp = (DenseSegPtr)(sap->segs);
+ if (which_end == SQN_LEFT)
+ {
+ if (dsp->starts[0] != -1 && dsp->starts[1] != -1) /* neither sequence is gapped */
+ {
+ dsp->starts[0] -= offset;
+ if (strand != Seq_strand_minus)
+ dsp->starts[1] -= offset;
+ dsp->lens[0] += offset;
+ } else /* one of the sequences is gapped -> add a new segment */
+ {
+ starts = (Int4Ptr)MemNew(2*(dsp->numseg+1)*sizeof(Int4));
+ lens = (Int4Ptr)MemNew((dsp->numseg+1)*sizeof(Int4));
+ strands = (Uint1Ptr)MemNew(2*(dsp->numseg+1)*sizeof(Uint1));
+ AlnMgrGetNthSeqRangeInSA(sap, 1, &i, &j);
+ starts[0] = i - offset;
+ AlnMgrGetNthSeqRangeInSA(sap, 1, &i, &j);
+ if (strand == Seq_strand_minus)
+ starts[1] = j + 1;
+ else
+ starts[1] = i - offset;
+ lens[0] = offset;
+ strands[0] = Seq_strand_plus;
+ strands[1] = strand;
+ for (i=0; i<dsp->numseg; i++)
+ {
+ starts[i+1] = dsp->starts[i];
+ starts[2*(i+1)] = dsp->starts[2*i];
+ lens[i+1] = dsp->lens[i];
+ strands[i+1] = dsp->strands[i];
+ strands[2*(i+1)] = dsp->strands[2*i];
+ }
+ dsp->numseg++;
+ MemFree(dsp->starts);
+ MemFree(dsp->lens);
+ MemFree(dsp->strands);
+ dsp->starts = starts;
+ dsp->lens = lens;
+ dsp->strands = strands;
+ }
+ } else if (which_end == SQN_RIGHT)
+ {
+ if (dsp->starts[2*(dsp->numseg-1)] != -1 && dsp->starts[2*(dsp->numseg-1)+1] != -1)
+ {
+ dsp->lens[dsp->numseg-1] += offset;
+ if (strand == Seq_strand_minus)
+ dsp->starts[2*(dsp->numseg-1)+1] -= offset;
+ } else /* one of the sequences is gapped -> add a new segment */
+ {
+ starts = (Int4Ptr)MemNew(2*(dsp->numseg+1)*sizeof(Int4));
+ lens = (Int4Ptr)MemNew((dsp->numseg+1)*sizeof(Int4));
+ strands = (Uint1Ptr)MemNew(2*(dsp->numseg+1)*sizeof(Uint1));
+ AlnMgrGetNthSeqRangeInSA(sap, 1, &i, &j);
+ starts[2*(dsp->numseg)-1] = i+1;
+ AlnMgrGetNthSeqRangeInSA(sap, 2, &i, &j);
+ if (strand == Seq_strand_minus)
+ starts[2*(dsp->numseg)] = i - offset;
+ else
+ starts[2*(dsp->numseg)] = j + 1;
+ lens[dsp->numseg] = offset;
+ strands[2*(dsp->numseg)-1] = Seq_strand_plus;
+ strands[2*(dsp->numseg)] = strand;
+ for (i=0; i<dsp->numseg; i++)
+ {
+ starts[i] = dsp->starts[i];
+ starts[2*i] = dsp->starts[2*i];
+ lens[i] = dsp->lens[i];
+ strands[i] = dsp->strands[i];
+ strands[2*i] = dsp->strands[2*i];
+ }
+ dsp->numseg++;
+ MemFree(dsp->starts);
+ MemFree(dsp->lens);
+ MemFree(dsp->strands);
+ dsp->starts = starts;
+ dsp->lens = lens;
+ dsp->strands = strands;
+ }
+ }
+ /* free the old index and reindex the alignment */
+ SAIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign(sap);
+}
+
+static void SQN_ExtendAlnAlg(SeqAlignPtr sap, Int4 ovl, Int4 which_side, Uint1 strand)
+{
+ BioseqPtr bsp1;
+ BioseqPtr bsp2;
+ Uint1 buf1[20];
+ Uint1 buf2[20];
+ DenseSegPtr dsp;
+ DenseSegPtr dsp_new;
+ Int4 gap;
+ Int4 i;
+ Int4 j;
+ Boolean mismatch;
+ SeqIdPtr sip1;
+ SeqIdPtr sip2;
+ SeqPortPtr spp;
+ Int4 start1;
+ Int4 start2;
+ Int4 stop1;
+ Int4 stop2;
+
+ if (sap == NULL || ovl == 0)
+ return;
+ AlnMgrGetNthSeqRangeInSA(sap, 1, &start1, &stop1);
+ AlnMgrGetNthSeqRangeInSA(sap, 2, &start2, &stop2);
+ sip1 = AlnMgrGetNthSeqIdPtr(sap, 1);
+ sip2 = AlnMgrGetNthSeqIdPtr(sap, 2);
+ bsp1 = BioseqLockById(sip1);
+ bsp2 = BioseqLockById(sip2);
+ if (which_side == SQN_LEFT && (start1<ovl+SQN_MAXGAP || start2<ovl+SQN_MAXGAP))
+ {
+ if (start1 < ovl)
+ ovl = start1;
+ if (start2 < ovl)
+ ovl = start2;
+ if (ovl <= 0) {
+ SeqIdFree(sip1);
+ SeqIdFree(sip2);
+ BioseqUnlock(bsp1);
+ BioseqUnlock(bsp2);
+ return;
+ }
+ dsp = (DenseSegPtr)(sap->segs);
+ dsp_new = DenseSegNew();
+ dsp_new->dim = 2;
+ dsp_new->numseg = dsp->numseg + 1;
+ dsp_new->starts = (Int4Ptr)MemNew(2*(dsp_new->numseg)*sizeof(Int4));
+ dsp_new->lens = (Int4Ptr)MemNew((dsp_new->numseg)*sizeof(Int4));
+ dsp_new->strands = (Uint1Ptr)MemNew(2*(dsp_new->numseg)*sizeof(Int4));
+ dsp_new->ids = dsp->ids;
+ dsp->ids = NULL;
+ dsp_new->starts[0] = start1-ovl;
+ dsp_new->starts[1] = start2-ovl;
+ dsp_new->lens[0] = ovl;
+ dsp_new->strands[0] = dsp_new->strands[1] = Seq_strand_plus;
+ for (i=1; i<dsp_new->numseg; i++)
+ {
+ dsp_new->lens[i] = dsp->lens[i-1];
+ dsp_new->starts[i*dsp->dim] = dsp->starts[(i-1)*dsp->dim];
+ dsp_new->starts[i*dsp->dim+1] = dsp->starts[(i-1)*dsp->dim+1];
+ dsp_new->strands[i*dsp->dim] = dsp_new->strands[i*dsp->dim+1] = Seq_strand_plus;
+ }
+ DenseSegFree(dsp);
+ sap->segs = (Pointer)(dsp_new);
+ SAIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign(sap);
+ SeqIdFree(sip1);
+ SeqIdFree(sip2);
+ BioseqUnlock(bsp1);
+ BioseqUnlock(bsp2);
+ return;
+ } else if (which_side == SQN_RIGHT && (bsp1->length-1-stop1 < ovl+SQN_MAXGAP || bsp2->length-1-stop2<ovl+SQN_MAXGAP))
+ {
+ if (bsp1->length-1-stop1<ovl)
+ ovl = bsp1->length-1-stop1;
+ if (bsp2->length-1-stop2<ovl)
+ ovl = bsp2->length-1-stop2;
+ if (ovl <= 0) {
+ SeqIdFree(sip1);
+ SeqIdFree(sip2);
+ BioseqUnlock(bsp1);
+ BioseqUnlock(bsp2);
+ return;
+ }
+ dsp = (DenseSegPtr)(sap->segs);
+ dsp_new = DenseSegNew();
+ dsp_new->dim = 2;
+ dsp_new->numseg = dsp->numseg + 1;
+ dsp_new->starts = (Int4Ptr)MemNew(2*(dsp_new->numseg)*sizeof(Int4));
+ dsp_new->lens = (Int4Ptr)MemNew((dsp_new->numseg)*sizeof(Int4));
+ dsp_new->strands = (Uint1Ptr)MemNew(2*(dsp_new->numseg)*sizeof(Int4));
+ dsp_new->ids = dsp->ids;
+ dsp->ids = NULL;
+ for (i=0; i<dsp->numseg; i++)
+ {
+ dsp_new->lens[i] = dsp->lens[i];
+ dsp_new->starts[i*dsp->dim] = dsp->starts[i*dsp->dim];
+ dsp_new->starts[i*dsp->dim+1] = dsp->starts[i*dsp->dim+1];
+ dsp_new->strands[i*dsp->dim] = dsp_new->strands[i*dsp->dim+1] = Seq_strand_plus;
+ }
+ dsp_new->lens[dsp_new->numseg-1] = ovl;
+ dsp_new->starts[(dsp_new->numseg-1)*2] = stop1+1;
+ dsp_new->starts[(dsp_new->numseg-1)*2+1] = stop2+1;
+ dsp_new->strands[(dsp_new->numseg-1)*2] = dsp_new->strands[(dsp_new->numseg-1)*2+1] = Seq_strand_plus;
+ DenseSegFree(dsp);
+ sap->segs = (Pointer)dsp_new;
+ SAIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign(sap);
+ SeqIdFree(sip1);
+ SeqIdFree(sip2);
+ BioseqUnlock(bsp1);
+ BioseqUnlock(bsp2);
+ return;
+ }
+ if (which_side == SQN_LEFT)
+ {
+ spp = SeqPortNew(bsp1, MAX(0, start1-(SQN_MAXGAP+ovl)), start1-1, Seq_strand_plus, Seq_code_ncbi4na);
+ SeqPortRead(spp, buf1, 20);
+ SeqPortFree(spp);
+ if (strand == Seq_strand_minus)
+ {
+ spp = SeqPortNew(bsp2, stop2+1, stop2 + 1 + ovl, strand, Seq_code_ncbi4na);
+ SeqPortRead(spp, buf2, 20);
+ SeqPortFree(spp);
+ } else
+ {
+ spp = SeqPortNew(bsp2, start2-1-ovl, start2-1, strand, Seq_code_ncbi4na);
+ SeqPortRead(spp, buf2, 20);
+ SeqPortFree(spp);
+ }
+ gap = -1;
+ for (i=0; i<SQN_MAXGAP; i++)
+ {
+ mismatch = FALSE;
+ for (j=0; j<ovl; j++)
+ {
+ if (buf2[j] != buf1[i+j])
+ mismatch = TRUE;
+ }
+ if (mismatch == FALSE)
+ gap = SQN_MAXGAP-i;
+ }
+ if (gap > 0)
+ {
+ dsp = (DenseSegPtr)(sap->segs);
+ dsp_new = DenseSegNew();
+ dsp_new->dim = 2;
+ dsp_new->numseg = dsp->numseg+2;
+ dsp_new->ids = dsp->ids;
+ dsp->ids = NULL;
+ dsp_new->starts = (Int4Ptr)MemNew((dsp_new->numseg)*2*sizeof(Int4));
+ dsp_new->lens = (Int4Ptr)MemNew((dsp_new->numseg)*sizeof(Int4));
+ dsp_new->strands = (Uint1Ptr)MemNew((dsp_new->numseg)*2*sizeof(Uint1));
+ for (i=2; i<dsp_new->numseg; i++)
+ {
+ dsp_new->starts[i*2] = dsp->starts[(i-2)*2];
+ dsp_new->starts[i*2+1] = dsp->starts[(i-2)*2+1];
+ dsp_new->strands[i+2] = dsp->strands[(i-2)*2];
+ dsp_new->strands[i*2+1] = dsp->strands[(i-2)*2+1];
+ dsp_new->lens[i] = dsp->lens[i-2];
+ }
+ dsp_new->starts[0] = dsp->starts[0] - gap - ovl;
+ dsp_new->starts[2] = dsp_new->starts[0] + ovl;
+ dsp_new->starts[3] = -1;
+ dsp_new->strands[0] = dsp_new->strands[2] = dsp->strands[0];
+ dsp_new->strands[1] = dsp_new->strands[2] = dsp->strands[1];
+ dsp_new->lens[0] = ovl;
+ dsp_new->lens[1] = gap;
+ if (strand == Seq_strand_minus)
+ dsp_new->starts[1] = stop2 + 1;
+ else
+ dsp_new->starts[1] = start2 - ovl;
+ sap->segs = (Pointer)dsp_new;
+ DenseSegFree(dsp);
+ SAIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign(sap);
+ } else
+ SQN_AddToAln(sap, ovl, SQN_LEFT, strand);
+ } else if (which_side == SQN_RIGHT)
+ {
+ spp = SeqPortNew(bsp1, MIN(stop1, bsp1->length-1), MIN(stop1+SQN_MAXGAP, bsp1->length-1), Seq_strand_plus, Seq_code_ncbi4na);
+ SeqPortRead(spp, buf1, 20);
+ SeqPortFree(spp);
+ if (strand == Seq_strand_minus)
+ {
+ spp = SeqPortNew(bsp2, start2-ovl, start2-1-ovl, strand, Seq_code_ncbi4na);
+ SeqPortRead(spp, buf2, 20);
+ SeqPortFree(spp);
+ } else
+ {
+ spp = SeqPortNew(bsp2, MIN(stop2+1, bsp2->length-1), MIN(stop2+1+ovl, bsp2->length-1), strand, Seq_code_ncbi4na);
+ SeqPortRead(spp, buf2, 20);
+ SeqPortFree(spp);
+ }
+ gap = -1;
+ for (i=0; i<SQN_MAXGAP; i++)
+ {
+ mismatch = FALSE;
+ for (j=0; j<ovl; j++)
+ {
+ if (buf1[i+j] != buf1[j])
+ mismatch = TRUE;
+ }
+ if (mismatch == FALSE && gap == -1)
+ gap = i;
+ }
+ if (gap > 0)
+ {
+ dsp = (DenseSegPtr)(sap->segs);
+ dsp_new = DenseSegNew();
+ dsp_new->dim = 2;
+ dsp_new->numseg = dsp->numseg+2;
+ dsp_new->ids = dsp->ids;
+ dsp->ids = NULL;
+ dsp_new->starts = (Int4Ptr)MemNew((dsp_new->numseg)*2*sizeof(Int4));
+ dsp_new->lens = (Int4Ptr)MemNew((dsp_new->numseg)*sizeof(Int4));
+ dsp_new->strands = (Uint1Ptr)MemNew((dsp_new->numseg)*2*sizeof(Uint1));
+ for (i=0; i<dsp->numseg; i++)
+ {
+ dsp_new->starts[i*2] = dsp->starts[i*2];
+ dsp_new->starts[i*2+1] = dsp->starts[i*2+1];
+ dsp_new->strands[i+2] = dsp->strands[i*2];
+ dsp_new->strands[i*2+1] = dsp->strands[i*2+1];
+ dsp_new->lens[i] = dsp->lens[i];
+ }
+ dsp_new->strands[2*dsp->numseg] = dsp_new->strands[2*dsp->numseg+2] = dsp->strands[0];
+ dsp_new->strands[2*dsp->numseg+1] = dsp_new->strands[2*dsp->numseg+3] = dsp->strands[1];
+ dsp_new->lens[dsp->numseg] = gap;
+ dsp_new->lens[dsp->numseg+1] = ovl;
+ dsp_new->starts[2*dsp->numseg] = dsp_new->starts[2*(dsp->numseg-1)]+dsp_new->lens[dsp->numseg-1];
+ dsp_new->starts[2*dsp->numseg+2] = dsp_new->starts[2*dsp->numseg] + gap;
+ if (strand == Seq_strand_minus)
+ dsp_new->starts[2*dsp->numseg+3] = start2 - ovl;
+ else
+ dsp_new->starts[2*dsp->numseg+3] = stop2 + 1;
+ dsp_new->starts[2*dsp->numseg+1] = -1;
+ sap->segs = (Pointer)dsp_new;
+ DenseSegFree(dsp);
+ SAIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign(sap);
+ } else
+ SQN_AddToAln(sap, ovl, SQN_RIGHT, strand);
+ }
+ SeqIdFree(sip1);
+ SeqIdFree(sip2);
+ BioseqUnlock(bsp1);
+ BioseqUnlock(bsp2);
+}
+
+static Uint4 sqn_binary_search_on_uint4_list(Uint4Ptr list, Uint4 pos, Uint4 listlen)
+{
+ Uint4 L;
+ Uint4 mid;
+ Uint4 R;
+
+ if (list == NULL || listlen == 0)
+ return 0;
+ L = 0;
+ R = listlen - 1;
+ while (L < R)
+ {
+ mid = (L+R)/2;
+ if (list[mid + 1] <= pos)
+ {
+ L = mid + 1;
+ } else
+ {
+ R = mid;
+ }
+ }
+ return R;
+}
+
+static Int4 MapRowCoordsSpecial(SeqAlignPtr sap, Uint4 pos, Int4 row, Int4 which_end)
+{
+ DenseSegPtr dsp;
+ Int4 idx;
+ Int4 offset;
+ SAIndexPtr saip;
+ Int4 start;
+
+ if (sap == NULL || row < 0)
+ return -1;
+ if (sap->saip == NULL)
+ return -1;
+ saip = (SAIndexPtr)sap->saip;
+ dsp = (DenseSegPtr)sap->segs;
+ start = sqn_binary_search_on_uint4_list(saip->aligncoords, pos, dsp->numseg);
+ offset = pos - saip->aligncoords[start];
+ idx = (dsp->dim*start) + row - 1;
+ if (dsp->starts[idx] == -1)
+ {
+ if (which_end == SQN_RIGHT)
+ {
+ /* round down */
+ while (start >= 0) {
+ idx = (dsp->dim*start) + row - 1;
+ if (dsp->starts[idx] != -1)
+ return (dsp->starts[idx] + dsp->lens[start] - 1);
+ start--;
+ }
+ return -2;
+ } else if (which_end == SQN_LEFT)
+ {
+ /* round up */
+ while (start < dsp->numseg) {
+ idx = (dsp->dim*start) + row - 1;
+ if (dsp->starts[idx] != -1)
+ return (dsp->starts[idx]);
+ start++;
+ }
+ return -2;
+ }
+ } else
+ {
+ idx = (dsp->dim*start) + row - 1;
+ if (dsp->strands[idx] != Seq_strand_minus)
+ return (dsp->starts[idx] + offset);
+ else
+ return (dsp->starts[idx] + dsp->lens[start] - 1 - offset);
+ }
+ return -1;
+}
+
+static Int4 MapBioseqToBioseqSpecial(SeqAlignPtr sap, Int4 begin, Int4 fin, Int4 pos, Int4 which_end)
+{
+ Int4 bspos;
+ Int4 sapos;
+ Int4 start1;
+ Int4 start2;
+ Int4 stop1;
+ Int4 stop2;
+
+ if (sap == NULL || sap->saip == NULL)
+ return -2;
+ AlnMgrGetNthSeqRangeInSA(sap, begin, &start1, &stop1);
+ AlnMgrGetNthSeqRangeInSA(sap, fin, &start2, &stop2);
+ /* check to see whether the position is outside the alignment */
+ if (pos < start1)
+ return (start2 - (start1 - pos));
+ else if (pos > stop1)
+ return (stop2 + (pos-stop1));
+ sapos = AlnMgrMapBioseqToSeqAlign(sap, pos, begin, NULL);
+ bspos = MapRowCoordsSpecial(sap, sapos, fin, which_end);
+ if (bspos >= 0)
+ return bspos;
+ else if (which_end == SQN_LEFT)
+ return (start2-1);
+ else if (which_end == SQN_RIGHT)
+ return (stop2+1);
+ else
+ return 0;
+}
+
+static void SPI_flip_sa_list (SeqAlignPtr sap)
+{
+ DenseSegPtr dsp;
+ Int4 i;
+ SeqIdPtr sip;
+ SeqIdPtr sip_next;
+ Int4 tmp_start;
+ Uint1 tmp_strand;
+
+ if (sap == NULL || sap->segtype != SAS_DENSEG)
+ return;
+ while (sap != NULL)
+ {
+ dsp = (DenseSegPtr)(sap->segs);
+ if (dsp->dim == 2) /* skip anything with more than 2 rows */
+ {
+ /* first switch the ids */
+ sip = dsp->ids;
+ sip_next = sip->next;
+ sip_next->next = sip;
+ sip->next = NULL;
+ dsp->ids = sip_next;
+ /* then switch the starts and strands */
+ for (i = 0; i<dsp->numseg; i++)
+ {
+ tmp_start = dsp->starts[2*i];
+ dsp->starts[2*i] = dsp->starts[2*i+1];
+ dsp->starts[2*i+1] = tmp_start;
+ tmp_strand = dsp->strands[2*i];
+ dsp->strands[2*i] = dsp->strands[2*i+1];
+ dsp->strands[2*i+1] = tmp_strand;
+ }
+ }
+ if (sap->saip != NULL) /* free indexes, reindex */
+ {
+ SAIndexFree(sap->saip);
+ sap->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign(sap);
+ }
+ sap = sap->next;
+ }
+}
+
+static SeqAlignPtr Sqn_GlobalAlignTwoSeq (BioseqPtr bsp1, BioseqPtr bsp2, BoolPtr revcomp)
+{
+ AMAlignIndexPtr amaip;
+ Int4 i;
+ BLAST_OptionsBlkPtr options;
+ CharPtr program = "blastn";
+ SeqAlignPtr sap;
+ SeqAlignPtr sap_final;
+ SeqAlignPtr sap_head;
+ SeqAlignPtr sap_new;
+ SeqAlignPtr sap_prev;
+ Int4 start1;
+ Int4 start2;
+ Int4 stop1;
+ Int4 stop2;
+ Uint1 strand;
+ Int4 extnd = 20;
+ SeqMgrFeatContext context;
+ Uint2 entityID;
+ SeqFeatPtr sfp;
+ SeqIdPtr sip;
+ SeqLocPtr slp;
+
+ if (bsp1 == NULL || bsp2 == NULL)
+ return NULL;
+ if (ISA_aa (bsp1->mol)) {
+ program = "blastp";
+ }
+ options = BLASTOptionNew(program, TRUE);
+ options->gapped_calculation = TRUE;
+ options->expect_value = 0.001;
+ if (bsp1->length > 10000 || bsp2->length > 10000)
+ {
+ options->expect_value = act_get_eval(60);
+ options->wordsize = 20;
+ options->filter_string = StringSave ("m L");
+ }
+ sap = BlastTwoSequences(bsp1, bsp2, program, options);
+ BLASTOptionDelete(options);
+ if (sap == NULL)
+ {
+ Message(MSG_OK,"BLAST finds no sequence similarity");
+ return NULL;
+ }
+ AlnMgrIndexLite(sap);
+ Sqn_RemoveInconsistentAlnsFromSet(sap, 20, 1);
+ amaip = (AMAlignIndexPtr)(sap->saip);
+ AlnMgrSortAlnSetByNthRowPos(sap, 1);
+ Sqn_GetNthSeqRangeInSASet(sap, 1, &start1, &stop1);
+ Sqn_GetNthSeqRangeInSASet(sap, 2, &start2, &stop2);
+ strand = AlnMgrGetNthStrand(amaip->saps[0], 2);
+
+ /* if opposite strand submitted, reverse complement, realign */
+
+ if (strand == Seq_strand_minus) {
+ if (revcomp != NULL) {
+ *revcomp = TRUE;
+ }
+ AMFreeAllIndexes (sap);
+ sap = SeqAlignFree (sap);
+ BioseqRevComp (bsp2);
+ entityID = ObjMgrGetEntityIDForPointer (bsp2);
+ if (! SeqMgrFeaturesAreIndexed (entityID)) {
+ SeqMgrIndexFeatures (entityID, NULL);
+ }
+ sfp = SeqMgrGetNextFeature (bsp2, NULL, 0, 0, &context);
+ while (sfp != NULL) {
+ sip = SeqLocId (sfp->location);
+ slp = SeqLocCopyRegion (sip, sfp->location, bsp2, 0,
+ bsp2->length - 1, Seq_strand_minus, FALSE);
+ sfp->location = SeqLocFree (sfp->location);
+ sfp->location = slp;
+ sfp = SeqMgrGetNextFeature (bsp2, sfp, 0, 0, &context);
+ }
+ SeqMgrClearFeatureIndexes (entityID, NULL);
+
+ options = BLASTOptionNew(program, TRUE);
+ options->gapped_calculation = TRUE;
+ options->expect_value = 0.001;
+ if (bsp1->length > 10000 || bsp2->length > 10000)
+ {
+ options->expect_value = act_get_eval(60);
+ options->wordsize = 20;
+ options->filter_string = StringSave ("m L");
+ }
+ sap = BlastTwoSequences(bsp1, bsp2, program, options);
+ BLASTOptionDelete(options);
+ if (sap == NULL)
+ {
+ Message(MSG_OK,"BLAST finds no sequence similarity in reverse complement");
+ return NULL;
+ }
+ AlnMgrIndexLite(sap);
+ Sqn_RemoveInconsistentAlnsFromSet(sap, 20, 1);
+ amaip = (AMAlignIndexPtr)(sap->saip);
+ AlnMgrSortAlnSetByNthRowPos(sap, 1);
+ Sqn_GetNthSeqRangeInSASet(sap, 1, &start1, &stop1);
+ Sqn_GetNthSeqRangeInSASet(sap, 2, &start2, &stop2);
+ strand = AlnMgrGetNthStrand(amaip->saps[0], 2);
+ }
+
+ /* done with any reverse complementing and reblasting, now extend frayed ends */
+
+ sap_head = NULL;
+
+ if (start1 > 6 && start1 < extnd)
+ sap_head = sap_prev = Sqn_FindPiece(bsp1, bsp2, MAX(start1-SQN_WINDOW, 0), start1, MAX(start1-SQN_WINDOW, 0), start2, strand, SQN_LEFT);
+ else if (start1 > 0 && start1 < extnd)
+ SQN_ExtendAlnAlg(amaip->saps[0], start1, SQN_LEFT, Seq_strand_plus);
+ Sqn_GetNthSeqRangeInSASet(sap, 1, &start1, &stop1);
+ Sqn_GetNthSeqRangeInSASet(sap, 2, &start2, &stop2);
+ if (start2 > 6 && start2 < extnd)
+ {
+ sap_new = Sqn_FindPiece(bsp2, bsp1, MAX(start2-SQN_WINDOW, 0), start2, MAX(start1-SQN_WINDOW, 0), start1, strand, SQN_LEFT);
+ if (sap_new != NULL)
+ SPI_flip_sa_list(sap_new);
+ if (sap_head != NULL)
+ {
+ sap_prev->next = sap_new;
+ sap_prev = sap_new;
+ } else
+ sap_head = sap_prev = sap_new;
+ } else if (start2 > 0 && start2 < extnd)
+ SQN_ExtendAlnAlg(amaip->saps[0], start2, SQN_LEFT, Seq_strand_plus);
+ for (i=0; i<amaip->numsaps-1; i++)
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 1, NULL, &start1);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 1, &stop1, NULL);
+ if (strand != Seq_strand_minus)
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, NULL, &start2);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, &stop2, NULL);
+ } else
+ {
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i], 2, &stop2, NULL);
+ AlnMgrGetNthSeqRangeInSA(amaip->saps[i+1], 2, NULL, &start2);
+ }
+ sap_new = Sqn_FindPiece(bsp1, bsp2, start1, stop1, start2, stop2, strand, SQN_MIDDLE);
+ if (sap_head)
+ {
+ sap_prev->next = sap_new;
+ if (sap_new != NULL)
+ sap_prev = sap_new;
+ } else
+ sap_head = sap_prev = sap_new;
+ }
+ Sqn_GetNthSeqRangeInSASet(sap, 1, &start1, &stop1);
+ Sqn_GetNthSeqRangeInSASet(sap, 2, &start2, &stop2);
+ if (bsp1->length-stop1 > 6 && bsp1->length-stop1 < extnd)
+ {
+ sap_new = Sqn_FindPiece(bsp1, bsp2, stop1, MIN(bsp1->length-1, stop1 + SQN_WINDOW), stop2, MIN(bsp2->length-1, stop2+SQN_WINDOW), strand, SQN_RIGHT);
+ if (sap_new != NULL)
+ {
+ if (sap_head != NULL)
+ {
+ sap_prev->next = sap_new;
+ sap_prev = sap_new;
+ } else
+ sap_head = sap_new;
+ }
+ } else if (bsp1->length-stop1 > 0 && bsp1->length-stop1 < extnd)
+ SQN_ExtendAlnAlg(amaip->saps[amaip->numsaps-1], bsp1->length-stop1, SQN_RIGHT, Seq_strand_plus);
+ Sqn_GetNthSeqRangeInSASet(sap, 1, &start1, &stop1);
+ Sqn_GetNthSeqRangeInSASet(sap, 2, &start2, &stop2);
+ if (bsp2->length-stop2 > 6 && bsp2->length-stop2 < extnd)
+ {
+ sap_new = Sqn_FindPiece(bsp2, bsp1, stop2, MIN(bsp2->length-1, stop2 + SQN_WINDOW), stop1, MIN(bsp1->length-1, stop1+SQN_WINDOW), strand, SQN_RIGHT);
+ if (sap_new != NULL)
+ {
+ SPI_flip_sa_list(sap_new);
+ if (sap_head != NULL)
+ {
+ sap_prev->next = sap_new;
+ sap_prev = sap_new;
+ } else
+ sap_head = sap_new;
+ }
+ } else if (bsp2->length-stop2 > 0 && bsp2->length-stop2 < extnd)
+ SQN_ExtendAlnAlg(amaip->saps[amaip->numsaps-1], bsp2->length-stop2, SQN_RIGHT, Seq_strand_plus);
+ sap_new = (SeqAlignPtr)(sap->segs);
+ while (sap_new->next != NULL)
+ {
+ sap_new = sap_new->next;
+ }
+ sap_new->next = sap_head; /* put the new alignments in the original set */
+ AMAlignIndexFree(amaip);
+ sap->saip = NULL;
+ AlnMgrIndexLite(sap); /* reindex the alignments */
+ sap_final = Sqn_CleanUpAlignments(sap, bsp1->length, bsp2->length);
+ return sap_final;
+}
+
+typedef struct upsdata {
+ FORM_MESSAGE_BLOCK
+ BioseqPtr oldbsp;
+ BioseqPtr newbsp;
+ SeqAlignPtr salp;
+ Boolean revcomp;
+ Boolean diffOrgs;
+ Int4 aln_length;
+ Int4 log10_aln_length;
+ Int4 old5, olda, old3;
+ Int4 new5, newa, new3;
+ Int4 recomb1, recomb2;
+ Int4 startmax, stopmax;
+ Uint1 strandold, strandnew;
+ CharPtr seq1, seq2, aln1, aln2;
+ VieweR overview;
+ SegmenT ovpict;
+ VieweR details;
+ SegmenT dtpict;
+ PaneL letters;
+ Int2 charwidth;
+ Int2 lineheight;
+ Int2 maxchars;
+ Int4 scaleX;
+ ValNodePtr indels;
+ ValNodePtr mismatches;
+ GrouP rmc;
+ GrouP sfb;
+ GrouP nobm;
+ ButtoN keepProteinIDs;
+ ButtoN accept;
+} UpsData, PNTR UpsDataPtr;
+
+static Boolean AdjustAlignment (
+ UpsDataPtr udp,
+ Int2 choice
+)
+
+{
+ DenseSegPtr dsp;
+ Int2 j;
+ SeqAlignPtr sap;
+
+ if (udp == NULL) return FALSE;
+
+ sap = udp->salp;
+ if (sap == NULL) return FALSE;
+ AMFreeAllIndexes (sap);
+
+ if (sap->segtype == SAS_DENSEG) {
+ dsp = (DenseSegPtr) sap->segs;
+
+ switch (choice) {
+ case 2 :
+ /* adjust alignment 5' */
+ if (dsp != NULL && dsp->lens != NULL && dsp->numseg > 0) {
+ dsp->lens [dsp->numseg - 1] += udp->old3;
+ }
+ break;
+ case 3 :
+ /* adjust alignment 3' */
+ if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
+ dsp->lens [0] += udp->old5;
+ dsp->starts [0] = 0;
+ dsp->starts [1] = 0;
+ for (j = 1; j < dsp->numseg; j++) {
+ if (dsp->starts [1 + j * 2] != -1) {
+ dsp->starts [1 + j * 2] += udp->old5 - udp->new5;
+ }
+ }
+ }
+ break;
+ case 4 :
+ /* adjust alignment patch */
+ if (dsp != NULL && dsp->lens != NULL && dsp->starts != NULL && dsp->numseg > 0) {
+ dsp->lens [dsp->numseg - 1] += udp->old3;
+ dsp->lens [0] += udp->old5;
+ dsp->starts [0] = 0;
+ dsp->starts [1] = 0;
+ for (j = 1; j < dsp->numseg; j++) {
+ if (dsp->starts [1 + j * 2] != -1) {
+ dsp->starts [1 + j * 2] += udp->old5 - udp->new5;
+ }
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ }
+
+ AlnMgrIndexSingleChildSeqAlign (sap);
+
+ return TRUE;
+}
+
+/*
+static Int4 MapBioseqToBioseq (SeqAlignPtr salp, Int4 pos, Int4 which_end)
+
+{
+ Int4 alnpt, newpt;
+
+ alnpt = AlnMgrMapBioseqToSeqAlign (salp, pos, 1, NULL);
+ if (alnpt < 0) return pos;
+ newpt = AlnMgrMapRowCoords (salp, alnpt, 2, NULL);
+ if (newpt < 0) return pos;
+ return newpt;
+}
+*/
+
+static void OffsetLoc (SeqLocPtr slp, Int4 offset, SeqIdPtr sip)
+
+{
+ PackSeqPntPtr psp;
+ SeqIntPtr sinp;
+ SeqPntPtr spp;
+ Uint1 used;
+
+ if (slp == NULL) return;
+ switch (slp->choice) {
+ case SEQLOC_INT :
+ sinp = (SeqIntPtr) slp->data.ptrvalue;
+ if (sinp != NULL) {
+ sinp->from += offset;
+ sinp->to += offset;
+ if (sip != NULL) {
+ sinp->id = SeqIdFree (sinp->id);
+ sinp->id = SeqIdDup (sip);
+ }
+ }
+ break;
+ case SEQLOC_PNT :
+ spp = (SeqPntPtr) slp->data.ptrvalue;
+ if (spp != NULL) {
+ spp->point += offset;
+ if (sip != NULL) {
+ spp->id = SeqIdFree (spp->id);
+ spp->id = SeqIdDup (sip);
+ }
+ }
+ break;
+ case SEQLOC_PACKED_PNT :
+ psp = (PackSeqPntPtr) slp->data.ptrvalue;
+ if (psp != NULL) {
+ for (used = 0; used < psp->used; used++) {
+ psp->pnts [used] += offset;
+ }
+ if (sip != NULL) {
+ psp->id = SeqIdFree (psp->id);
+ psp->id = SeqIdDup (sip);
+ }
+ }
+ break;
+ default :
+ break;
+ }
+}
+
+static void OffsetLocation (SeqLocPtr loc, Int4 offset, SeqIdPtr sip)
+
+{
+ SeqLocPtr slp;
+
+ slp = SeqLocFindNext (loc, NULL);
+ while (slp != NULL) {
+ OffsetLoc (slp, offset, sip);
+ slp = SeqLocFindNext (loc, slp);
+ }
+}
+
+static void PromoteSeqId (SeqIdPtr sip, Pointer userdata)
+
+{
+ SeqIdPtr bestid, newid, oldid;
+
+ bestid = (SeqIdPtr) userdata;
+
+ newid = SeqIdDup (bestid);
+ if (newid == NULL) return;
+
+ oldid = ValNodeNew (NULL);
+ if (oldid == NULL) return;
+
+ MemCopy (oldid, sip, sizeof (ValNode));
+ oldid->next = NULL;
+
+ sip->choice = newid->choice;
+ sip->data.ptrvalue = newid->data.ptrvalue;
+
+ SeqIdFree (oldid);
+ ValNodeFree (newid);
+
+ SeqIdStripLocus (sip);
+}
+
+static void CorrectFeatureSeqIds (
+ SeqFeatPtr sfp,
+ Pointer userdata
+)
+
+{
+ VisitSeqIdsInSeqLoc (sfp->location, userdata, PromoteSeqId);
+}
+
+static Boolean DoFeaturePropWithOffset (
+ UpsDataPtr udp,
+ Int4 offset,
+ SeqAnnotPtr PNTR sapp
+)
+
+{
+ BioseqPtr bsp, newbsp, oldbsp;
+ CodeBreakPtr cbp;
+ SeqMgrFeatContext context;
+ CdRegionPtr crp;
+ SeqFeatPtr dup, sfp, last = NULL;
+ Uint2 entityID;
+ Boolean keepProteinIDs;
+ SeqEntryPtr newsep, prdsep, top;
+ RnaRefPtr rrp;
+ SeqAnnotPtr sap = NULL, saptmp;
+ SeqDescrPtr sdp;
+ SeqIdPtr sip;
+ tRNAPtr trp;
+
+ if (udp == NULL) return FALSE;
+
+ SeqEntrySetScope (NULL);
+
+ sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &context);
+ if (sfp == NULL) return FALSE;
+
+ if (udp->diffOrgs) {
+ keepProteinIDs = FALSE;
+ } else {
+ keepProteinIDs = GetStatus (udp->keepProteinIDs);
+ }
+
+ oldbsp = udp->oldbsp;
+
+ entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
+ top = GetBestTopParentForData (entityID, udp->oldbsp);
+
+ sdp = ExtractBioSourceAndPubs (top);
+
+ sip = SeqIdFindBest (oldbsp->id, 0);
+
+ while (sfp != NULL) {
+
+ dup = AsnIoMemCopy ((Pointer) sfp,
+ (AsnReadFunc) SeqFeatAsnRead,
+ (AsnWriteFunc) SeqFeatAsnWrite);
+
+ if (last == NULL) {
+ sap = SeqAnnotNew ();
+ if (oldbsp->annot == NULL) {
+ oldbsp->annot = sap;
+ } else {
+ for (saptmp = oldbsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
+ saptmp->next = sap;
+ }
+ sap->type = 1;
+ sap->data = (Pointer) dup;
+ } else {
+ last->next = dup;
+ }
+ last = dup;
+
+ /*
+ sep = SeqMgrGetSeqEntryForData (oldbsp);
+ CreateNewFeature (sep, NULL, dup->data.choice, dup);
+ */
+
+ OffsetLocation (dup->location, offset, sip);
+ switch (dup->data.choice) {
+ case SEQFEAT_CDREGION :
+ crp = (CdRegionPtr) dup->data.value.ptrvalue;
+ if (crp != NULL) {
+ for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
+ OffsetLocation (cbp->loc, offset, sip);
+ }
+ }
+ break;
+ case SEQFEAT_RNA :
+ rrp = (RnaRefPtr) dup->data.value.ptrvalue;
+ if (rrp != NULL && rrp->ext.choice == 2) {
+ trp = (tRNAPtr) rrp->ext.value.ptrvalue;
+ if (trp != NULL && trp->anticodon != NULL) {
+ OffsetLocation (trp->anticodon, offset, sip);
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ if (dup->product != NULL) {
+ SeqEntrySetScope (NULL);
+ bsp = BioseqFindFromSeqLoc (dup->product);
+ if (bsp != NULL) {
+ prdsep = SeqMgrGetSeqEntryForData (bsp);
+ if (prdsep != NULL) {
+ newsep = AsnIoMemCopy ((Pointer) prdsep,
+ (AsnReadFunc) SeqEntryAsnRead,
+ (AsnWriteFunc) SeqEntryAsnWrite);
+ if (newsep != NULL) {
+ if (IS_Bioseq (newsep)) {
+ newbsp = (BioseqPtr) newsep->data.ptrvalue;
+ if (newbsp != NULL) {
+ if (! keepProteinIDs) {
+ newbsp->id = SeqIdSetFree (newbsp->id);
+ newbsp->id = MakeNewProteinSeqId (NULL, sip);
+ newbsp->hist = SeqHistFree (newbsp->hist);
+ VisitFeaturesOnBsp (newbsp, (Pointer) newbsp->id, CorrectFeatureSeqIds);
+ SetSeqFeatProduct (dup, newbsp);
+ /*
+ dup->product = SeqLocFree (dup->product);
+ dup->product = CreateWholeInterval (newsep);
+ */
+ }
+ SeqMgrReplaceInBioseqIndex (newbsp);
+ }
+ }
+ AddSeqEntryToSeqEntry (top, newsep, TRUE);
+ }
+ }
+ }
+ }
+
+ sfp = SeqMgrGetNextFeature (udp->newbsp, sfp, 0, 0, &context);
+ }
+
+ ReplaceBioSourceAndPubs (top, sdp);
+
+ if (sapp != NULL) {
+ *sapp = sap;
+ }
+
+ return TRUE;
+}
+
+static void ReplaceLocation (SeqAlignPtr salp, SeqLocPtr slp, Int4 length, Int4 begin, Int4 fin)
+
+{
+ PackSeqPntPtr psp;
+ Int4 pt;
+ SeqIntPtr sinp;
+ SeqPntPtr spp;
+ Uint1 used;
+
+ if (slp == NULL) return;
+ switch (slp->choice) {
+ case SEQLOC_INT :
+ sinp = (SeqIntPtr) slp->data.ptrvalue;
+ if (sinp != NULL) {
+ pt = MapBioseqToBioseqSpecial (salp, begin, fin, sinp->from, SQN_LEFT);
+ if (pt < 0) {
+ pt = 0;
+ } else if (pt >= length) {
+ pt = length - 1;
+ }
+ sinp->from = pt;
+ pt = MapBioseqToBioseqSpecial (salp, begin, fin, sinp->to, SQN_RIGHT);
+ if (pt < 0) {
+ pt = 0;
+ } else if (pt >= length) {
+ pt = length - 1;
+ }
+ sinp->to = pt;
+ }
+ break;
+ case SEQLOC_PNT :
+ spp = (SeqPntPtr) slp->data.ptrvalue;
+ if (spp != NULL) {
+ pt = MapBioseqToBioseqSpecial (salp, begin, fin, spp->point, SQN_LEFT);
+ if (pt < 0) {
+ pt = 0;
+ } else if (pt >= length) {
+ pt = length - 1;
+ }
+ spp->point = pt;
+ }
+ break;
+ case SEQLOC_PACKED_PNT :
+ psp = (PackSeqPntPtr) slp->data.ptrvalue;
+ if (psp != NULL) {
+ for (used = 0; used < psp->used; used++) {
+ pt = MapBioseqToBioseqSpecial (salp, begin, fin, psp->pnts [used], SQN_LEFT);
+ if (pt < 0) {
+ pt = 0;
+ } else if (pt >= length) {
+ pt = length - 1;
+ }
+ psp->pnts [used] = pt;
+ }
+ }
+ break;
+ default :
+ break;
+ }
+}
+
+static Boolean DoFeaturePropThruAlign (
+ UpsDataPtr udp,
+ SeqAnnotPtr PNTR sapp
+)
+
+{
+ BioseqPtr bsp, newbsp, oldbsp;
+ CodeBreakPtr cbp, prevcbp, nextcbp;
+ SeqMgrFeatContext context;
+ CdRegionPtr crp;
+ SeqFeatPtr dup, sfp, last = NULL;
+ Uint2 entityID;
+ Int4 from, to;
+ Boolean keepProteinIDs;
+ SeqLocPtr newloc, slp;
+ SeqEntryPtr newsep, prdsep, top;
+ RnaRefPtr rrp;
+ SeqAnnotPtr sap = NULL, saptmp;
+ SeqDescrPtr sdp;
+ SeqIdPtr sip;
+ Boolean split;
+ tRNAPtr trp;
+
+ if (udp == NULL) return FALSE;
+
+ SeqEntrySetScope (NULL);
+
+ sfp = SeqMgrGetNextFeature (udp->newbsp, NULL, 0, 0, &context);
+ if (sfp == NULL) return FALSE;
+
+ keepProteinIDs = GetStatus (udp->keepProteinIDs);
+
+ oldbsp = udp->oldbsp;
+
+ entityID = ObjMgrGetEntityIDForPointer (oldbsp);
+ top = GetBestTopParentForData (entityID, oldbsp);
+
+ sdp = ExtractBioSourceAndPubs (top);
+
+ sip = SeqIdFindBest (oldbsp->id, 0);
+
+ from = udp->new5;
+ to = udp->new5 + udp->newa;
+
+ while (sfp != NULL) {
+
+ if (context.right >= from && context.left <= to) {
+ split = FALSE;
+ newloc = SeqLocCopyRegion (oldbsp->id, sfp->location, udp->newbsp, from, to, Seq_strand_plus, &split);
+ if (newloc != NULL) {
+ OffsetLocation (newloc, from, NULL);
+ dup = AsnIoMemCopy ((Pointer) sfp,
+ (AsnReadFunc) SeqFeatAsnRead,
+ (AsnWriteFunc) SeqFeatAsnWrite);
+ SeqLocFree (dup->location);
+ dup->location = newloc;
+ if (split) {
+ dup->partial = TRUE;
+ }
+
+ if (last == NULL) {
+ sap = SeqAnnotNew ();
+ if (oldbsp->annot == NULL) {
+ oldbsp->annot = sap;
+ } else {
+ for (saptmp = oldbsp->annot; saptmp->next != NULL; saptmp = saptmp->next) continue;
+ saptmp->next = sap;
+ }
+ sap->type = 1;
+ sap->data = (Pointer) dup;
+ } else {
+ last->next = dup;
+ }
+ last = dup;
+
+ /*
+ sep = SeqMgrGetSeqEntryForData (oldbsp);
+ CreateNewFeature (sep, NULL, dup->data.choice, dup);
+ */
+
+ slp = SeqLocFindNext (dup->location, NULL);
+ while (slp != NULL) {
+ ReplaceLocation (udp->salp, slp, oldbsp->length, 2, 1);
+ slp = SeqLocFindNext (dup->location, slp);
+ }
+ switch (dup->data.choice) {
+ case SEQFEAT_CDREGION :
+ crp = (CdRegionPtr) dup->data.value.ptrvalue;
+ if (crp != NULL) {
+ prevcbp = NULL;
+ for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp) {
+ nextcbp = cbp->next;
+ newloc = SeqLocCopyRegion (oldbsp->id, cbp->loc, udp->newbsp, from, to, Seq_strand_plus, &split);
+ OffsetLocation (newloc, from, NULL);
+ SeqLocFree (cbp->loc);
+ cbp->loc = newloc;
+ if (cbp->loc == NULL) {
+ if (prevcbp != NULL) {
+ prevcbp->next = nextcbp;
+ } else {
+ crp->code_break = nextcbp;
+ }
+ cbp->next = NULL;
+ CodeBreakFree (cbp);
+ } else {
+ prevcbp = cbp;
+ slp = SeqLocFindNext (cbp->loc, NULL);
+ while (slp != NULL) {
+ ReplaceLocation (udp->salp, slp, oldbsp->length, 2, 1);
+ slp = SeqLocFindNext (cbp->loc, slp);
+ }
+ }
+ }
+ }
+ break;
+ case SEQFEAT_RNA :
+ rrp = (RnaRefPtr) dup->data.value.ptrvalue;
+ if (rrp != NULL && rrp->ext.choice == 2) {
+ trp = (tRNAPtr) rrp->ext.value.ptrvalue;
+ if (trp != NULL && trp->anticodon != NULL) {
+ newloc = SeqLocCopyRegion (oldbsp->id, trp->anticodon, udp->newbsp, from, to, Seq_strand_plus, &split);
+ OffsetLocation (newloc, from, NULL);
+ SeqLocFree (trp->anticodon);
+ trp->anticodon = newloc;
+ slp = SeqLocFindNext (trp->anticodon, NULL);
+ while (slp != NULL) {
+ ReplaceLocation (udp->salp, slp, oldbsp->length, 2, 1);
+ slp = SeqLocFindNext (trp->anticodon, slp);
+ }
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ if (dup->product != NULL) {
+ SeqEntrySetScope (NULL);
+ bsp = BioseqFindFromSeqLoc (dup->product);
+ if (bsp != NULL) {
+ prdsep = SeqMgrGetSeqEntryForData (bsp);
+ if (prdsep != NULL) {
+ newsep = AsnIoMemCopy ((Pointer) prdsep,
+ (AsnReadFunc) SeqEntryAsnRead,
+ (AsnWriteFunc) SeqEntryAsnWrite);
+ if (newsep != NULL) {
+ if (IS_Bioseq (newsep)) {
+ newbsp = (BioseqPtr) newsep->data.ptrvalue;
+ if (newbsp != NULL) {
+ if (! keepProteinIDs) {
+ newbsp->id = SeqIdSetFree (newbsp->id);
+ newbsp->id = MakeNewProteinSeqId (NULL, sip);
+ VisitFeaturesOnBsp (newbsp, (Pointer) newbsp->id, CorrectFeatureSeqIds);
+ SetSeqFeatProduct (dup, newbsp);
+ /*
+ dup->product = SeqLocFree (dup->product);
+ dup->product = CreateWholeInterval (newsep);
+ */
+ }
+ SeqMgrReplaceInBioseqIndex (newbsp);
+ }
+ }
+ AddSeqEntryToSeqEntry (top, newsep, TRUE);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ sfp = SeqMgrGetNextFeature (udp->newbsp, sfp, 0, 0, &context);
+ }
+
+ ReplaceBioSourceAndPubs (top, sdp);
+
+ if (sapp != NULL) {
+ *sapp = sap;
+ }
+
+ return TRUE;
+}
+
+static Boolean ReplaceSequence (UpsDataPtr udp)
+
+{
+ MsgAnswer ans;
+ ByteStorePtr bs;
+ CodeBreakPtr cbp;
+ SeqMgrFeatContext context;
+ CdRegionPtr crp;
+ Int4 len;
+ BioseqPtr newbsp;
+ BioseqPtr oldbsp;
+ RnaRefPtr rrp;
+ Uint1 seq_data_type;
+ SeqFeatPtr sfp;
+ SeqLocPtr slp;
+ tRNAPtr trp;
+
+ if (StringICmp (udp->seq1, udp->seq2) == 0) {
+ ans = Message (MSG_OKC, "Replacement sequence is identical to original - possible error");
+ if (ans == ANS_CANCEL) return FALSE;
+ }
+
+ oldbsp = udp->oldbsp;
+ newbsp = udp->newbsp;
+
+ sfp = SeqMgrGetNextFeature (oldbsp, NULL, 0, 0, &context);
+ while (sfp != NULL) {
+ slp = SeqLocFindNext (sfp->location, NULL);
+ while (slp != NULL) {
+ ReplaceLocation (udp->salp, slp, newbsp->length, 1, 2);
+ slp = SeqLocFindNext (sfp->location, slp);
+ }
+ switch (sfp->data.choice) {
+ case SEQFEAT_CDREGION :
+ crp = (CdRegionPtr) sfp->data.value.ptrvalue;
+ if (crp != NULL) {
+ for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
+ slp = SeqLocFindNext (cbp->loc, NULL);
+ while (slp != NULL) {
+ ReplaceLocation (udp->salp, slp, newbsp->length, 1, 2);
+ slp = SeqLocFindNext (cbp->loc, slp);
+ }
+ }
+ }
+ break;
+ case SEQFEAT_RNA :
+ rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
+ if (rrp != NULL && rrp->ext.choice == 2) {
+ trp = (tRNAPtr) rrp->ext.value.ptrvalue;
+ if (trp != NULL && trp->anticodon != NULL) {
+ slp = SeqLocFindNext (trp->anticodon, NULL);
+ while (slp != NULL) {
+ ReplaceLocation (udp->salp, slp, newbsp->length, 1, 2);
+ slp = SeqLocFindNext (trp->anticodon, slp);
+ }
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ sfp = SeqMgrGetNextFeature (oldbsp, sfp, 0, 0, &context);
+ }
+
+ bs = oldbsp->seq_data;
+ oldbsp->seq_data = newbsp->seq_data;
+ newbsp->seq_data = bs;
+ len = oldbsp->length;
+ oldbsp->length = newbsp->length;
+ newbsp->length = len;
+ seq_data_type = oldbsp->seq_data_type;
+ oldbsp->seq_data_type = newbsp->seq_data_type;
+ newbsp->seq_data_type = seq_data_type;
+
+ return TRUE;
+}
+
+static Boolean Merge5Prime (UpsDataPtr udp)
+
+{
+ ByteStorePtr bs;
+ Char ch;
+ Int4 i, newlen;
+ BioseqPtr newbsp;
+ CharPtr ptr, str, tmp;
+
+ newlen = udp->new5 + udp->newa + udp->old3;
+ str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
+ if (str == NULL) return FALSE;
+
+ /* construct replacement sequence by recombining between old and overlap */
+ ptr = str;
+
+ tmp = udp->seq2;
+ for (i = 0; i < udp->new5 + udp->newa; i++) {
+ ch = *tmp;
+ *ptr = ch;
+ tmp++;
+ ptr++;
+ }
+
+ tmp = udp->seq1 + udp->old5 + udp->olda;
+ for (i = 0; i < udp->old3; i++) {
+ ch = *tmp;
+ *ptr = ch;
+ tmp++;
+ ptr++;
+ }
+
+ *ptr = '\0';
+ bs = BSNew (newlen);
+ BSWrite (bs, (VoidPtr) str, newlen);
+
+ udp->seq2 = MemFree (udp->seq2);
+ udp->seq2 = str;
+
+ if (bs != NULL && BSLen (bs) < 1) {
+ bs = BSFree (bs);
+ }
+ if (bs == NULL) return FALSE;
+
+ /* overlap turned into replacement sequence */
+
+ newbsp = udp->newbsp;
+ newbsp->seq_data = BSFree (newbsp->seq_data);
+ newbsp->seq_data = bs;
+ newbsp->seq_data_type = Seq_code_iupacna;
+ newbsp->length = newlen;
+
+ /* adjust alignment and reindex */
+
+ if (! AdjustAlignment (udp, 2)) return FALSE;
+
+ /* then finish by replacing with new sequence */
+
+ return ReplaceSequence (udp);
+}
+
+static Boolean Merge3Prime (UpsDataPtr udp)
+
+{
+ ByteStorePtr bs;
+ Char ch;
+ Int4 i, newlen;
+ BioseqPtr newbsp;
+ CharPtr ptr, str, tmp;
+
+ newlen = udp->old5 + udp->newa + udp->new3;
+ str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
+ if (str == NULL) return FALSE;
+
+ /* construct replacement sequence by recombining between old and overlap */
+ ptr = str;
+
+ tmp = udp->seq1;
+ for (i = 0; i < udp->old5; i++) {
+ ch = *tmp;
+ *ptr = ch;
+ tmp++;
+ ptr++;
+ }
+
+ tmp = udp->seq2 + udp->new5;
+ for (i = 0; i < udp->newa + udp->new3; i++) {
+ ch = *tmp;
+ *ptr = ch;
+ tmp++;
+ ptr++;
+ }
+
+ *ptr = '\0';
+ bs = BSNew (newlen);
+ BSWrite (bs, (VoidPtr) str, newlen);
+
+ udp->seq2 = MemFree (udp->seq2);
+ udp->seq2 = str;
+
+ if (bs != NULL && BSLen (bs) < 1) {
+ bs = BSFree (bs);
+ }
+ if (bs == NULL) return FALSE;
+
+ /* overlap turned into replacement sequence */
+
+ newbsp = udp->newbsp;
+ newbsp->seq_data = BSFree (newbsp->seq_data);
+ newbsp->seq_data = bs;
+ newbsp->seq_data_type = Seq_code_iupacna;
+ newbsp->length = newlen;
+
+ /* adjust alignment and reindex */
+
+ if (! AdjustAlignment (udp, 3)) return FALSE;
+
+ /* then finish by replacing with new sequence */
+
+ return ReplaceSequence (udp);
+}
+
+static Boolean PatchSequence (UpsDataPtr udp)
+
+{
+ ByteStorePtr bs;
+ Char ch;
+ Int4 i, newlen;
+ BioseqPtr newbsp;
+ CharPtr ptr, str, tmp;
+
+ newlen = udp->old5 + udp->newa + udp->old3;
+ str = (CharPtr) MemNew (sizeof (Char) * (size_t) (newlen + 5));
+ if (str == NULL) return FALSE;
+
+ /* construct replacement sequence by double recombination */
+ ptr = str;
+
+ tmp = udp->seq1;
+ for (i = 0; i < udp->old5; i++) {
+ ch = *tmp;
+ *ptr = ch;
+ tmp++;
+ ptr++;
+ }
+
+ tmp = udp->seq2 + udp->new5;
+ for (i = 0; i < udp->newa; i++) {
+ ch = *tmp;
+ *ptr = ch;
+ tmp++;
+ ptr++;
+ }
+
+ tmp = udp->seq1 + udp->old5 + udp->olda;
+ for (i = 0; i < udp->old3; i++) {
+ ch = *tmp;
+ *ptr = ch;
+ tmp++;
+ ptr++;
+ }
+
+ *ptr = '\0';
+ bs = BSNew (newlen);
+ BSWrite (bs, (VoidPtr) str, newlen);
+
+ udp->seq2 = MemFree (udp->seq2);
+ udp->seq2 = str;
+
+ if (bs != NULL && BSLen (bs) < 1) {
+ bs = BSFree (bs);
+ }
+ if (bs == NULL) return FALSE;
+
+ /* overlap turned into replacement sequence */
+
+ newbsp = udp->newbsp;
+ newbsp->seq_data = BSFree (newbsp->seq_data);
+ newbsp->seq_data = bs;
+ newbsp->seq_data_type = Seq_code_iupacna;
+ newbsp->length = newlen;
+
+ /* adjust alignment and reindex */
+
+ if (! AdjustAlignment (udp, 4)) return FALSE;
+
+ /* then finish by replacing with new sequence */
+
+ return ReplaceSequence (udp);
+}
+
+static void MarkProductForDeletion (
+ SeqLocPtr product
+)
+
+{
+ BioseqPtr bsp;
+ SeqIdPtr sip;
+
+ if (product == NULL) return;
+ sip = SeqLocId (product);
+ if (sip == NULL) return;
+ bsp = BioseqFind (sip);
+ if (bsp == NULL) return;
+ bsp->idx.deleteme = TRUE;
+}
+
+static void CombineTexts (
+ CharPtr PNTR txtptr,
+ CharPtr PNTR oldtxtptr
+)
+
+{
+ size_t len;
+ CharPtr str;
+
+ if (txtptr == NULL || oldtxtptr == NULL) return;
+
+ if (*txtptr == NULL) {
+
+ *txtptr = *oldtxtptr;
+ *oldtxtptr = NULL;
+
+ } else if (*oldtxtptr != NULL && StringICmp (*txtptr, *oldtxtptr) != 0) {
+
+ len = StringLen (*txtptr) + StringLen (*oldtxtptr) + 5;
+ str = MemNew (sizeof (Char) * len);
+ StringCpy (str, *txtptr);
+ StringCat (str, "; ");
+ StringCat (str, *oldtxtptr);
+ *txtptr = MemFree (*txtptr);
+ *txtptr = str;
+ }
+}
+
+static void FuseCommonFeatureFields (
+ SeqFeatPtr sfp,
+ SeqFeatPtr oldsfp
+)
+
+{
+ GBQualPtr lastgbq;
+ SeqFeatXrefPtr lastxref;
+
+ if (sfp == NULL || oldsfp == NULL) return;
+
+ CombineTexts (&(sfp->comment), &(oldsfp->comment));
+ CombineTexts (&(sfp->title), &(oldsfp->title));
+ CombineTexts (&(sfp->except_text), &(oldsfp->except_text));
+
+ if (sfp->qual == NULL) {
+ sfp->qual = oldsfp->qual;
+ oldsfp->qual = NULL;
+ } else if (oldsfp->qual != NULL) {
+ for (lastgbq = sfp->qual; lastgbq->next != NULL; lastgbq = lastgbq->next) continue;
+ lastgbq->next = oldsfp->qual;
+ oldsfp->qual = NULL;
+ }
+
+ ValNodeLink (&(sfp->dbxref), oldsfp->dbxref);
+ oldsfp->dbxref = NULL;
+
+ ValNodeLink (&(sfp->cit), oldsfp->cit);
+ oldsfp->cit = NULL;
+
+ if (sfp->xref == NULL) {
+ sfp->xref = oldsfp->xref;
+ oldsfp->xref = NULL;
+ } else if (oldsfp->xref != NULL) {
+ for (lastxref = sfp->xref; lastxref->next != NULL; lastxref = lastxref->next) continue;
+ lastxref->next = oldsfp->xref;
+ oldsfp->xref = NULL;
+ }
+
+ if (sfp->ext == NULL) {
+ sfp->ext = oldsfp->ext;
+ oldsfp->ext = NULL;
+ } else if (oldsfp->ext != NULL) {
+ sfp->ext = CombineUserObjects (sfp->ext, oldsfp->ext);
+ oldsfp->ext = NULL;
+ }
+
+ sfp->partial |= oldsfp->partial;
+ sfp->excpt |= oldsfp->excpt;
+ sfp->pseudo |= oldsfp->pseudo;
+}
+
+static void FuseFeatures (
+ SeqFeatPtr sfp,
+ SeqFeatPtr oldsfp
+)
+
+{
+ GeneRefPtr grp, oldgrp;
+ BioseqPtr prod, oldprod;
+ SeqFeatPtr prot, oldprot;
+ ProtRefPtr prp, oldprp;
+ RnaRefPtr rrp, oldrrp;
+ SeqIdPtr sip;
+
+ if (sfp == NULL || oldsfp == NULL) return;
+
+ /* merge common fields */
+
+ FuseCommonFeatureFields (sfp, oldsfp);
+
+ /* now deal with type-specific data */
+
+ switch (sfp->data.choice) {
+ case SEQFEAT_GENE :
+ grp = (GeneRefPtr) sfp->data.value.ptrvalue;
+ oldgrp = (GeneRefPtr) oldsfp->data.value.ptrvalue;
+ if (grp == NULL || oldgrp == NULL) return;
+ CombineTexts (&(grp->locus), &(oldgrp->locus));
+ CombineTexts (&(grp->allele), &(oldgrp->allele));
+ CombineTexts (&(grp->desc), &(oldgrp->desc));
+ CombineTexts (&(grp->maploc), &(oldgrp->maploc));
+ grp->pseudo |= oldgrp->pseudo;
+ ValNodeLink (&(grp->db), oldgrp->db);
+ oldgrp->db = NULL;
+ ValNodeLink (&(grp->syn), oldgrp->syn);
+ oldgrp->syn = NULL;
+ break;
+ case SEQFEAT_CDREGION :
+ sip = SeqLocId (sfp->product);
+ prod = BioseqFind (sip);
+ sip = SeqLocId (oldsfp->product);
+ oldprod = BioseqFind (sip);
+ if (prod == NULL || oldprod == NULL) return;
+ prot = SeqMgrGetBestProteinFeature (prod, NULL);
+ oldprot = SeqMgrGetBestProteinFeature (oldprod, NULL);
+ if (prot == NULL || oldprot == NULL) return;
+ FuseCommonFeatureFields (prot, oldprot);
+ prp = (ProtRefPtr) prot->data.value.ptrvalue;
+ oldprp = (ProtRefPtr) oldprot->data.value.ptrvalue;
+ if (prp == NULL || oldprp == NULL) return;
+ ValNodeLink (&(prp->name), oldprp->name);
+ oldprp->name = NULL;
+ ValNodeLink (&(prp->ec), oldprp->ec);
+ oldprp->ec = NULL;
+ ValNodeLink (&(prp->activity), oldprp->activity);
+ oldprp->activity = NULL;
+ ValNodeLink (&(prp->db), oldprp->db);
+ oldprp->db = NULL;
+ CombineTexts (&(prp->desc), &(oldprp->desc));
+ break;
+ case SEQFEAT_RNA :
+ rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
+ oldrrp = (RnaRefPtr) oldsfp->data.value.ptrvalue;
+ if (rrp == NULL || oldrrp == NULL) return;
+ if (rrp->ext.choice == 1 && oldrrp->ext.choice == 1) {
+ CombineTexts ((CharPtr PNTR) &(rrp->ext.value.ptrvalue), (CharPtr PNTR) &(oldrrp->ext.value.ptrvalue));
+ }
+ break;
+ case SEQFEAT_REGION :
+ case SEQFEAT_COMMENT :
+ if (sfp->data.value.ptrvalue == NULL || oldsfp->data.value.ptrvalue == NULL) return;
+ CombineTexts ((CharPtr PNTR) &(sfp->data.value.ptrvalue), (CharPtr PNTR) &(oldsfp->data.value.ptrvalue));
+ break;
+ default :
+ break;
+ }
+}
+
+static void ResolveDuplicateFeats (
+ UpsDataPtr udp,
+ BioseqPtr bsp,
+ SeqAnnotPtr sap
+)
+
+{
+ SeqMgrFeatContext context, lastcontext;
+ Int2 i, j;
+ Boolean ivalssame;
+ SeqFeatPtr lastsfp = NULL, sfp;
+ Int2 nobmval;
+
+ if (udp == NULL || bsp == NULL || sap == NULL) return;
+
+ nobmval = GetValue (udp->nobm);
+ if (nobmval == 3) return; /* keep both */
+
+ SeqMgrIndexFeatures (0, (Pointer) bsp);
+
+ lastsfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &context);
+ if (lastsfp == NULL) return;
+
+ MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
+
+ sfp = SeqMgrGetNextFeature (bsp, lastsfp, 0, 0, &context);
+ if (sfp == NULL) return;
+
+ while (sfp != NULL) {
+
+ if (context.left == lastcontext.left &&
+ context.right == lastcontext.right &&
+ context.featdeftype == lastcontext.featdeftype) {
+
+ if (context.strand == lastcontext.strand ||
+ lastcontext.strand == Seq_strand_unknown ||
+ context.strand == Seq_strand_unknown) {
+
+ ivalssame = TRUE;
+ if (context.numivals != lastcontext.numivals ||
+ context.ivals == NULL ||
+ lastcontext.ivals == NULL) {
+
+ ivalssame = FALSE;
+
+ } else {
+
+ for (i = 0, j = 0; i < lastcontext.numivals; i++, j += 2) {
+ if (context.ivals [j] != lastcontext.ivals [j]) {
+ ivalssame = FALSE;
+ }
+ if (context.ivals [j + 1] != lastcontext.ivals [j + 1]) {
+ ivalssame = FALSE;
+ }
+ }
+ }
+
+ if (ivalssame &&
+ context.sap != lastcontext.sap &&
+ (context.sap == sap || lastcontext.sap == sap)) {
+
+ if (nobmval == 1) { /* keep new */
+ if (context.sap == sap) {
+ lastsfp->idx.deleteme = TRUE;
+ MarkProductForDeletion (lastsfp->product);
+ } else if (lastcontext.sap == sap) {
+ sfp->idx.deleteme = TRUE;
+ MarkProductForDeletion (sfp->product);
+ }
+
+ } else if (nobmval == 2) { /* keep old */
+ if (context.sap == sap) {
+ sfp->idx.deleteme = TRUE;
+ MarkProductForDeletion (sfp->product);
+ } else if (lastcontext.sap == sap) {
+ lastsfp->idx.deleteme = TRUE;
+ MarkProductForDeletion (lastsfp->product);
+ }
+
+ } else if (nobmval == 4) { /* merge */
+ if (context.sap == sap) {
+ FuseFeatures (sfp, lastsfp);
+ lastsfp->idx.deleteme = TRUE;
+ MarkProductForDeletion (lastsfp->product);
+ } else if (lastcontext.sap == sap) {
+ FuseFeatures (lastsfp, sfp);
+ sfp->idx.deleteme = TRUE;
+ MarkProductForDeletion (sfp->product);
+ }
+ }
+ }
+ }
+ }
+
+ lastsfp = sfp;
+ MemCopy ((Pointer) &lastcontext, (Pointer) &context, sizeof (SeqMgrFeatContext));
+
+ sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
+ }
+}
+
+static void AcceptRMC (ButtoN b)
+
+{
+ Uint2 entityID;
+ Int2 rmcval, sfbval;
+ SeqAnnotPtr sap = NULL;
+ SeqEntryPtr sep;
+ UpsDataPtr udp;
+ Boolean update = FALSE;
+
+ udp = (UpsDataPtr) GetObjectExtra (b);
+ if (udp == NULL) return;
+ SafeHide (udp->form);
+ sfbval = GetValue (udp->sfb);
+ rmcval = GetValue (udp->rmc);
+ if (sfbval == 1 || sfbval == 3) {
+ switch (rmcval) {
+ case 1 :
+ if (ReplaceSequence (udp)) {
+ update = TRUE;
+ }
+ break;
+ case 2 :
+ if (Merge5Prime (udp)) {
+ update = TRUE;
+ }
+ break;
+ case 3 :
+ if (Merge3Prime (udp)) {
+ update = TRUE;
+ }
+ break;
+ case 4 :
+ if (PatchSequence (udp)) {
+ update = TRUE;
+ }
+ break;
+ default :
+ break;
+ }
+ if ( sfbval == 3) {
+ switch (rmcval) {
+ case 1 :
+ if (DoFeaturePropWithOffset (udp, 0, &sap)) {
+ update = TRUE;
+ }
+ break;
+ case 2 :
+ if (DoFeaturePropWithOffset (udp, 0, &sap)) {
+ update = TRUE;
+ }
+ break;
+ case 3 :
+ if (DoFeaturePropWithOffset (udp, udp->old5 - udp->new5, &sap)) {
+ update = TRUE;
+ }
+ break;
+ case 4 :
+ if (DoFeaturePropWithOffset (udp, udp->old5 - udp->new5, &sap)) {
+ update = TRUE;
+ }
+ break;
+ default :
+ break;
+ }
+ }
+ } else if (sfbval == 2) {
+ switch (rmcval) {
+ case 1 :
+ if (DoFeaturePropThruAlign (udp, &sap)) {
+ update = TRUE;
+ }
+ break;
+ case 2 :
+ if (DoFeaturePropThruAlign (udp, &sap)) {
+ update = TRUE;
+ }
+ break;
+ case 3 :
+ if (DoFeaturePropThruAlign (udp, &sap)) {
+ update = TRUE;
+ }
+ break;
+ case 4 :
+ if (DoFeaturePropThruAlign (udp, &sap)) {
+ update = TRUE;
+ }
+ break;
+ default :
+ break;
+ }
+ }
+ if (sfbval == 2 || sfbval == 3) {
+ if (update) {
+ entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
+ sep = GetTopSeqEntryForEntityID (entityID);
+ /* need to set scope to make sure we mark the right bioseq for deletion */
+ SeqEntrySetScope (sep);
+ ResolveDuplicateFeats (udp, udp->oldbsp, sap);
+ SeqEntrySetScope (NULL);
+ DeleteMarkedObjects (entityID, 0, NULL);
+ }
+ }
+ if (update) {
+ entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
+ ObjMgrSetDirtyFlag (entityID, TRUE);
+ ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+ }
+ Remove (udp->form);
+}
+
+static void UpdateAccept (GrouP g)
+
+{
+ Int2 nobmval, rmcval, sfbval;
+ UpsDataPtr udp;
+
+ udp = (UpsDataPtr) GetObjectExtra (g);
+ if (udp == NULL) return;
+ rmcval = GetValue (udp->rmc);
+ if (rmcval == 0) {
+ SafeDisable (udp->accept);
+ return;
+ }
+ sfbval = GetValue (udp->sfb);
+ if (sfbval == 0 || sfbval == 1 || udp->diffOrgs) {
+ SafeDisable (udp->keepProteinIDs);
+ } else if (sfbval == 2 || sfbval == 3) {
+ SafeEnable (udp->keepProteinIDs);
+ }
+ if (sfbval == 0) {
+ SafeDisable (udp->accept);
+ return;
+ }
+ nobmval = GetValue (udp->nobm);
+ if (sfbval == 2 || sfbval == 3) {
+ if (nobmval == 0) {
+ SafeDisable (udp->accept);
+ return;
+ }
+ }
+ SafeEnable (udp->accept);
+}
+
+static void DrawAlignBlock (
+ SegmenT pict,
+ Int4 top,
+ Int4 bottom,
+ Int4 labelpt,
+ Int2 labelaln,
+ Int4 len5,
+ Int4 lena,
+ Int4 len3,
+ Int4 aln_length
+)
+
+{
+ Char str [96];
+
+ if (len5 > 0) {
+ AddRectangle (pict, -len5, top, 0, bottom, NO_ARROW, FALSE, 0);
+ }
+ sprintf (str, "%ld", (long) len5);
+ AddLabel (pict, -len5, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
+
+ if (len3 > 0) {
+ AddRectangle (pict, aln_length, top, aln_length + len3, bottom, NO_ARROW, FALSE, 0);
+ }
+ sprintf (str, "%ld", (long) len3);
+ AddLabel (pict, aln_length + len3, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
+
+ AddRectangle (pict, 0, top, aln_length, bottom, NO_ARROW, TRUE, 0);
+ sprintf (str, "%ld", (long) lena);
+ AddLabel (pict, aln_length / 2, labelpt, str, SMALL_TEXT, 5, labelaln, 0);
+}
+
+static SegmenT MakeAlignPicture (
+ UpsDataPtr udp,
+ CharPtr strid1,
+ CharPtr strid2,
+ SeqAlignPtr sap
+)
+
+{
+ SegmenT pict;
+ Char str [96];
+ Int4 top, bottom;
+
+ pict = CreatePicture ();
+ if (sap == NULL) return pict;
+
+ top = 0;
+ bottom = top - 10;
+
+ DrawAlignBlock (pict, top, bottom, bottom, LOWER_CENTER, udp->old5, udp->olda, udp->old3, udp->aln_length);
+
+ /*
+ AddLabel (pict, (udp->stopmax - udp->startmax) / 2, bottom - 20, strid1, SMALL_TEXT, 5, LOWER_CENTER, 0);
+ */
+
+
+ sprintf (str, "%ld", (long) udp->aln_length);
+ AddLabel (pict, udp->aln_length / 2, 10, str, SMALL_TEXT, 5, MIDDLE_CENTER, 0);
+
+
+ top = 30;
+ bottom = top - 10;
+
+ DrawAlignBlock (pict, top, bottom, top, UPPER_CENTER, udp->new5, udp->newa, udp->new3, udp->aln_length);
+
+ /*
+ AddLabel (pict, (udp->stopmax - udp->startmax) / 2, top + 20, strid2, SMALL_TEXT, 5, UPPER_CENTER, 0);
+ */
+
+ return pict;
+}
+
+/*
+static void DrawAlignBits (
+ SegmenT pict,
+ Int4 top,
+ Int4 bottom,
+ Int4 row,
+ SeqAlignPtr sap
+)
+
+{
+ Int4 len, start, stop;
+ AlnMsgPtr amp;
+
+ amp = AlnMsgNew ();
+ if (amp == NULL) return;
+
+ amp->from_m = 0;
+ amp->to_m = -1;
+ amp->row_num = row;
+
+ start = 0;
+ while (AlnMgrGetNextAlnBit (sap, amp)) {
+ len = amp->to_b - amp->from_b + 1;
+ stop = start + len;
+ if (amp->gap != 0) {
+ AddLine (pict, start, (top + bottom) / 2, stop, (top + bottom) / 2, FALSE, 0);
+ } else {
+ AddRectangle (pict, start, top, stop, bottom, NO_ARROW, FALSE, 0);
+ }
+ start += len;
+ }
+
+ AlnMsgFree (amp);
+}
+*/
+
+static void DrawAlignDiffs (
+ UpsDataPtr udp,
+ SegmenT pict,
+ Int4 top,
+ Int4 bottom,
+ SeqAlignPtr sap
+)
+
+{
+ AlnMsgPtr amp1, amp2;
+ SegmenT seg;
+ Int4 start, stop, len, len1, len2, i, j, k;
+
+ if (udp->seq1 == NULL || udp->seq2 == NULL) return;
+ len1 = StringLen (udp->seq1);
+ len2 = StringLen (udp->seq2);
+
+ amp1 = AlnMsgNew ();
+ amp2 = AlnMsgNew ();
+ if (amp1 == NULL || amp2 == NULL) return;
+
+ seg = CreateSegment (pict, 0, 0);
+ AddAttribute (seg, COLOR_ATT, RED_COLOR, 0, 0, 0, 0);
+
+ amp1->from_m = 0;
+ amp1->to_m = -1;
+ amp1->row_num = 1;
+
+ amp2->from_m = 0;
+ amp2->to_m = -1;
+ amp2->row_num = 2;
+
+ start = 0;
+ stop = 0;
+
+ while (AlnMgrGetNextAlnBit (sap, amp1) && AlnMgrGetNextAlnBit (sap, amp2)) {
+ len = amp1->to_b - amp1->from_b + 1;
+ if (len == amp2->to_b - amp2->from_b + 1) {
+ stop = start + len;
+ if (amp1->gap == 0 && amp2->gap == 0) {
+ for (i = start, j = amp1->from_b, k = amp2->from_b;
+ i < stop && j <= len1 && k <= len2; i++, j++, k++) {
+ if (udp->seq1 [j] != udp->seq2 [k]) {
+
+ /* record for accurate scrolling to text view */
+ ValNodeAddInt (&(udp->mismatches), 0, i);
+
+ AddLine (seg, i, top, i, bottom, FALSE, 0);
+ }
+ }
+ }
+ }
+ start += len;
+ }
+
+ AlnMsgFree (amp1);
+ AlnMsgFree (amp2);
+}
+
+static void DrawAlignBits (
+ UpsDataPtr udp,
+ SegmenT pict,
+ Int4 top,
+ Int4 bottom,
+ Int4 row,
+ Int4 pos1,
+ Int4 pos2,
+ SeqAlignPtr sap
+)
+
+{
+ AlnMsgPtr amp;
+ Int4 len, start, stop, from, to;
+ Char str [96];
+ Boolean wasgap;
+
+ amp = AlnMsgNew ();
+ if (amp == NULL) return;
+
+ amp->from_m = 0;
+ amp->to_m = -1;
+ amp->row_num = row;
+
+ start = 0;
+ stop = 0;
+ from = 0;
+ to = 0;
+ wasgap = FALSE;
+
+ while (AlnMgrGetNextAlnBit (sap, amp)) {
+ len = amp->to_b - amp->from_b + 1;
+ stop = start + len;
+ if (amp->gap != 0) {
+ if (wasgap) {
+ to = stop;
+ } else {
+ AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
+ wasgap = TRUE;
+ from = start;
+ to = stop;
+ }
+ } else {
+ if (wasgap) {
+
+ /* record for accurate scrolling to text view */
+ ValNodeAddInt (&(udp->indels), 0, from);
+
+ AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
+ wasgap = FALSE;
+ from = start;
+ to = stop;
+ } else {
+ to = stop;
+ }
+ }
+ start += len;
+ }
+
+ if (to > from) {
+ if (wasgap) {
+
+ /* record for accurate scrolling to text view */
+ ValNodeAddInt (&(udp->indels), 0, from);
+
+ AddLine (pict, from, (top + bottom) / 2, to, (top + bottom) / 2, FALSE, 0);
+ } else {
+ AddRectangle (pict, from, top, to, bottom, NO_ARROW, FALSE, 0);
+ }
+ }
+
+ AlnMsgFree (amp);
+
+ sprintf (str, "%ld", (long) pos1);
+ AddLabel (pict, 0, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_LEFT, 0);
+
+ sprintf (str, "%ld", (long) pos2);
+ AddLabel (pict, to, (top + bottom) / 2, str, SMALL_TEXT, 5, MIDDLE_RIGHT, 0);
+}
+
+static SegmenT MakeAlignDetails (
+ UpsDataPtr udp,
+ CharPtr strid1,
+ CharPtr strid2,
+ SeqAlignPtr sap
+)
+
+{
+ Int4 aln_length;
+ SegmenT pict;
+ Int4 top, bottom;
+
+ pict = CreatePicture ();
+ if (sap == NULL) return pict;
+
+ aln_length = udp->aln_length;
+
+ top = 0;
+ bottom = top - 10;
+
+ DrawAlignBits (udp, pict, top, bottom, 1, udp->old5 + 1, udp->old5 + udp->olda, sap);
+
+ /*
+ AddLabel (pict, aln_length / 2, bottom, strid1, SMALL_TEXT, 5, LOWER_CENTER, 0);
+ */
+
+ top = 30;
+ bottom = top - 10;
+
+ if (udp->revcomp) {
+ DrawAlignBits (udp, pict, top, bottom, 2, udp->new3 + udp->newa, udp->new3 + 1, sap);
+ } else {
+ DrawAlignBits (udp, pict, top, bottom, 2, udp->new5 + 1, udp->new5 + udp->newa, sap);
+ }
+
+ /*
+ AddLabel (pict, aln_length / 2, top, strid2, SMALL_TEXT, 5, UPPER_CENTER, 0);
+ */
+
+ top = 15;
+ bottom = top - 10;
+
+ DrawAlignDiffs (udp, pict, top, bottom, sap);
+
+ return pict;
+}
+
+static CharPtr MakeAlignSequence (
+ UpsDataPtr udp,
+ SeqAlignPtr sap,
+ Int4 row,
+ CharPtr seq
+)
+
+{
+ CharPtr aln;
+ AlnMsgPtr amp;
+ Int4 aln_length, len, lens, start, stop, from, to, i, j;
+
+ if (udp == NULL || sap == NULL || seq == NULL) return NULL;
+ lens = StringLen (seq);
+
+ aln = (CharPtr) MemNew (sizeof (Char) * (udp->aln_length + 2));
+ if (aln == NULL) return NULL;
+ aln_length = udp->aln_length;
+ MemSet ((Pointer) aln, '-', aln_length);
+
+ amp = AlnMsgNew ();
+ if (amp == NULL) return aln;
+
+ amp->from_m = 0;
+ amp->to_m = -1;
+ amp->row_num = row;
+
+ start = 0;
+ stop = 0;
+ from = 0;
+ to = 0;
+
+ while (AlnMgrGetNextAlnBit (sap, amp)) {
+ len = amp->to_b - amp->from_b + 1;
+ stop = start + len;
+
+ if (amp->gap == 0) {
+ for (i = start, j = amp->from_b; i < stop && j < lens; i++, j++) {
+ aln [i] = seq [j];
+ }
+ }
+ start += len;
+ }
+
+ AlnMsgFree (amp);
+
+ return aln;
+}
+
+static void PrintTAln (ButtoN b)
+
+{
+ AsnIoPtr aip;
+ Char path [PATH_MAX];
+ UpsDataPtr udp;
+
+ udp = (UpsDataPtr) GetObjectExtra (b);
+ if (udp == NULL) return;
+ TmpNam (path);
+ aip = AsnIoOpen (path, "w");
+ if (aip != NULL) {
+ SeqAlignAsnWrite (udp->salp, aip, NULL);
+ AsnIoClose (aip);
+ LaunchGeneralTextViewer (path, "Update Sequence Alignment");
+ }
+ FileRemove (path);
+}
+
+static void PrintGAln (ButtoN b)
+
+{
+ UpsDataPtr udp;
+
+ udp = (UpsDataPtr) GetObjectExtra (b);
+ if (udp == NULL) return;
+ PrintViewer (udp->overview);
+ PrintViewer (udp->details);
+}
+
+static void CalculateOverhangs (
+ UpsDataPtr udp
+)
+
+{
+ Int4 aln_length;
+ Uint2 entityID;
+ SeqAlignPtr sap;
+ SeqEntryPtr sep;
+ Int4 stopold, startold, lenold, stopnew, startnew, lennew;
+
+ if (udp == NULL) return;
+ sap = udp->salp;
+ if (sap == NULL) return;
+ aln_length = AlnMgrGetAlnLength (sap, FALSE);
+ AlnMgrGetNthSeqRangeInSA (sap, 1, &startold, &stopold);
+ AlnMgrGetNthSeqRangeInSA (sap, 2, &startnew, &stopnew);
+ lenold = udp->oldbsp->length;
+ lennew = udp->newbsp->length;
+
+ udp->old5 = startold;
+ udp->old3 = lenold - stopold - 1;
+ udp->olda = stopold - startold + 1;
+
+ udp->new5 = startnew;
+ udp->new3 = lennew - stopnew - 1;
+ udp->newa = stopnew - startnew + 1;
+
+ udp->aln_length = aln_length;
+ udp->startmax = MAX (startold, startnew);
+ udp->stopmax = MAX (aln_length + lenold - stopold, aln_length + lennew - stopnew);
+
+ udp->strandold = AlnMgrGetNthStrand (sap, 1);
+ udp->strandnew = AlnMgrGetNthStrand (sap, 2);
+
+ entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
+ sep = GetTopSeqEntryForEntityID (entityID);
+ SeqEntrySetScope (sep);
+ udp->seq1 = GetSequenceByBsp (udp->oldbsp);
+ SeqEntrySetScope (NULL);
+
+ entityID = ObjMgrGetEntityIDForPointer (udp->oldbsp);
+ sep = GetTopSeqEntryForEntityID (entityID);
+ SeqEntrySetScope (sep);
+ udp->seq2 = GetSequenceByBsp (udp->newbsp);
+ SeqEntrySetScope (NULL);
+
+ udp->aln1 = MakeAlignSequence (udp, sap, 1, udp->seq1);
+ udp->aln2 = MakeAlignSequence (udp, sap, 2, udp->seq2);
+
+ udp->log10_aln_length = 1;
+ while (aln_length >= 10) {
+ aln_length /= 10;
+ (udp->log10_aln_length)++;
+ }
+}
+
+static Int4 CalculateBestScale (
+ UpsDataPtr udp,
+ VieweR vwr,
+ SegmenT pict
+)
+
+{
+ BoxInfo box;
+ Int2 i;
+ Int4 max, worldwid, portwid;
+ RecT r;
+ Int4 scaleX, oldscaleX;
+ Int4 wid;
+
+ ObjectRect (vwr, &r);
+ InsetRect (&r, 4, 4);
+ wid = (Int4) (r.right - r.left + 1);
+
+ SegmentBox (pict, &box);
+ oldscaleX = (box.right - box.left + wid - 1) / wid;
+ RecalculateSegment (pict, oldscaleX, 1);
+ SegmentBox (pict, &box);
+ portwid = wid * oldscaleX;
+ worldwid = box.right - box.left + 20 * oldscaleX + 1;
+ max = MAX (worldwid, portwid);
+ scaleX = (max + wid - 1) / wid;
+ i = 0;
+ while (i < 10 && (scaleX > oldscaleX || portwid < worldwid)) {
+ oldscaleX = scaleX;
+ RecalculateSegment (pict, oldscaleX, 1);
+ SegmentBox (pict, &box);
+ portwid = wid * oldscaleX;
+ worldwid = box.right - box.left + 20 * oldscaleX + 1;
+ max = MAX (worldwid, portwid);
+ scaleX = (max + wid - 1) / wid;
+ i++;
+ }
+
+ return scaleX;
+}
+
+/*
+static Uint1 leftTriFillSym [] = {
+ 0x06, 0x1E, 0x7E, 0xFE, 0x7E, 0x1E, 0x06, 0x00
+};
+static Uint1 rightTriFillSym [] = {
+ 0xC0, 0xF0, 0xFC, 0xFE, 0xFC, 0xF0, 0xC0, 0x00
+};
+*/
+static Uint1 leftTriFillSym [] = {
+ 0x0C, 0x3C, 0xFC, 0x3C, 0x0C, 0x00, 0x00, 0x00
+};
+static Uint1 rightTriFillSym [] = {
+ 0xC0, 0xF0, 0xFC, 0xF0, 0xC0, 0x00, 0x00, 0x00
+};
+
+static void LetDraw (
+ PaneL pnl
+)
+
+{
+ Char ch1, ch2;
+ Int2 i, k, q, left, top, bottom, arrowwidth;
+ size_t len;
+ Int4 offset, j, pos, realpos;
+ RecT r, x;
+ BaR sb;
+ Char str [32];
+ UpsDataPtr udp;
+
+ udp = (UpsDataPtr) GetObjectExtra (pnl);
+ if (udp == NULL) return;
+
+ ObjectRect (pnl, &r);
+ InsetRect (&r, 4, 4);
+
+ sb = GetSlateHScrollBar ((SlatE) pnl);
+ offset = GetBarValue (sb);
+
+ SelectFont (SetSmallFont ());
+
+ /* draw top (new) letters */
+
+ MoveTo (r.left, r.top + 8 + 3 * udp->lineheight);
+ for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
+ PaintChar (udp->aln2 [j]);
+ }
+
+ /* draw bottom (old) letters */
+
+ MoveTo (r.left, r.top + 8 + 5 * udp->lineheight);
+ for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
+ PaintChar (udp->aln1 [j]);
+ }
+
+ /* draw recombination arrows */
+
+ arrowwidth = MIN (6, udp->charwidth);
+ if (udp->recomb1 >= offset && udp->recomb1 <= offset + udp->maxchars) {
+ left = r.left + udp->charwidth * (udp->recomb1 - offset);
+ LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
+ CopyBits (&x, leftTriFillSym);
+ }
+
+ if (udp->recomb2 >= offset && udp->recomb2 <= offset + udp->maxchars) {
+ left = r.left + udp->charwidth * (udp->recomb2 - offset - 1);
+ LoadRect (&x, left, r.top, left + arrowwidth, r.top + 6);
+ CopyBits (&x, rightTriFillSym);
+ }
+
+ /* draw red mismatch lines */
+
+ Red ();
+ top = r.top + 8 + 4 * udp->lineheight - Ascent ();
+ bottom = top + udp->lineheight - 2;
+
+ for (i = 0, j = offset; i < udp->maxchars && j < udp->aln_length; i++, j++) {
+ ch1 = udp->aln1 [j];
+ ch2 = udp->aln2 [j];
+ if (ch1 == ch2) {
+ } else if (ch1 == '-' || ch2 == '-') {
+ } else {
+ left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
+ MoveTo (left, top);
+ LineTo (left, bottom);
+ }
+ }
+ Black ();
+
+ /* draw top (new) tick marks and coordinates */
+
+ bottom = r.top + 8 + 3 * udp->lineheight - Ascent () - 2;
+ top = bottom - 5;
+ i = 0;
+ j = offset;
+ pos = AlnMgrMapRowCoords (udp->salp, j, 2, NULL);
+ while (pos < 1 && i < udp->maxchars && j < udp->aln_length) {
+ i++;
+ j++;
+ pos = AlnMgrMapRowCoords (udp->salp, j, 2, NULL);
+ }
+ for (; i < udp->maxchars + udp->log10_aln_length && j < udp->aln_length; i++, j++) {
+ ch1 = udp->aln2 [j];
+ if (ch1 != '-') {
+ if (udp->revcomp) {
+ realpos = (udp->newbsp->length - pos - 1);
+ } else {
+ realpos = pos;
+ }
+ if (((realpos + 1) % 10) == 0) {
+ left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
+ if (i < udp->maxchars) {
+ MoveTo (left, top);
+ LineTo (left, bottom);
+ }
+ sprintf (str, "%ld", (long) (realpos + 1));
+ len = StringLen (str);
+ if (len <= j + 1) {
+ k = i - len + 1;
+ q = 0;
+ if (k < 0) {
+ q -= k;
+ k = 0;
+ }
+ if (q < len) {
+ left = r.left + k * udp->charwidth;
+ MoveTo (left, r.top + 8 + udp->lineheight);
+ while (k < udp->maxchars && q < len) {
+ PaintChar (str [q]);
+ k++;
+ q++;
+ }
+ }
+ }
+ } else if (((realpos + 1) % 5) == 0) {
+ left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
+ if (i < udp->maxchars) {
+ MoveTo (left, top + 3);
+ LineTo (left, bottom);
+ }
+ }
+ pos++;
+ }
+ }
+
+ /* draw bottom (old) tick marks and coordinates */
+
+ top = r.top + 8 + 6 * udp->lineheight - Ascent () + 2;
+ bottom = top + 5;
+ i = 0;
+ j = offset;
+ pos = AlnMgrMapRowCoords (udp->salp, j, 1, NULL);
+ while (pos < 1 && i < udp->maxchars && j < udp->aln_length) {
+ i++;
+ j++;
+ pos = AlnMgrMapRowCoords (udp->salp, j, 1, NULL);
+ }
+ for (; i < udp->maxchars + udp->log10_aln_length && j < udp->aln_length; i++, j++) {
+ ch1 = udp->aln1 [j];
+ if (ch1 != '-') {
+ if (((pos + 1) % 10) == 0) {
+ left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
+ if (i < udp->maxchars) {
+ MoveTo (left, top);
+ LineTo (left, bottom);
+ }
+ sprintf (str, "%ld", (long) (pos + 1));
+ len = StringLen (str);
+ if (len <= j + 1) {
+ k = i - len + 1;
+ q = 0;
+ if (k < 0) {
+ q -= k;
+ k = 0;
+ }
+ if (q < len) {
+ left = r.left + k * udp->charwidth;
+ MoveTo (left, r.top + 8 + 7 * udp->lineheight);
+ while (k < udp->maxchars && q < len) {
+ PaintChar (str [q]);
+ k++;
+ q++;
+ }
+ }
+ }
+ } else if (((pos + 1) % 5) == 0) {
+ left = r.left + i * udp->charwidth + udp->charwidth / 2 - 1;
+ if (i < udp->maxchars) {
+ MoveTo (left, top);
+ LineTo (left, bottom - 3);
+ }
+ }
+ pos++;
+ }
+ }
+
+ SelectFont (systemFont);
+}
+
+static void LetScrl (
+ BaR sb,
+ SlatE slt,
+ Int4 newval,
+ Int4 oldval
+)
+
+{
+ RecT r;
+ UpsDataPtr udp;
+
+ udp = (UpsDataPtr) GetObjectExtra (slt);
+ if (udp == NULL) return;
+
+ ObjectRect (udp->letters, &r);
+ InsetRect (&r, 4, 4);
+ Select (udp->letters);
+ if (ABS (oldval - newval) < udp->maxchars) {
+ ScrollRect (&r, (oldval - newval) * udp->charwidth, 0);
+ } else {
+ InsetRect (&r, -2, -2);
+ InvalRect (&r);
+ }
+ Update ();
+}
+
+static void DtlClck (
+ VieweR vwr,
+ SegmenT pict,
+ PoinT pt
+)
+
+{
+ Int4 goHere;
+ Int4 offset;
+ Int4 maxover2;
+ PntInfo pnt;
+ BaR sb;
+ UpsDataPtr udp;
+ ValNodePtr vnp;
+
+ udp = (UpsDataPtr) GetViewerData (vwr);
+ if (udp == NULL) return;
+
+ sb = GetSlateHScrollBar ((SlatE) udp->letters);
+
+ MapViewerToWorld (vwr, pt, &pnt);
+ maxover2 = udp->maxchars / 2;
+ if (pnt.x <= 0) {
+ pnt.x = 0;
+ } else if (pnt.x >= udp->aln_length) {
+ pnt.x = udp->aln_length - udp->maxchars;
+ } else if (pnt.x >= maxover2) {
+
+ offset = GetBarValue (sb);
+
+ /* look for clicks within 5 pixels of an indel start or a mismatch */
+
+ goHere = -1;
+ for (vnp = udp->indels; vnp != NULL && goHere < 0; vnp = vnp->next) {
+ if (ABS (pnt.x - vnp->data.intvalue) < udp->scaleX * 5) {
+ goHere = vnp->data.intvalue;
+ }
+ }
+ for (vnp = udp->mismatches; vnp != NULL && goHere < 0; vnp = vnp->next) {
+ if (ABS (pnt.x - vnp->data.intvalue) < udp->scaleX * 5) {
+ goHere = vnp->data.intvalue;
+ }
+ }
+
+ if (goHere >= 0) {
+ pnt.x = goHere;
+ } else {
+ /* if already visible, no need to scroll */
+ if (pnt.x - maxover2 > offset && pnt.x - maxover2 < offset + maxover2 - 5) return;
+ if (pnt.x - maxover2 < offset && pnt.x - maxover2 > offset - maxover2 + 5) return;
+ }
+
+ /* go left 1/2 screen so desired point is in the middle */
+
+ pnt.x -= maxover2;
+ }
+
+ ResetClip ();
+ SetBarValue (sb, pnt.x);
+ Update ();
+}
+
+static void FrameVwr (
+ VieweR vwr,
+ SegmenT pict
+)
+
+{
+ RecT r;
+
+ ResetClip ();
+ ObjectRect (vwr, &r);
+ FrameRect (&r);
+}
+
+static int LIBCALLBACK SortVnpByInt (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+ ValNodePtr vnp1;
+ ValNodePtr vnp2;
+
+ if (ptr1 == NULL || ptr2 == NULL) return 0;
+ vnp1 = *((ValNodePtr PNTR) ptr1);
+ vnp2 = *((ValNodePtr PNTR) ptr2);
+ if (vnp1 == NULL || vnp2 == NULL) return 0;
+
+ if (vnp1->data.intvalue > vnp2->data.intvalue) {
+ return 1;
+ } else if (vnp1->data.intvalue < vnp2->data.intvalue) {
+ return -1;
+ }
+
+ return 0;
+}
+
+extern void QuitProc (void);
+
+static void UpdateSequenceFormMessage (ForM f, Int2 mssg)
+
+{
+ BaseFormPtr bfp;
+ StdEditorProcsPtr sepp;
+
+ bfp = (BaseFormPtr) GetObjectExtra (f);
+ if (bfp == NULL) return;
+ switch (mssg) {
+ case VIB_MSG_CLOSE :
+ Remove (f);
+ break;
+ case VIB_MSG_QUIT :
+ QuitProc ();
+ break;
+ default :
+ sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
+ if (sepp != NULL && sepp->handleMessages != NULL) {
+ sepp->handleMessages (f, mssg);
+ }
+ break;
+ }
+}
+
+static void CleanupUpdateSequenceForm (GraphiC g, VoidPtr data)
+
+{
+ Uint2 entityID;
+ UpsDataPtr udp;
+
+ udp = (UpsDataPtr) data;
+ if (udp != NULL) {
+ udp->ovpict = DeletePicture (udp->ovpict);
+ udp->dtpict = DeletePicture (udp->dtpict);
+ udp->salp = SeqAlignFree (udp->salp);
+ entityID = ObjMgrGetEntityIDForPointer (udp->newbsp);
+ udp->newbsp = ObjMgrFreeByEntityID (entityID);
+ udp->seq1 = MemFree (udp->seq1);
+ udp->seq2 = MemFree (udp->seq2);
+ udp->aln1 = MemFree (udp->aln1);
+ udp->aln2 = MemFree (udp->aln2);
+ udp->indels = ValNodeFree (udp->indels);
+ udp->mismatches = ValNodeFree (udp->mismatches);
+ }
+ StdCleanupFormProc (g, data);
+}
+
+#ifdef WIN_MAC
+extern void UpdateSequenceFormActivated (WindoW w);
+
+static void UpdateSequenceFormActivate (WindoW w)
+
+{
+ BaseFormPtr bfp;
+
+ bfp = (BaseFormPtr) GetObjectExtra (w);
+ if (bfp != NULL) {
+ if (bfp->activate != NULL) {
+ bfp->activate (w);
+ }
+ }
+}
+#endif
+
+static CharPtr txt1 =
+ "Sequence Relationship displays sequence lengths";
+
+static CharPtr txt2 =
+ "Alignment Details displays sequence positions";
+
+static CharPtr txt3 =
+ "Click above to scroll Alignment Text position";
+
+static CharPtr txt4 =
+ "Alignment Text displays sequence letters";
+
+static ForM UpdateSequenceForm (
+ BioseqPtr oldbsp,
+ BioseqPtr newbsp,
+ SeqAlignPtr salp,
+ Boolean revcomp
+)
+
+{
+ ButtoN b2, b3, b4;
+ BioSourcePtr biop1, biop2;
+ GrouP c, g, y, z = NULL;
+ SeqMgrDescContext dcontext;
+ Uint2 entityID, hgt;
+ SeqMgrFeatContext fcontext;
+ GrouP gp1, gp2, gp3, ppt0, ppt1, ppt2, ppt3, ppt4 = NULL;
+ OrgRefPtr orp1, orp2;
+ RecT r;
+ BaR sb;
+ Int4 scaleX;
+ SeqDescrPtr sdp;
+ SeqFeatPtr sfp;
+ Boolean sidebyside = FALSE;
+ SeqIdPtr sip;
+ Char strid1 [41], strid2 [41], txt0 [256];
+ UpsDataPtr udp;
+ WindoW w;
+
+ if (oldbsp == NULL || newbsp == NULL) return NULL;
+ udp = (UpsDataPtr) MemNew (sizeof (UpsData));
+ if (udp == NULL) return NULL;
+ w = FixedWindow (-50, -33, -10, -10, "Update Sequence", NULL);
+ if (w == NULL) return NULL;
+
+#ifdef WIN_MSWIN
+ if (screenRect.bottom - screenRect.top < 750) {
+ sidebyside = TRUE;
+ }
+#endif
+
+ sip = SeqIdFindWorst (oldbsp->id);
+ SeqIdWrite (sip, strid1, PRINTID_REPORT, sizeof (strid1) - 1);
+ sip = SeqIdFindWorst (newbsp->id);
+ SeqIdWrite (sip, strid2, PRINTID_REPORT, sizeof (strid2) - 1);
+ if (StringICmp (strid2, "SequinUpdateSequence") == 0 && newbsp->id->next != NULL) {
+ sip = SeqIdFindWorst (newbsp->id->next);
+ SeqIdWrite (sip, strid2, PRINTID_REPORT, sizeof (strid2) - 1);
+ }
+
+ SetObjectExtra (w, (Pointer) udp, CleanupUpdateSequenceForm);
+ udp->form = (ForM) w;
+ udp->formmessage = UpdateSequenceFormMessage;
+
+#ifdef WIN_MAC
+ udp->activate = UpdateSequenceFormActivated;
+ SetActivate (w, UpdateSequenceFormActivate);
+#endif
+
+ udp->oldbsp = oldbsp;
+ udp->newbsp = newbsp;
+ udp->salp = salp;
+ udp->revcomp = revcomp;
+ udp->diffOrgs = FALSE;
+
+ CalculateOverhangs (udp);
+
+ sprintf (txt0, "New sequence: %s - Length: %ld\nOld Sequence: %s - Length: %ld",
+ strid2, (long) newbsp->length, strid1, (long) oldbsp->length);
+ ppt0 = MultiLinePrompt (w, txt0, 350, programFont);
+
+ if (sidebyside) {
+ y = HiddenGroup (w, 0, -5, NULL);
+ } else {
+ y = HiddenGroup (w, -1, 0, NULL);
+ }
+
+ ppt1 = MultiLinePrompt (y, txt1, 350, programFont);
+ udp->overview = CreateViewer (y, 350 + Nlm_vScrollBarWidth, 100, FALSE, FALSE);
+
+ ppt2 = MultiLinePrompt (y, txt2, 350, programFont);
+ udp->details = CreateViewer (y, 350 + Nlm_vScrollBarWidth, 80, FALSE, FALSE);
+
+ ppt3 = MultiLinePrompt (y, txt3, 350, programFont);
+
+ if (sidebyside) {
+ ppt4 = MultiLinePrompt (y, txt4, 350, programFont);
+ }
+
+#ifdef WIN_MAC
+ hgt = 90;
+#else
+ hgt = 110;
+#endif
+ udp->letters = AutonomousPanel4 (y, 350 + Nlm_vScrollBarWidth, hgt, LetDraw,
+ NULL, LetScrl, 0, NULL, NULL);
+ SetObjectExtra (udp->letters, (Pointer) udp, NULL);
+
+#ifdef WIN_MAC
+ if (indexerVersion && shftKey) {
+ ButtoN b;
+ z = HiddenGroup (y, 2, 0, NULL);
+ SetGroupSpacing (z, 10, 3);
+ b = PushButton (z, "Print Graphic", PrintGAln);
+ SetObjectExtra (b, (Pointer) udp, NULL);
+ b = PushButton (z, "Display Alignment", PrintTAln);
+ SetObjectExtra (b, (Pointer) udp, NULL);
+ }
+#endif
+
+ udp->ovpict = NULL;
+ udp->dtpict = NULL;
+
+ g = HiddenGroup (y, -1, 0, NULL);
+ SetGroupSpacing (g, 5, 5);
+
+ gp1 = NormalGroup (g, 4, 0, "Alignment Relationship", programFont, NULL);
+ udp->rmc = HiddenGroup (gp1, 4, 0, UpdateAccept);
+ SetObjectExtra (udp->rmc, (Pointer) udp, NULL);
+ SetGroupSpacing (udp->rmc, 10, 5);
+ RadioButton (udp->rmc, "Replace");
+ b2 = RadioButton (udp->rmc, "Extend 5'");
+ b3 = RadioButton (udp->rmc, "Extend 3'");
+ b4 = RadioButton (udp->rmc, "Patch");
+
+ gp2 = NormalGroup (g, 4, 0, "Update Operation", programFont, NULL);
+ udp->sfb = HiddenGroup (gp2, 4, 0, UpdateAccept);
+ SetObjectExtra (udp->sfb, (Pointer) udp, NULL);
+ SetGroupSpacing (udp->sfb, 10, 5);
+ RadioButton (udp->sfb, "Sequence");
+ RadioButton (udp->sfb, "Features");
+ RadioButton (udp->sfb, "Sequence + Features");
+
+ udp->keepProteinIDs = CheckBox (g, "Keep Protein IDs", NULL);
+
+ gp3 = NormalGroup (g, 4, 0, "Duplicate Feature Policy", programFont, NULL);
+ udp->nobm = HiddenGroup (gp3, 4, 0, UpdateAccept);
+ SetObjectExtra (udp->nobm, (Pointer) udp, NULL);
+ SetGroupSpacing (udp->nobm, 10, 5);
+ RadioButton (udp->nobm, "New");
+ RadioButton (udp->nobm, "Old");
+ RadioButton (udp->nobm, "Both");
+ RadioButton (udp->nobm, "Merge");
+
+ AlignObjects (ALIGN_CENTER, (HANDLE) gp1, (HANDLE) gp2, (HANDLE) gp3,
+ (HANDLE) udp->keepProteinIDs, NULL);
+
+
+ c = HiddenGroup (w, 4, 0, NULL);
+ udp->accept = PushButton (c, "Accept", AcceptRMC);
+ SetObjectExtra (udp->accept, (Pointer) udp, NULL);
+ PushButton (c, "Cancel", StdCancelButtonProc);
+
+ if (sidebyside) {
+ AlignObjects (ALIGN_CENTER, (HANDLE) udp->overview, (HANDLE) udp->details,
+ (HANDLE) ppt1, (HANDLE) ppt2, (HANDLE) ppt3, NULL);
+ AlignObjects (ALIGN_CENTER, (HANDLE) udp->letters, (HANDLE) ppt4,
+ (HANDLE) g, (HANDLE) z, NULL);
+ AlignObjects (ALIGN_CENTER, (HANDLE) ppt0, (HANDLE) y, (HANDLE) c, NULL);
+ } else {
+ AlignObjects (ALIGN_CENTER, (HANDLE) udp->overview, (HANDLE) udp->details,
+ (HANDLE) udp->letters, (HANDLE) ppt0, (HANDLE) ppt1, (HANDLE) ppt2,
+ (HANDLE) ppt3, (HANDLE) g, (HANDLE) c, (HANDLE) z, NULL);
+ }
+ RealizeWindow (w);
+
+ udp->ovpict = MakeAlignPicture (udp, strid1, strid2, salp);
+ scaleX = CalculateBestScale (udp, udp->overview, udp->ovpict);
+ AttachPicture (udp->overview, udp->ovpict, 0, 0, UPPER_LEFT, scaleX, 1, FrameVwr);
+
+ udp->dtpict = MakeAlignDetails (udp, strid1, strid2, salp);
+ scaleX = CalculateBestScale (udp, udp->details, udp->dtpict);
+ udp->scaleX = scaleX;
+ AttachPicture (udp->details, udp->dtpict, 0, 0, UPPER_LEFT, scaleX, 1, FrameVwr);
+ SetViewerData (udp->details, (Pointer) udp, NULL);
+ SetViewerProcs (udp->details, DtlClck, NULL, NULL, NULL);
+
+ udp->indels = ValNodeSort (udp->indels, SortVnpByInt);
+ udp->mismatches = ValNodeSort (udp->mismatches, SortVnpByInt);
+
+ SelectFont (SetSmallFont ());
+ ObjectRect (udp->letters, &r);
+ InsetRect (&r, 4, 4);
+ udp->lineheight = LineHeight ();
+ udp->charwidth = MaxCharWidth ();
+ udp->maxchars = (r.right - r.left - 2 + udp->charwidth - 1) / udp->charwidth;
+ SelectFont (systemFont);
+
+ sb = GetSlateHScrollBar ((SlatE) udp->letters);
+ SetBarMax (sb, udp->aln_length - (Int4) udp->maxchars);
+ CorrectBarPage (sb, (Int4) udp->maxchars - 1, (Int4) udp->maxchars - 1);
+
+ udp->recomb1 = -1;
+ udp->recomb2 = -1;
+
+ if (udp->new5 > udp->old5 && udp->new3 < udp->old3) {
+ /* extend 5' */
+ SetValue (udp->rmc, 2);
+ /*
+ Disable (udp->rmc);
+ */
+ Disable (b3);
+ Disable (b4);
+ udp->recomb2 = udp->aln_length;
+ } else if (udp->new5 < udp->old5 && udp->new3 > udp->old3) {
+ /* extend 3' */
+ SetValue (udp->rmc, 3);
+ /*
+ Disable (udp->rmc);
+ */
+ Disable (b2);
+ Disable (b4);
+ udp->recomb1 = 0;
+ } else if (udp->new5 >= udp->old5 && udp->new3 >= udp->old3) {
+ /* replace */
+ SetValue (udp->rmc, 1);
+ Disable (udp->rmc);
+ udp->recomb1 = 0;
+ udp->recomb2 = udp->aln_length;
+ } else if (udp->new5 <= udp->old5 && udp->new3 <= udp->old3) {
+ /* patch */
+ SetValue (udp->rmc, 4);
+ /*
+ Disable (udp->rmc);
+ */
+ Disable (b2);
+ Disable (b3);
+ udp->recomb1 = 0;
+ udp->recomb2 = udp->aln_length;
+ /* if patch sequence matches, must be feature propagation only */
+ if (StringNICmp (udp->seq1 + udp->old5 - udp->new5, udp->seq2, StringLen (udp->seq2)) == 0) {
+ SetValue (udp->sfb, 2);
+ Disable (udp->sfb);
+ }
+ }
+
+ /* if no features, must be sequence update only */
+
+ entityID = ObjMgrGetEntityIDForPointer (newbsp);
+ if (! SeqMgrFeaturesAreIndexed (entityID)) {
+ SeqMgrIndexFeatures (entityID, NULL);
+ }
+ sfp = SeqMgrGetNextFeature (newbsp, NULL, 0, 0, &fcontext);
+ if (sfp == NULL) {
+ SetValue (udp->sfb, 1);
+ Disable (udp->sfb);
+ Disable (udp->nobm);
+ }
+
+ /* if different organisms, must be feature propagation only */
+
+ orp1 = NULL;
+ orp2 = NULL;
+ sdp = SeqMgrGetNextDescriptor (oldbsp, NULL, Seq_descr_source, &dcontext);
+ if (sdp != NULL) {
+ biop1 = (BioSourcePtr) sdp->data.ptrvalue;
+ if (biop1 != NULL) {
+ orp1 = biop1->org;
+ }
+ }
+ sdp = SeqMgrGetNextDescriptor (newbsp, NULL, Seq_descr_source, &dcontext);
+ if (sdp != NULL) {
+ biop2 = (BioSourcePtr) sdp->data.ptrvalue;
+ if (biop2 != NULL) {
+ orp2 = biop2->org;
+ }
+ }
+ if (orp1 != NULL && orp2 != NULL) {
+ if (StringICmp (orp1->taxname, orp2->taxname) != 0) {
+ if (sfp != NULL) {
+ SetValue (udp->sfb, 2);
+ Disable (udp->sfb);
+ udp->diffOrgs = TRUE;
+ } else {
+ /* no features, cannot do anything */
+ SetValue (udp->sfb, 0);
+ Disable (udp->sfb);
+ Disable (udp->nobm);
+ }
+ Disable (udp->rmc);
+ }
+ }
+
+ /* disable accept button unless rmc and sfb are both preset */
+
+ UpdateAccept (udp->rmc);
+
+/*
+{
+ AsnIoPtr aip;
+ Char path [PATH_MAX];
+
+ TmpNam (path);
+ aip = AsnIoOpen (path, "w");
+ if (aip != NULL) {
+ SeqAlignAsnWrite (salp, aip, NULL);
+ AsnIoClose (aip);
+ DisplayFancy (udp->doc, path, NULL, NULL, programFont, 0);
+ }
+ FileRemove (path);
+}
+*/
+
+ return (ForM) w;
+}
+
+static void HasPubsCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+ BioseqPtr bsp;
+ BioseqSetPtr bssp;
+ BoolPtr rsult;
+ ValNodePtr sdp;
+
+ if (sep == NULL || sep->data.ptrvalue == NULL) return;
+ rsult = (BoolPtr) mydata;
+ if (IS_Bioseq (sep)) {
+ bsp = (BioseqPtr) sep->data.ptrvalue;
+ sdp = bsp->descr;
+ } else if (IS_Bioseq_set (sep)) {
+ bssp = (BioseqSetPtr) sep->data.ptrvalue;
+ sdp = bssp->descr;
+ } else return;
+ while (sdp != NULL) {
+ if (sdp->choice == Seq_descr_pub) {
+ *rsult = TRUE;
+ return;
+ }
+ sdp = sdp->next;
+ }
+}
+
+static Boolean LIBCALL SeqEntryHasPubs (SeqEntryPtr sep)
+
+{
+ Boolean rsult;
+
+ rsult = FALSE;
+ if (sep != NULL) {
+ SeqEntryExplore (sep, (Pointer) &rsult, HasPubsCallback);
+ }
+ return rsult;
+}
+
+static Boolean CheckForIDCollision (
+ BioseqPtr oldbsp,
+ BioseqPtr newbsp
+)
+
+{
+ SeqIdPtr sip;
+
+ if (oldbsp == NULL || newbsp == NULL) return FALSE;
+ for (sip = newbsp->id; sip != NULL; sip = sip->next) {
+ if (SeqIdIn (sip, oldbsp->id)) return TRUE;
+ }
+ return FALSE;
+}
+
+static CharPtr convPubDescMssg =
+"Do you wish to convert publications to apply only to the appropriate ranges?";
+
+extern void PrepareToUpdateSequences (
+ BioseqPtr oldbsp,
+ BioseqPtr newbsp
+);
+extern void PrepareToUpdateSequences (
+ BioseqPtr oldbsp,
+ BioseqPtr newbsp
+)
+
+{
+ Uint2 entityID;
+ ForM f;
+ SeqEntryPtr oldsep, newsep;
+ Boolean revcomp = FALSE;
+ SeqAlignPtr salp = NULL;
+ SeqIdPtr sip, tempid = NULL;
+
+ if (oldbsp == NULL || newbsp == NULL) return;
+ if (ISA_na (oldbsp->mol) != ISA_na (newbsp->mol)) {
+ Message (MSG_OK, "Both sequences must be either nucleotides or proteins");
+ return;
+ }
+ if (oldbsp->repr != Seq_repr_raw || newbsp->repr != Seq_repr_raw) {
+ Message (MSG_OK, "Both sequences must be raw");
+ return;
+ }
+
+ entityID = ObjMgrGetEntityIDForPointer (oldbsp);
+ oldsep = GetBestTopParentForData (entityID, oldbsp);
+ entityID = ObjMgrGetEntityIDForPointer (newbsp);
+ newsep = GetBestTopParentForData (entityID, newbsp);
+ if (oldsep == NULL || newsep == NULL) return;
+
+ if (SeqEntryHasPubs (oldsep) || SeqEntryHasPubs (newsep)) {
+ if (Message (MSG_YN, convPubDescMssg) == ANS_YES) {
+ ConvertPubSrcComDescsToFeats (oldsep, TRUE, FALSE, FALSE, FALSE);
+ ConvertPubSrcComDescsToFeats (newsep, TRUE, FALSE, FALSE, FALSE);
+ }
+ }
+
+ WatchCursor ();
+ tempid = NULL;
+ if (CheckForIDCollision (oldbsp, newbsp)) {
+ sip = SeqIdParse ("lcl|SequinUpdateSequence");
+ if (sip != NULL) {
+ /* unlink colliding id, temporarily replace */
+ tempid = newbsp->id;
+ newbsp->id = sip;
+ SeqMgrReplaceInBioseqIndex (newbsp);
+ }
+ }
+ salp = Sqn_GlobalAlignTwoSeq (oldbsp, newbsp, &revcomp);
+ if (tempid != NULL) {
+ /* add back colliding id now that blast is done */
+ sip->next = tempid;
+ SeqMgrReplaceInBioseqIndex (newbsp);
+ }
+ ArrowCursor ();
+ if (salp == NULL) {
+ Message (MSG_OK, "Unable to align the sequences");
+ return;
+ }
+
+ f = UpdateSequenceForm (oldbsp, newbsp, salp, revcomp);
+ if (f == NULL) return;
+ Show (f);
+ Select (f);
+ SendHelpScrollMessage (helpForm, "Edit Menu", "Update Sequence");
+}
+
+extern void NewUpdateSequence (
+ IteM i
+);
+extern void NewUpdateSequence (
+ IteM i
+)
+
+{
+ BaseFormPtr bfp;
+ BioseqPtr bsp, nbsp;
+ Pointer dataptr;
+ Uint2 datatype;
+ FILE *fp;
+ Char path [PATH_MAX];
+ SeqEntryPtr sep, nwsep = NULL;
+ SeqSubmitPtr ssp;
+
+#ifdef WIN_MAC
+ bfp = currentFormDataPtr;
+#else
+ bfp = GetObjectExtra (i);
+#endif
+ if (bfp == NULL) return;
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ if (sep == NULL) return;
+ bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+ if (bsp == NULL) return;
+
+ if (bsp->repr != Seq_repr_raw) {
+ Message (MSG_OK, "Only raw sequences can be updated");
+ return;
+ }
+
+ if (! GetInputFileName (path, sizeof (path),"","TEXT")) return;
+ fp = FileOpen (path, "r");
+ if (fp == NULL) return;
+ dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, NULL, FALSE, FALSE, TRUE, FALSE);
+ FileClose (fp);
+ if (dataptr == NULL) return;
+
+ if (datatype == OBJ_SEQENTRY) {
+ nwsep = (SeqEntryPtr) dataptr;
+ } else if (datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET) {
+ nwsep = SeqMgrGetSeqEntryForData (dataptr);
+ } else if (datatype == OBJ_SEQSUB) {
+ ssp = (SeqSubmitPtr) dataptr;
+ if (ssp != NULL && ssp->datatype == 1) {
+ nwsep = (SeqEntryPtr) ssp->data;
+ }
+ }
+ if (nwsep == NULL) return;
+ if (ISA_na (bsp->mol)) {
+ nbsp = FindNucBioseq (nwsep);
+ } else {
+ nwsep = FindNthBioseq (nwsep, 1);
+ if (nwsep == NULL || nwsep->choice != 1) return;
+ nbsp = (BioseqPtr) nwsep->data.ptrvalue;
+ }
+ if (nbsp == NULL) return;
+
+ PrepareToUpdateSequences (bsp, nbsp);
+}
+
+
+/* NEW FEATURE PROPAGATION SECTION */
+
+typedef struct fprdata {
+ FORM_MESSAGE_BLOCK
+ BioseqPtr bsp;
+ SeqAlignPtr salp;
+ Uint2 selFeatItemID;
+ Int4 aln_length;
+ Int4 log10_aln_length;
+ VieweR details;
+ SegmenT dtpict;
+ Int4 scaleX;
+ GrouP allOrSel;
+ GrouP gapSplit;
+ ButtoN stopCDS;
+ ButtoN transPast;
+ ButtoN accept;
+} FprData, PNTR FprDataPtr;
+
+typedef struct ivalinfo {
+ Int4 start1;
+ Int4 stop1;
+ Int4 start2;
+ Int4 stop2;
+ struct ivalinfo PNTR next;
+} IvalInfo, PNTR IvalInfoPtr;
+
+static IvalInfoPtr IvalInfoFree (
+ IvalInfoPtr ival
+)
+
+{
+ IvalInfoPtr next;
+
+ while (ival != NULL) {
+ next = ival->next;
+ MemFree (ival);
+ ival = next;
+ }
+ return NULL;
+}
+
+static IvalInfoPtr GetAlignmentIntervals (SeqAlignPtr sap, Int4 row1, Int4 row2, Int4 from, Int4 to)
+{
+ AlnMsgPtr amp1;
+ AlnMsgPtr amp2;
+ IvalInfoPtr ival;
+ IvalInfoPtr ival_head;
+ IvalInfoPtr ival_prev;
+ Int4 from_aln;
+ Int4 start;
+ Int4 stop;
+ Int4 tmp;
+ Int4 to_aln;
+
+ if (sap == NULL || sap->saip == NULL)
+ return NULL;
+ AlnMgrGetNthSeqRangeInSA(sap, row1, &start, &stop);
+ if (from < start)
+ from = start;
+ if (to > stop)
+ to = stop;
+ from_aln = AlnMgrMapBioseqToSeqAlign(sap, from, row1, NULL);
+ to_aln = AlnMgrMapBioseqToSeqAlign(sap, to, row1, NULL);
+ if (from_aln > to_aln)
+ {
+ tmp = from_aln;
+ from_aln = to_aln;
+ to_aln = tmp;
+ }
+ amp1 = AlnMsgNew();
+ amp1->from_m = from_aln;
+ amp1->to_m = to_aln;
+ amp1->row_num = row1;
+ amp2 = AlnMsgNew();
+ amp2->from_m = from_aln;
+ amp2->to_m = to_aln;
+ amp2->row_num = row2;
+ ival_head = ival_prev = NULL;
+ while (AlnMgrGetNextAlnBit(sap, amp1) && AlnMgrGetNextAlnBit(sap, amp2))
+ {
+ if (amp1->gap == 0 && amp2->gap == 0)
+ {
+ ival = (IvalInfoPtr)MemNew(sizeof(IvalInfo));
+ ival->start1 = amp1->from_b;
+ ival->stop1 = amp1->to_b;
+ ival->start2 = amp2->from_b;
+ ival->stop2 = amp2->to_b;
+ if (ival_head == NULL)
+ ival_head = ival_prev = ival;
+ else
+ {
+ ival_prev->next = ival;
+ ival_prev = ival;
+ }
+ }
+ }
+ AlnMsgFree(amp1);
+ AlnMsgFree(amp2);
+ return ival_head;
+}
+
+static IvalInfoPtr MergeAdjacentIntervals (
+ IvalInfoPtr list
+)
+
+{
+ IvalInfoPtr curr, last, next;
+
+ if (list != NULL) {
+ curr = list->next;
+ last = list;
+ while (curr != NULL) {
+ next = curr->next;
+ if (curr->start2 == last->stop2 + 1) {
+ last->stop2 = MAX (curr->stop2, last->stop2);
+ MemFree (curr);
+ last->next = next;
+ } else {
+ last = curr;
+ }
+ curr = next;
+ }
+ }
+ return list;
+}
+
+static SeqLocPtr MapLocForProp (
+ SeqAlignPtr salp,
+ Int4 begin,
+ Int4 fin,
+ SeqIdPtr sip,
+ Boolean gapSplit,
+ SeqLocPtr location
+)
+
+{
+ SeqLocPtr head = NULL;
+ IvalInfoPtr ival;
+ IvalInfoPtr ival_head;
+ SeqIntPtr sinp;
+ SeqLocPtr slp;
+ SeqPntPtr spp;
+ Uint1 strand;
+
+ slp = SeqLocFindNext (location, NULL);
+ while (slp != NULL) {
+ switch (slp->choice) {
+ case SEQLOC_INT :
+ sinp = (SeqIntPtr) slp->data.ptrvalue;
+ if (sinp != NULL) {
+ strand = sinp->strand;
+ ival_head = GetAlignmentIntervals (salp, begin, fin, sinp->from, sinp->to);
+ ival_head = MergeAdjacentIntervals (ival_head);
+ if (ival_head != NULL) {
+
+ /* what if one or the other interval maps into a gap? */
+
+ if (gapSplit) {
+ for (ival = ival_head; ival != NULL; ival = ival->next) {
+ sinp = SeqIntNew ();
+ sinp->from = ival->start2;
+ sinp->to = ival->stop2;
+ sinp->strand = strand;
+ sinp->id = SeqIdDup (sip);
+ ValNodeAddPointer (&head, SEQLOC_INT, (Pointer) sinp);
+ }
+ } else {
+ sinp = SeqIntNew ();
+ sinp->from = ival_head->start2;
+ for (ival = ival_head; ival->next != NULL; ival = ival->next) continue;
+ sinp->to = ival->stop2;
+ sinp->strand = strand;
+ sinp->id = SeqIdDup (sip);
+ ValNodeAddPointer (&head, SEQLOC_INT, (Pointer) sinp);
+ }
+
+ }
+ IvalInfoFree (ival_head);
+ }
+ break;
+ case SEQLOC_PNT :
+ spp = (SeqPntPtr) slp->data.ptrvalue;
+ if (spp != NULL) {
+ strand = spp->strand;
+ ival_head = GetAlignmentIntervals (salp, begin, fin, spp->point, spp->point);
+ if (ival_head != NULL) {
+
+ spp = SeqPntNew ();
+ spp->point = ival_head->start2;
+ spp->strand = strand;
+ spp->id = SeqIdDup (sip);
+ ValNodeAddPointer (&head, SEQLOC_PNT, (Pointer) spp);
+
+ }
+ IvalInfoFree (ival_head);
+ }
+ break;
+ case SEQLOC_PACKED_PNT :
+ /* not yet implemented */
+ break;
+ default :
+ break;
+ }
+
+ slp = SeqLocFindNext (location, slp);
+ }
+
+ if (head == NULL) return NULL;
+ if (head->next == NULL) return head;
+
+ slp = ValNodeNew (NULL);
+ slp->choice = SEQLOC_MIX;
+ slp->data.ptrvalue = (Pointer) head;
+ slp->next = NULL;
+
+ return slp;
+}
+
+static void ExtendLocToEnd (
+ SeqLocPtr location,
+ BioseqPtr bsp,
+ Uint1 strand
+)
+
+{
+ SeqIntPtr sinp;
+ SeqLocPtr slp, last = NULL;
+
+ slp = SeqLocFindNext (location, NULL);
+ while (slp != NULL) {
+ last = slp;
+ slp = SeqLocFindNext (location, slp);
+ }
+ if (last == NULL) return;
+
+ switch (last->choice) {
+ case SEQLOC_INT :
+ sinp = (SeqIntPtr) last->data.ptrvalue;
+ if (sinp != NULL) {
+ if (strand == Seq_strand_minus) {
+ sinp->from = 0;
+ } else {
+ sinp->to = bsp->length - 1;
+ }
+ }
+ case SEQLOC_PNT :
+ /* not yet implemented */
+ break;
+ case SEQLOC_PACKED_PNT :
+ /* not yet implemented */
+ break;
+ default :
+ break;
+ }
+}
+
+static void TruncateCDS (
+ SeqFeatPtr sfp,
+ BioseqPtr pbsp
+)
+
+{
+ Int4 len;
+ SeqIntPtr sinp;
+ SeqLocPtr slp;
+ Int4 total = 0;
+
+ slp = SeqLocFindNext (sfp->location, NULL);
+ while (slp != NULL) {
+ len = SeqLocLen (slp);
+
+ if (len + total <= (pbsp->length + 1) * 3) {
+ total += len;
+ } else {
+ if (slp->choice == SEQLOC_INT) {
+ sinp = (SeqIntPtr) slp->data.ptrvalue;
+ if (sinp != NULL) {
+ len = (pbsp->length + 1) * 3 - total;
+ if (sinp->strand == Seq_strand_minus) {
+ sinp->from = sinp->to - len + 1;
+ } else {
+ sinp->to = sinp->from + len - 1;
+ }
+ }
+ }
+ return;
+ }
+
+ slp = SeqLocFindNext (sfp->location, slp);
+ }
+}
+
+static void DoFeatProp (
+ BioseqPtr bsp,
+ SeqAlignPtr salp,
+ Int4 begin,
+ Int4 fin,
+ SeqFeatPtr sfp,
+ Boolean gapSplit,
+ Boolean stopCDS,
+ Boolean transPast,
+ Boolean cds3end,
+ Uint1 strand
+)
+
+{
+ CodeBreakPtr cbp, prevcbp, nextcbp;
+ CdRegionPtr crp;
+ SeqFeatPtr dup, prot;
+ Uint2 entityID;
+ MolInfoPtr mip;
+ BioseqPtr newbsp, pbsp;
+ SeqLocPtr newloc;
+ Boolean partial5;
+ Boolean partial3;
+ ProtRefPtr prp;
+ RnaRefPtr rrp;
+ SeqDescrPtr sdp;
+ SeqEntryPtr sep;
+ SeqIdPtr sip;
+ tRNAPtr trp;
+ SeqFeatXrefPtr xref;
+ Boolean xtend;
+
+ if (bsp == NULL || salp == NULL || sfp == NULL) return;
+
+ sip = AlnMgrGetNthSeqIdPtr (salp, fin);
+ if (sip == NULL) return;
+
+ newloc = MapLocForProp (salp, begin, fin, sip, gapSplit, sfp->location);
+ if (newloc == NULL) return;
+
+ dup = AsnIoMemCopy ((Pointer) sfp,
+ (AsnReadFunc) SeqFeatAsnRead,
+ (AsnWriteFunc) SeqFeatAsnWrite);
+ SeqLocFree (dup->location);
+ dup->location = newloc;
+
+ switch (dup->data.choice) {
+ case SEQFEAT_CDREGION :
+ crp = (CdRegionPtr) dup->data.value.ptrvalue;
+ if (crp != NULL) {
+ prevcbp = NULL;
+ for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp) {
+ nextcbp = cbp->next;
+ newloc = MapLocForProp (salp, begin, fin, sip, gapSplit, cbp->loc);
+ SeqLocFree (cbp->loc);
+ cbp->loc = newloc;
+ if (cbp->loc == NULL) {
+ if (prevcbp != NULL) {
+ prevcbp->next = nextcbp;
+ } else {
+ crp->code_break = nextcbp;
+ }
+ cbp->next = NULL;
+ CodeBreakFree (cbp);
+ } else {
+ prevcbp = cbp;
+ }
+ }
+ }
+ break;
+ case SEQFEAT_RNA :
+ rrp = (RnaRefPtr) dup->data.value.ptrvalue;
+ if (rrp != NULL && rrp->ext.choice == 2) {
+ trp = (tRNAPtr) rrp->ext.value.ptrvalue;
+ if (trp != NULL && trp->anticodon != NULL) {
+ newloc = MapLocForProp (salp, begin, fin, sip, gapSplit, trp->anticodon);
+ SeqLocFree (trp->anticodon);
+ trp->anticodon = newloc;
+ }
+ }
+ break;
+ default :
+ break;
+ }
+
+ newbsp = BioseqFindCore (sip);
+ if (newbsp == NULL) return;
+ sep = SeqMgrGetSeqEntryForData (newbsp);
+ if (sep == NULL) return;
+ CreateNewFeature (sep, NULL, dup->data.choice, dup);
+
+ if (dup->product != NULL) {
+ dup->product = SeqLocFree (dup->product);
+ }
+
+ if (dup->data.choice != SEQFEAT_CDREGION) return;
+
+ if (transPast && cds3end) {
+ ExtendLocToEnd (dup->location, newbsp, strand);
+ }
+
+ sip = SeqLocId (sfp->product);
+ if (sip == NULL) return;
+ pbsp = BioseqFindCore (sip);
+ if (pbsp == NULL) return;
+ prot = SeqMgrGetBestProteinFeature (pbsp, NULL);
+ if (prot == NULL || prot->data.choice != SEQFEAT_PROT) return;
+ prp = (ProtRefPtr) prot->data.value.ptrvalue;
+ if (prp == NULL) return;
+ prp = AsnIoMemCopy ((Pointer) prp,
+ (AsnReadFunc) ProtRefAsnRead,
+ (AsnWriteFunc) ProtRefAsnWrite);
+ xref = SeqFeatXrefNew ();
+ if (xref == NULL) return;
+ xref->data.choice = SEQFEAT_PROT;
+ xref->data.value.ptrvalue = (Pointer) prp;
+ xref->next = dup->xref;
+ dup->xref = xref;
+
+ entityID = ObjMgrGetEntityIDForPointer (newbsp);
+ PromoteXrefsEx (dup, newbsp, entityID, (Boolean) (! stopCDS), FALSE);
+
+ /* now truncate new cds based on new protein length */
+
+ sip = SeqLocId (dup->product);
+ if (sip == NULL) return;
+ pbsp = BioseqFindCore (sip);
+ if (pbsp == NULL) return;
+ TruncateCDS (dup, pbsp);
+
+ CheckSeqLocForPartial (dup->location, &partial5, &partial3);
+ if (cds3end) {
+ xtend = FALSE;
+ if (strand == Seq_strand_minus) {
+ if (SeqLocStop (dup->location) == 0) {
+ xtend = TRUE;
+ }
+ } else {
+ if (SeqLocStop (dup->location) == newbsp->length - 1) {
+ xtend = TRUE;
+ }
+ }
+ if (xtend) {
+ partial3 = TRUE;
+ SetSeqLocPartial (dup->location, partial5, partial3);
+ for (sdp = pbsp->descr; sdp != NULL; sdp = sdp->next) {
+ if (sdp->choice != Seq_descr_molinfo) continue;
+ mip = (MolInfoPtr) sdp->data.ptrvalue;
+ if (mip == NULL) continue;
+ if (partial5 && partial3) {
+ mip->completeness = 5;
+ } else if (partial5) {
+ mip->completeness = 3;
+ } else if (partial3) {
+ mip->completeness = 4;
+ }
+ }
+ }
+ }
+ dup->partial = (Boolean) (partial5 || partial3);
+}
+
+static Boolean CDSgoesToEnd (
+ BioseqPtr bsp,
+ SeqMgrFeatContext PNTR fcontext
+)
+
+{
+ if (fcontext->strand == Seq_strand_minus) {
+ if (fcontext->left == 0 && fcontext->partialR) return TRUE;
+ } else {
+ if (fcontext->right == bsp->length - 1 && fcontext->partialR) return TRUE;
+ }
+ return FALSE;
+}
+
+static void AcceptFeatProp (
+ ButtoN b
+)
+
+{
+ BioseqPtr bsp;
+ Boolean cds3end;
+ Uint2 entityID;
+ SeqMgrFeatContext fcontext;
+ FprDataPtr fdp;
+ Boolean gapSplit;
+ Int4 i;
+ Int4 numRows;
+ Int4 row;
+ SeqAlignPtr salp;
+ SeqFeatPtr sfp;
+ SeqIdPtr sip;
+ Boolean stopCDS;
+ Boolean transPast;
+
+ fdp = (FprDataPtr) GetObjectExtra (b);
+ if (fdp == NULL) return;
+ SafeHide (fdp->form);
+
+ bsp = fdp->bsp;
+ salp = fdp->salp;
+ if (bsp == NULL || salp == NULL) {
+ Remove (fdp->form);
+ return;
+ }
+
+ if (GetValue (fdp->allOrSel) == 1) {
+ fdp->selFeatItemID = 0;
+ }
+ if (GetValue (fdp->gapSplit) == 1) {
+ gapSplit = FALSE;
+ } else {
+ gapSplit= TRUE;
+ }
+ if (GetStatus (fdp->stopCDS)) {
+ stopCDS = TRUE;
+ } else {
+ stopCDS = FALSE;
+ }
+ if (GetStatus (fdp->transPast)) {
+ transPast = TRUE;
+ } else {
+ transPast = FALSE;
+ }
+
+ SeqEntrySetScope (NULL);
+
+ SAIndexFree (salp->saip);
+ salp->saip = NULL;
+ AlnMgrIndexSingleChildSeqAlign (salp);
+
+ sip = SeqIdFindBest (bsp->id, 0);
+ row = AlnMgrGetNForSip (salp, sip);
+ numRows = AlnMgrGetNumRows (salp);
+
+ if (row == -1) {
+ Message (MSG_OK, "AlnMgrGetNForSip failed");
+ Remove (fdp->form);
+ return;
+ }
+ if (numRows < 1) {
+ Message (MSG_OK, "AlnMgrGetNumRows failed");
+ Remove (fdp->form);
+ return;
+ }
+ if (row < 1 || row > numRows) {
+ Message (MSG_OK, "row is %ld, numRows is %ld, unable to process", (long) row, (long) numRows);
+ Remove (fdp->form);
+ return;
+ }
+
+ if (fdp->selFeatItemID != 0) {
+
+ /* propagate single selected feature */
+
+ sfp = SeqMgrGetDesiredFeature (0, bsp, fdp->selFeatItemID, 0, NULL, &fcontext);
+ if (sfp != NULL) {
+ cds3end = CDSgoesToEnd (bsp, &fcontext);
+ for (i = 1; i <= numRows; i++) {
+ if (i != row) {
+ DoFeatProp (bsp, salp, row, i, sfp, gapSplit, stopCDS, transPast, cds3end, fcontext.strand);
+ }
+ }
+ }
+ } else {
+
+ /* propagate all features on bioseq */
+
+ sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
+ while (sfp != NULL) {
+ cds3end = CDSgoesToEnd (bsp, &fcontext);
+ for (i = 1; i <= numRows; i++) {
+ if (i != row) {
+ DoFeatProp (bsp, salp, row, i, sfp, gapSplit, stopCDS, transPast, cds3end, fcontext.strand);
+ }
+ }
+
+ sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
+ }
+ }
+
+ entityID = ObjMgrGetEntityIDForPointer (bsp);
+ ObjMgrSetDirtyFlag (entityID, TRUE);
+ ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+
+ Remove (fdp->form);
+}
+
+static ForM FeaturePropagateForm (
+ BioseqPtr bsp,
+ SeqAlignPtr salp,
+ Uint2 selFeatItemID
+)
+
+{
+ ButtoN b;
+ GrouP c;
+ FprDataPtr fdp;
+ GrouP g;
+ PrompT ppt;
+ SeqIdPtr sip;
+ Char strid [41];
+ Char txt [128];
+ WindoW w;
+
+ if (bsp == NULL) return NULL;
+ fdp = (FprDataPtr) MemNew (sizeof (FprData));
+ if (fdp == NULL) return NULL;
+ w = FixedWindow (-50, -33, -10, -10, "Feature Propagate", NULL);
+ if (w == NULL) return NULL;
+
+ SetObjectExtra (w, (Pointer) fdp, StdCleanupFormProc);
+ fdp->form = (ForM) w;
+ fdp->formmessage = UpdateSequenceFormMessage;
+
+#ifdef WIN_MAC
+ fdp->activate = UpdateSequenceFormActivated;
+ SetActivate (w, UpdateSequenceFormActivate);
+#endif
+
+ fdp->bsp = bsp;
+ fdp->salp = salp;
+ fdp->selFeatItemID = selFeatItemID;
+
+ sip = SeqIdFindWorst (bsp->id);
+ SeqIdWrite (sip, strid, PRINTID_REPORT, sizeof (strid) - 1);
+ if (ISA_na (bsp->mol)) {
+ sprintf (txt, "Propagate from %s to all other nucleotides", strid);
+ } else {
+ sprintf (txt, "Propagate from %s to all other proteins", strid);
+ }
+
+ g = HiddenGroup (w, -1, 0, NULL);
+ SetGroupSpacing (g, 5, 5);
+
+ ppt = StaticPrompt (g, txt, 0, 0, programFont, 'c');
+
+ fdp->allOrSel = HiddenGroup (g, 2, 0, NULL);
+ RadioButton (fdp->allOrSel, "All Features");
+ b = RadioButton (fdp->allOrSel, "Selected Feature");
+ if (selFeatItemID > 0) {
+ SetValue (fdp->allOrSel, 2);
+ } else {
+ Disable (b);
+ SetValue (fdp->allOrSel, 1);
+ }
+
+ fdp->gapSplit = HiddenGroup (g, 2, 0, NULL);
+ RadioButton (fdp->gapSplit, "Extend over gaps");
+ RadioButton (fdp->gapSplit, "Split at gaps");
+ SetValue (fdp->gapSplit, 1);
+
+ fdp->stopCDS = CheckBox (g, "Stop CDS translation at internal stop codon", NULL);
+ SetStatus (fdp->stopCDS, TRUE);
+
+ fdp->transPast = CheckBox (g, "Translate CDS after partial 3' boundary", NULL);
+
+ c = HiddenGroup (w, 4, 0, NULL);
+ fdp->accept = PushButton (c, "Accept", AcceptFeatProp);
+ SetObjectExtra (fdp->accept, (Pointer) fdp, NULL);
+ PushButton (c, "Cancel", StdCancelButtonProc);
+
+ AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) fdp->allOrSel,
+ (HANDLE) fdp->gapSplit, (HANDLE) fdp->stopCDS,
+ (HANDLE) fdp->transPast, (HANDLE) c, NULL);
+ RealizeWindow (w);
+
+ return (ForM) w;
+}
+
+extern void NewFeaturePropagate (
+ IteM i
+);
+extern void NewFeaturePropagate (
+ IteM i
+)
+
+{
+ BaseFormPtr bfp;
+ BioseqPtr bsp;
+ ForM f;
+ SeqMgrFeatContext fcontext;
+ Uint2 itemID = 0;
+ SeqAlignPtr salp;
+ SeqFeatPtr sfp;
+ SelStructPtr sel;
+ SeqEntryPtr sep;
+
+#ifdef WIN_MAC
+ bfp = currentFormDataPtr;
+#else
+ bfp = GetObjectExtra (i);
+#endif
+ if (bfp == NULL) return;
+ sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+ if (sep == NULL) return;
+ bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+ if (bsp == NULL) {
+ Message (MSG_OK, "You must target a single sequence in order to propagate");
+ return;
+ }
+ sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
+ if (sfp == NULL) {
+ Message (MSG_OK, "The sequence must have features in order to propagate");
+ return;
+ }
+ salp = SeqMgrFindSeqAlignByID (bfp->input_entityID, 1);
+ if (salp == NULL) {
+ Message (MSG_OK, "The record must have an alignment in order to propagate");
+ return;
+ }
+
+ sel = ObjMgrGetSelected ();
+ if (sel != NULL && sel->entityID == bfp->input_entityID &&
+ sel->next == NULL && sel->itemtype == OBJ_SEQFEAT) {
+ sfp = SeqMgrGetDesiredFeature (bfp->input_entityID, NULL, sel->itemID, 0, NULL, &fcontext);
+ if (sfp != NULL && fcontext.bsp == bsp) {
+ itemID = sel->itemID;
+ }
+ }
+
+ f = FeaturePropagateForm (bsp, salp, itemID);
+ if (f == NULL) return;
+ Show (f);
+ Select (f);
+ SendHelpScrollMessage (helpForm, "Edit Menu", "Feature Propagate");
+}
+