1 /*   sequin8.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *            National Center for Biotechnology Information (NCBI)
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government do not place any restriction on its use or reproduction.
13 *  We would, however, appreciate having the NCBI and the author cited in
14 *  any work or product based on this material
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name:  sequin8.c
27 *
28 * Author:  Jonathan Kans
29 *
30 * Version Creation Date:   2/3/98
31 *
32 * $Revision: 6.677 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date     Name        Description of modification
39 * -------  ----------  -----------------------------------------------------
40 *
41 *
42 * ==========================================================================
43 */
44 
45 #include "sequin.h"
46 #include <objsub.h>
47 #include <valid.h>
48 #include <cdrgn.h>
49 #include <suggslp.h>
50 #include <toasn3.h>
51 #include <subutil.h>
52 #include <explore.h>
53 #include <medarch.h>
54 #include <medutil.h>
55 #include <tofasta.h>
56 #include <asn2gnbk.h>
57 #include <alignmgr2.h>
58 #include <spidey.h>
59 #include <blast.h>
60 #include <salpanel.h>
61 #include <seqpanel.h>
62 #include <edutil.h>
63 #include <tax3api.h>
64 #include <asn2gnbp.h> /* included for discrepancy report */
65 #include <algo/blast/api/twoseq_api.h>
66 #include <algo/blast/api/blast_seqalign.h>
67 
68 #include <macrodlg.h>
69 #include <macroapi.h>
70 #include <alignval.h>
71 #include <pubdesc.h>
72 
73 #include <sqnutils.h>
74 
75 #define DEFLINE_MAX_LEN          380
76 #define TEXT_MAX_LEN             64
77 #define DEFLINE_MAX_GENENAME_LEN 64
78 #define ALL_FEATURES             255
79 
80 typedef struct evidenceformdata {
81   FEATURE_FORM_BLOCK
82 
83   LisT           objlist;
84   TexT           findthis;
85   Uint2          itemtype;
86   Uint2          subtype;
87   PopuP          evdence;
88   Uint2          exp_ev;
89   ValNodePtr     head;
90   Boolean        stringfound;
91   Char           findStr [128];
92   ButtoN         case_insensitive;
93   ButtoN         when_string_not_present;
94 } EvidenceFormData, PNTR
95 
96 EvidenceFormPtr;
97 
98 typedef struct codebreakformdata {
99   FEATURE_FORM_BLOCK
100   PopuP  aminoAcidPopup;
101   Char   currentCodonStr [4];
102   TexT   codonText;
103   ButtoN acceptButton;
104 } CodeBreakFormData, PNTR CodeBreakFormPtr;
105 
IsRealImpFeat(Uint2 subtype)106 static Boolean IsRealImpFeat (Uint2 subtype)
107 
108 {
109   if (subtype >= FEATDEF_allele && subtype <= FEATDEF_site_ref) return TRUE;
110   if (subtype == FEATDEF_oriT) return TRUE;
111   return FALSE;
112 }
113 
114 
ParseInNucUpdates(IteM i)115 extern void ParseInNucUpdates (IteM i)
116 
117 {
118   BaseFormPtr  bfp;
119   SeqEntryPtr  sep;
120 
121 #ifdef WIN_MAC
122   bfp = currentFormDataPtr;
123 #else
124   bfp = GetObjectExtra (i);
125 #endif
126   if (bfp == NULL) return;
127   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
128   if (sep == NULL) return;
129   Message (MSG_OK, "Not yet implemented");
130 }
131 
132 #undef NLM_EXTERN
133 #ifdef NLM_IMPORT
134 #define NLM_EXTERN NLM_IMPORT
135 #else
136 #define NLM_EXTERN extern
137 #endif
138 
GeneticCodeFromCrp(CdRegionPtr crp)139 static Int2 GeneticCodeFromCrp (CdRegionPtr crp)
140 
141 {
142   Int2            code;
143   GeneticCodePtr  gcp;
144   Char            name [256];
145   ValNodePtr      tmp;
146 
147   code = 0;
148   name [0] = '\0';
149   gcp = crp->genetic_code;
150   if (gcp != NULL) {
151     tmp = (ValNodePtr) gcp->data.ptrvalue;
152     for (tmp = (ValNodePtr) gcp->data.ptrvalue; tmp != NULL; tmp = tmp->next) {
153       switch (tmp->choice) {
154         case 1 :
155           if (name [0] == '\0') {
156             StringNCpy_0 (name, (CharPtr) tmp->data.ptrvalue, sizeof (name));
157           }
158           break;
159         case 2 :
160           code = tmp->data.intvalue;
161           break;
162         default :
163           break;
164       }
165     }
166     if (code == 0) {
167       gcp = GeneticCodeFind (code, name);
168       if (gcp != NULL) {
169         for (tmp = (ValNodePtr) gcp->data.ptrvalue; tmp != NULL; tmp = tmp->next) {
170           switch (tmp->choice) {
171             case 2 :
172               code = tmp->data.intvalue;
173               break;
174             default :
175               break;
176           }
177         }
178       }
179     }
180   }
181   return code;
182 }
183 
ExtendSeqLocToPosition(SeqLocPtr slp,Boolean end5,Int4 pos)184 extern void ExtendSeqLocToPosition (SeqLocPtr slp, Boolean end5, Int4 pos)
185 {
186   Uint1          strand;
187   SeqLocPtr      slp_to_change, slp_index;
188   Int4           extent_to_change;
189   Int4           start, stop;
190   SeqIdPtr       sip;
191   BioseqPtr      bsp;
192 
193   if (slp == NULL || pos < 0) return;
194 
195   bsp = BioseqFindFromSeqLoc (slp);
196   if (bsp == NULL) return;
197 
198   slp_to_change = NULL;
199   strand = SeqLocStrand (slp);
200   switch (slp->choice)
201   {
202     case SEQLOC_INT:
203       slp_to_change = slp;
204       break;
205     case SEQLOC_MIX:
206   	case SEQLOC_PACKED_INT:
207       sip = SeqLocId (slp);
208       if (sip == NULL) return; /* can only process if all on one bioseq */
209       slp_to_change = NULL;
210       if ((strand == Seq_strand_minus && end5)
211         || (strand != Seq_strand_minus && !end5))
212       {
213         extent_to_change = 0;
214         for (slp_index = (SeqLocPtr)slp->data.ptrvalue; slp_index != NULL; slp_index = slp_index->next)
215         {
216           stop = GetOffsetInBioseq (slp_index, bsp, SEQLOC_STOP);
217           if (stop > extent_to_change)
218           {
219             slp_to_change = slp_index;
220             extent_to_change = stop;
221           }
222         }
223       }
224       else
225       {
226         extent_to_change = bsp->length;
227         for (slp_index = (SeqLocPtr)slp->data.ptrvalue; slp_index != NULL; slp_index = slp_index->next)
228         {
229           start = GetOffsetInBioseq (slp_index, bsp, SEQLOC_START);
230           if (start < extent_to_change)
231           {
232             slp_to_change = slp_index;
233             extent_to_change = start;
234           }
235         }
236       }
237       break;
238   }
239 
240   if (slp_to_change != NULL)
241   {
242     if ((strand == Seq_strand_minus && end5)
243       || (strand != Seq_strand_minus && !end5))
244     {
245       start = GetOffsetInBioseq (slp_to_change, bsp, SEQLOC_START);
246       stop = pos;
247     }
248     else
249     {
250       start = pos;
251       stop = GetOffsetInBioseq (slp_to_change, bsp, SEQLOC_STOP);
252     }
253     if (start < 0
254         || stop > bsp->length - 1
255         || start > stop)
256     {
257       return;
258     }
259     expand_seq_loc (start, stop, strand, slp_to_change);
260   }
261 }
262 
263 
ExtendOnePartialFeatureExEx(SeqFeatPtr sfp,Boolean extend5,Boolean extend3,Boolean stop_at_gap)264 static void ExtendOnePartialFeatureExEx (SeqFeatPtr sfp, Boolean extend5, Boolean extend3, Boolean stop_at_gap)
265 {
266   BioseqPtr   bsp;
267   Boolean     partial3, partial5;
268   Int4        start_diff;
269   CdRegionPtr crp;
270 
271   if (sfp == NULL) return;
272   bsp = BioseqFindFromSeqLoc (sfp->location);
273   if (bsp == NULL) return;
274   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
275   if (partial5 && extend5)
276   {
277     if (stop_at_gap) {
278       start_diff = ExtendSeqLocToEndOrGap (sfp->location, bsp, TRUE);
279     } else {
280       start_diff = ExtendSeqLocToEnd (sfp->location, bsp, TRUE);
281     }
282     if (start_diff > 0 && sfp->data.choice == SEQFEAT_CDREGION) {
283       crp = (CdRegionPtr) sfp->data.value.ptrvalue;
284       if (crp != NULL) {
285           if (crp->frame == 0) {
286               crp->frame = 1;
287           }
288           crp->frame = (crp->frame + start_diff - 1) % 3 + 1;
289       }
290     }
291   }
292   if (partial3 && extend3)
293   {
294     if (stop_at_gap) {
295       ExtendSeqLocToEndOrGap (sfp->location, bsp, FALSE);
296     } else {
297       ExtendSeqLocToEnd (sfp->location, bsp, FALSE);
298     }
299   }
300 }
301 
302 
ExtendOnePartialFeatureEx(SeqFeatPtr sfp,Boolean extend5,Boolean extend3)303 static void ExtendOnePartialFeatureEx (SeqFeatPtr sfp, Boolean extend5, Boolean extend3)
304 {
305   ExtendOnePartialFeatureExEx (sfp, extend5, extend3, FALSE);
306 }
307 
308 
ExtendOnePartialFeatureToEndOrGap(SeqFeatPtr sfp,Pointer userdata)309 static void ExtendOnePartialFeatureToEndOrGap (SeqFeatPtr sfp, Pointer userdata)
310 {
311   ExtendOnePartialFeatureExEx (sfp, TRUE, TRUE, TRUE);
312 }
313 
314 
ExtendOnePartialFeature(SeqFeatPtr sfp,Pointer userdata)315 static void ExtendOnePartialFeature (SeqFeatPtr sfp, Pointer userdata)
316 {
317   ExtendOnePartialFeatureEx (sfp, TRUE, TRUE);
318 }
319 
320 
ExtendPartialFeaturesToEndsForEntityID(Uint2 entityID)321 NLM_EXTERN void ExtendPartialFeaturesToEndsForEntityID (Uint2 entityID)
322 {
323   SeqEntryPtr       sep, old_scope;
324   SelStructPtr      sel;
325   SeqFeatPtr        sfp;
326   SeqMgrFeatContext fcontext;
327 
328   sep = GetTopSeqEntryForEntityID (entityID);
329   if (sep == NULL) return;
330   sel = ObjMgrGetSelected ();
331   WatchCursor ();
332   Update ();
333   old_scope = SeqEntrySetScope(sep);
334   if (sel == NULL)
335   {
336     VisitFeaturesInSep (sep, NULL, ExtendOnePartialFeature);
337   }
338   else
339   {
340     while (sel != NULL)
341     {
342       if (sel->entityID == entityID
343         && sel->itemtype == OBJ_SEQFEAT)
344       {
345         sfp = SeqMgrGetDesiredFeature (entityID, NULL, sel->itemID, 0, NULL, &fcontext);
346         if (sfp != NULL)
347         {
348           ExtendOnePartialFeature (sfp, NULL);
349         }
350       }
351       sel = sel->next;
352     }
353   }
354   SeqEntrySetScope(old_scope);
355   ArrowCursor ();
356   Update ();
357   ObjMgrSetDirtyFlag (entityID, TRUE);
358   ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
359 }
360 
361 
ExtendPartialFeatures(IteM i)362 extern void ExtendPartialFeatures (IteM i)
363 {
364   BaseFormPtr       bfp;
365 
366 #ifdef WIN_MAC
367   bfp = currentFormDataPtr;
368 #else
369   bfp = GetObjectExtra (i);
370 #endif
371   if (bfp == NULL) return;
372   ExtendPartialFeaturesToEndsForEntityID(bfp->input_entityID);
373 }
374 
375 
376 typedef struct extendpartialfeaturesform {
377   FORM_MESSAGE_BLOCK
378   DialoG feature_type;
379   ButtoN extend5;
380   ButtoN extend3;
381   ButtoN stop_at_gaps;
382   DialoG constraint;
383   ButtoN leave_dlg_up;
384 } ExtendPartialFeaturesFormData, PNTR ExtendPartialFeaturesFormPtr;
385 
DoExtendPartialFeatures(ButtoN b)386 static void DoExtendPartialFeatures (ButtoN b)
387 {
388   ExtendPartialFeaturesFormPtr f;
389   SeqEntryPtr sep;
390   AECRActionPtr action;
391   ApplyActionPtr fake_apply;
392   FeatureFieldPtr feature_field;
393   ValNodePtr vnp;
394   ValNodePtr object_list;
395   Boolean    extend5, extend3, stop_at_gaps;
396 
397   f = (ExtendPartialFeaturesFormPtr) GetObjectExtra (b);
398   if (f == NULL) return;
399 
400   sep = GetTopSeqEntryForEntityID (f->input_entityID);
401   if (sep == NULL) return;
402 
403   /* note - this is a small amount of hackery, designed to put off adding "extend partial features" as a macro language action.
404    * if this is ever added, this code should be moved to macroapi.c.
405    */
406   feature_field = FeatureFieldNew ();
407   vnp = DialogToPointer (f->feature_type);
408   if (vnp == NULL) {
409     feature_field->type = Macro_feature_type_any;
410   } else {
411     feature_field->type = vnp->choice;
412     vnp = ValNodeFree (vnp);
413   }
414   fake_apply = ApplyActionNew ();
415   ValNodeAddPointer (&(fake_apply->field), FieldType_feature_field, feature_field);
416   action = AECRActionNew ();
417   ValNodeAddPointer (&(action->action), ActionChoice_apply, fake_apply);
418 
419   action->constraint = DialogToPointer (f->constraint);
420   object_list = GetObjectListForAECRAction (sep, action);
421   action = AECRActionFree (action);
422 
423   extend5 = GetStatus (f->extend5);
424   extend3 = GetStatus (f->extend3);
425   stop_at_gaps = GetStatus (f->stop_at_gaps);
426   for (vnp = object_list; vnp != NULL; vnp = vnp->next) {
427     if (vnp->choice == OBJ_SEQFEAT && vnp->data.ptrvalue != NULL) {
428       ExtendOnePartialFeatureExEx (vnp->data.ptrvalue, extend5, extend3, stop_at_gaps);
429     }
430   }
431   object_list = ValNodeFree (object_list);
432   ArrowCursor ();
433   Update ();
434   ObjMgrSetDirtyFlag (f->input_entityID, TRUE);
435   ObjMgrSendMsg (OM_MSG_UPDATE, f->input_entityID, 0, 0);
436   if (!GetStatus (f->leave_dlg_up)) {
437     Remove (f->form);
438   }
439 }
440 
441 
ExtendPartialFeaturesWithConstraintBaseForm(BaseFormPtr bfp)442 NLM_EXTERN void ExtendPartialFeaturesWithConstraintBaseForm (BaseFormPtr bfp)
443 {
444   ExtendPartialFeaturesFormPtr f;
445   ValNodePtr          feature_list = NULL;
446   ValNode             vn;
447   WindoW              w;
448   GrouP               h, g, c;
449   PrompT              p1;
450   ButtoN              b;
451 
452   if (bfp == NULL) return;
453 
454   f = (ExtendPartialFeaturesFormPtr) MemNew (sizeof (ExtendPartialFeaturesFormData));
455   if (f == NULL) return;
456 
457   w = FixedWindow (-50, -33, -10, -10, "Extend Partial Features", StdCloseWindowProc);
458   SetObjectExtra (w, f, StdCleanupExtraProc);
459   f->form = (ForM) w;
460   f->input_entityID = bfp->input_entityID;
461 
462   h = HiddenGroup (w, -1, 0, NULL);
463   SetGroupSpacing (h, 10, 10);
464 
465   p1 = StaticPrompt (h, "Feature Type to Extend", 0, dialogTextHeight, programFont, 'c');
466   ValNodeAddPointer (&feature_list, Macro_feature_type_any, StringSave ("Any"));
467   AddAllFeaturesToChoiceList (&feature_list);
468 
469   f->feature_type = ValNodeSelectionDialog (h, feature_list, TALL_SELECTION_LIST, ValNodeStringName,
470                                 ValNodeSimpleDataFree, ValNodeStringCopy,
471                                 ValNodeChoiceMatch, "feature type",
472                                 NULL, NULL, FALSE);
473   vn.choice = Macro_feature_type_any;
474   vn.data.ptrvalue = NULL;
475   vn.next = NULL;
476   PointerToDialog (f->feature_type, &vn);
477 
478   g = HiddenGroup (h, 2, 0, NULL);
479   f->extend5 = CheckBox (g, "Extend partial 5'", NULL);
480   SetStatus (f->extend5, TRUE);
481   f->extend3 = CheckBox (g, "Extend partial 3'", NULL);
482   SetStatus (f->extend3, TRUE);
483 
484   f->stop_at_gaps = CheckBox (h, "Stop at gaps", NULL);
485   SetStatus (f->stop_at_gaps, TRUE);
486 
487   f->constraint = ComplexConstraintDialog (h, NULL, NULL);
488   ChangeComplexConstraintFieldType (f->constraint, FieldType_feature_field, NULL, Macro_feature_type_any);
489   c = HiddenGroup (h, 3, 0, NULL);
490   b = PushButton (c, "Accept", DoExtendPartialFeatures);
491   SetObjectExtra (b, f, NULL);
492   PushButton (c, "Cancel", StdCancelButtonProc);
493   f->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
494 
495   AlignObjects (ALIGN_CENTER, (HANDLE) p1,
496                               (HANDLE) f->feature_type,
497                               (HANDLE) g,
498                               (HANDLE) f->stop_at_gaps,
499                               (HANDLE) f->constraint,
500                               (HANDLE) c,
501                               NULL);
502   Show (w);
503 }
504 
505 
ExtendPartialFeaturesWithConstraint(IteM i)506 extern void ExtendPartialFeaturesWithConstraint (IteM i)
507 {
508   BaseFormPtr       bfp;
509 
510 #ifdef WIN_MAC
511   bfp = currentFormDataPtr;
512 #else
513   bfp = GetObjectExtra (i);
514 #endif
515   ExtendPartialFeaturesWithConstraintBaseForm(bfp);
516 }
517 
518 
HasValidStartCodon(SeqFeatPtr cds)519 static Boolean HasValidStartCodon (SeqFeatPtr cds)
520 {
521   ByteStorePtr  bs;
522   CharPtr       prot;
523 
524   if (cds == NULL) return FALSE;
525 
526   bs = ProteinFromCdRegionEx (cds, TRUE, FALSE);
527 
528   if (bs == NULL) return FALSE;
529   prot = BSMerge (bs, NULL);
530   bs = BSFree (bs);
531   if (prot == NULL) return FALSE;
532   if (prot [0] != 'M') return FALSE;
533   return TRUE;
534 }
535 
FixReadingFrame(CdRegionPtr crp,SeqLocPtr slp,BioseqPtr bsp,Int4 start)536 static void FixReadingFrame (
537   CdRegionPtr crp,
538   SeqLocPtr slp,
539   BioseqPtr bsp,
540   Int4 start
541 )
542 {
543   Int4 offset;
544 
545   if (crp == NULL || slp == NULL) return;
546 
547   if (SeqLocStrand (slp) == Seq_strand_minus)
548   {
549     offset = bsp->length - start;
550   }
551   else
552   {
553     offset = start;
554   }
555   start = offset % 3;
556   start = start + 1;
557   crp->frame = start;
558 }
559 
RecomputeSuggestedIntervalsForCDS(Uint2 entityID,BioseqPtr PNTR batchbsp,Int4Ptr count,MonitorPtr mon,SeqFeatPtr sfp)560 extern void RecomputeSuggestedIntervalsForCDS
561 (Uint2          entityID,
562  BioseqPtr PNTR batchbsp,
563  Int4Ptr        count,
564  MonitorPtr     mon,
565  SeqFeatPtr     sfp)
566 {
567   Int2           code;
568   CdRegionPtr    crp;
569   BioseqPtr      nucbsp;
570   BioseqPtr      protbsp;
571   SeqIdPtr       sip;
572   SeqLocPtr      slp;
573   Char           str [256];
574   Char           tmp [256];
575   Boolean        partial3, partial5;
576 
577   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return;
578   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
579   if (crp == NULL) return;
580 
581   code = GeneticCodeFromCrp (crp);
582 
583   nucbsp = GetBioseqGivenSeqLoc (sfp->location, entityID);
584   if (nucbsp != NULL && batchbsp != NULL && *batchbsp != NULL
585       && nucbsp != *batchbsp) {
586     ClearBatchSuggestNucleotide ();
587     *batchbsp = nucbsp;
588     SetBatchSuggestNucleotide (*batchbsp, code);
589 /*    Message (MSG_POSTERR, "Recompute Suggest is reverting to slower processing"); */
590   }
591   sip = SeqLocId (sfp->product);
592   if (sip != NULL) {
593     protbsp = BioseqFind (sip);
594     if (nucbsp != NULL && protbsp != NULL &&
595         ISA_na (nucbsp->mol) && ISA_aa (protbsp->mol) &&
596         nucbsp->length > 0 && protbsp->length > 0) {
597       str [0] = '\0';
598       tmp [0] = '\0';
599       sip = SeqIdFindWorst (protbsp->id);
600       SeqIdWrite (sip, tmp, PRINTID_REPORT, sizeof (tmp));
601       if (count != NULL)
602       {
603         (*count) ++;
604         if (mon != NULL)
605         {
606           sprintf (str, "Processing sequence %d [%s]", *count, tmp);
607           MonitorStrValue (mon, str);
608           Update ();
609         }
610       }
611       slp = PredictCodingRegion (nucbsp, protbsp, code);
612       if (slp == NULL) return;
613 
614       /* correct for partial conditions */
615       CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
616       if (!partial5) {
617         crp->frame = 0;
618       }
619 
620       sfp->location = SeqLocFree (sfp->location);
621       sfp->location = slp;
622 
623       /* if no valid start codon, cds is 5' partial */
624       if (! HasValidStartCodon (sfp))
625       {
626         partial5 = TRUE;
627       }
628 
629       if (partial5 || partial3)
630       {
631 #if 0
632         /* removed, per DeAnne's request */
633         if (partial5)
634         {
635           start = GetOffsetInBioseq (sfp->location, nucbsp, SEQLOC_START);
636           FixReadingFrame (crp, sfp->location, nucbsp, start);
637           ExtendSeqLocToEnd (sfp->location, nucbsp, TRUE);
638         }
639 #endif
640         if (partial3)
641         {
642           ExtendSeqLocToEnd (sfp->location, nucbsp, FALSE);
643         }
644         SetSeqLocPartial (sfp->location, partial5, partial3);
645       }
646       sfp->partial = LocationHasNullsBetween (sfp->location);
647       sfp->partial |= partial5 || partial3;
648     }
649   }
650 }
651 
RecomputeIntervalsForOneCDS(SeqFeatPtr sfp,RecompDataPtr rdp)652 extern void RecomputeIntervalsForOneCDS (SeqFeatPtr sfp, RecompDataPtr rdp)
653 {
654   SeqFeatPtr gene_to_update = NULL;
655   SeqLocPtr      orig_loc = NULL;
656 
657   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION || rdp == NULL)
658   {
659     return;
660   }
661 
662   if (rdp->fix_genes)
663   {
664     gene_to_update = SeqMgrGetOverlappingGene (sfp->location, NULL);
665     orig_loc = (SeqLocPtr) AsnIoMemCopy (sfp->location,
666                                          (AsnReadFunc) SeqLocAsnRead,
667                                          (AsnWriteFunc) SeqLocAsnWrite);
668   }
669   RecomputeSuggestedIntervalsForCDS (rdp->entityID, &(rdp->batchbsp),
670                                      &(rdp->count), rdp->mon, sfp);
671 
672   if (gene_to_update != NULL)
673   {
674     UpdateGeneLocation (gene_to_update, orig_loc,
675                         sfp->location, rdp->entityID);
676   }
677   orig_loc = SeqLocFree (orig_loc);
678 
679 }
680 
RecomputeSuggCallback(GatherContextPtr gcp)681 static Boolean RecomputeSuggCallback (GatherContextPtr gcp)
682 {
683   RecompDataPtr  rdp;
684   SeqFeatPtr     sfp;
685 
686   if (gcp == NULL) return TRUE;
687   if (gcp->thistype != OBJ_SEQFEAT) return TRUE;
688   rdp = (RecompDataPtr) gcp->userdata;
689   if (rdp == NULL) return TRUE;
690   sfp = (SeqFeatPtr) gcp->thisitem;
691   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return TRUE;
692 
693   RecomputeIntervalsForOneCDS (sfp, rdp);
694   return TRUE;
695 }
696 
RecomputeSuggestEx(Uint2 entityID,Boolean fix_genes,Boolean recompute_all)697 extern void RecomputeSuggestEx (Uint2 entityID, Boolean fix_genes, Boolean recompute_all)
698 
699 {
700   Int2              code;
701   GatherScope       gs;
702   SeqEntryPtr       nucsep;
703   RecompData        rd;
704   SeqEntryPtr       sep;
705   SelStructPtr      sel;
706   SeqFeatPtr        sfp;
707   SeqMgrFeatContext fcontext;
708 
709   sep = GetTopSeqEntryForEntityID (entityID);
710   if (sep == NULL) return;
711   sel = ObjMgrGetSelected ();
712   WatchCursor ();
713   Update ();
714   rd.count = 0;
715   rd.mon = MonitorStrNewEx ("Correcting Coding Regions", 20, FALSE);
716   rd.batchbsp = NULL;
717   rd.no_stop_at_end_of_complete_cds = FALSE;
718   rd.fix_genes = fix_genes;
719   rd.entityID = entityID;
720   nucsep = FindNucSeqEntry (sep);
721   if (nucsep != NULL && IS_Bioseq (nucsep)) {
722     rd.batchbsp = (BioseqPtr) nucsep->data.ptrvalue;
723   }
724   if (rd.batchbsp != NULL) {
725     code = SeqEntryToGeneticCode (sep, NULL, NULL, 0);
726     SetBatchSuggestNucleotide (rd.batchbsp, code);
727   }
728   if (sel == NULL || recompute_all)
729   {
730     MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
731     gs.seglevels = 1;
732     gs.get_feats_location = FALSE;
733     MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
734     gs.ignore[OBJ_BIOSEQ] = FALSE;
735     gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
736     gs.ignore[OBJ_SEQFEAT] = FALSE;
737     gs.ignore[OBJ_SEQANNOT] = FALSE;
738     GatherEntity (entityID, (Pointer) (&rd), RecomputeSuggCallback, &gs);
739   }
740   else
741   {
742     while (sel != NULL)
743     {
744       if (sel->entityID == entityID
745         && sel->itemtype == OBJ_SEQFEAT)
746       {
747         sfp = SeqMgrGetDesiredFeature (entityID, NULL, sel->itemID, 0, NULL, &fcontext);
748         if (sfp != NULL && sfp->idx.subtype == FEATDEF_CDS)
749         {
750           RecomputeIntervalsForOneCDS (sfp, &rd);
751         }
752       }
753       sel = sel->next;
754     }
755   }
756   MonitorFree (rd.mon);
757   if (rd.batchbsp != NULL) {
758     ClearBatchSuggestNucleotide ();
759   }
760   ArrowCursor ();
761   Update ();
762   ObjMgrSetDirtyFlag (entityID, TRUE);
763   ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
764 }
765 
RecomputeSuggest(IteM i)766 extern void RecomputeSuggest (IteM i)
767 {
768   BaseFormPtr       bfp;
769 
770 #ifdef WIN_MAC
771   bfp = currentFormDataPtr;
772 #else
773   bfp = GetObjectExtra (i);
774 #endif
775   if (bfp == NULL)
776   {
777     return;
778   }
779   RecomputeSuggestEx (bfp->input_entityID, FALSE, FALSE);
780 }
781 
RecomputeSuggestFixGenes(IteM i)782 extern void RecomputeSuggestFixGenes (IteM i)
783 {
784   BaseFormPtr       bfp;
785 
786 #ifdef WIN_MAC
787   bfp = currentFormDataPtr;
788 #else
789   bfp = GetObjectExtra (i);
790 #endif
791   if (bfp == NULL)
792   {
793     return;
794   }
795   RecomputeSuggestEx (bfp->input_entityID, TRUE, FALSE);
796 }
797 
798 
RetranslateCDSCallback(GatherContextPtr gcp)799 static Boolean RetranslateCDSCallback (GatherContextPtr gcp)
800 
801 {
802   RecompDataPtr  rdp;
803   SeqFeatPtr     sfp;
804 
805   if (gcp == NULL) return TRUE;
806   if (gcp->thistype != OBJ_SEQFEAT) return TRUE;
807   rdp = (RecompDataPtr) gcp->userdata;
808   if (rdp == NULL) return TRUE;
809   sfp = (SeqFeatPtr) gcp->thisitem;
810   return RetranslateOneCDS (sfp, gcp->entityID, rdp->include_stop,
811                             rdp->no_stop_at_end_of_complete_cds);
812 }
813 
RetranslateCdRegionsEx(Uint2 entityID,Boolean include_stop,Boolean no_stop_at_end_of_complete_cds)814 extern void RetranslateCdRegionsEx (
815   Uint2   entityID,
816   Boolean include_stop,
817   Boolean no_stop_at_end_of_complete_cds )
818 
819 {
820   GatherScope  gs;
821   RecompData   rd;
822   SeqEntryPtr  sep;
823 
824   sep = GetTopSeqEntryForEntityID (entityID);
825   if (sep == NULL) return;
826   WatchCursor ();
827   Update ();
828   rd.count = 0;
829   rd.mon = MonitorStrNewEx ("Correcting Coding Regions", 20, FALSE);
830   rd.include_stop = include_stop;
831   rd.no_stop_at_end_of_complete_cds = no_stop_at_end_of_complete_cds;
832   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
833   gs.seglevels = 1;
834   gs.get_feats_location = FALSE;
835   MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
836   gs.ignore[OBJ_BIOSEQ] = FALSE;
837   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
838   gs.ignore[OBJ_SEQFEAT] = FALSE;
839   gs.ignore[OBJ_SEQANNOT] = FALSE;
840   GatherEntity (entityID, (Pointer) (&rd), RetranslateCDSCallback, &gs);
841   MonitorFree (rd.mon);
842   ArrowCursor ();
843   Update ();
844   ObjMgrSetDirtyFlag (entityID, TRUE);
845   ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
846 }
847 
RetranslateCdRegions(IteM i,Boolean include_stop,Boolean no_stop_at_end_of_complete_cds)848 static void RetranslateCdRegions (
849   IteM i,
850   Boolean include_stop,
851   Boolean no_stop_at_end_of_complete_cds )
852 
853 {
854   BaseFormPtr  bfp;
855 
856 #ifdef WIN_MAC
857   bfp = currentFormDataPtr;
858 #else
859   bfp = GetObjectExtra (i);
860 #endif
861   if (bfp == NULL) return;
862   RetranslateCdRegionsEx (bfp->input_entityID, include_stop, no_stop_at_end_of_complete_cds);
863 }
864 
RetranslateCdRegionsNoStop(IteM i)865 extern void RetranslateCdRegionsNoStop (IteM i)
866 
867 {
868   RetranslateCdRegions (i, FALSE, FALSE);
869 }
870 
RetranslateCdRegionsDoStop(IteM i)871 extern void RetranslateCdRegionsDoStop (IteM i)
872 
873 {
874   RetranslateCdRegions (i, TRUE, FALSE);
875 }
876 
RetranslateCdRegionsNoStopExceptEndCompleteCDS(IteM i)877 extern void RetranslateCdRegionsNoStopExceptEndCompleteCDS (IteM i)
878 {
879   RetranslateCdRegions (i, TRUE, TRUE);
880 }
881 
882 
RetranslateForNoStop(SeqFeatPtr sfp,Pointer data)883 static void RetranslateForNoStop (SeqFeatPtr sfp, Pointer data)
884 {
885   CdRegionPtr  crp;
886   Uint1        new_frame = 0, i, orig_frame;
887   ByteStorePtr bs;
888   CharPtr      str;
889   Int4         lens [3];
890   Int4         max;
891   Boolean      retval = TRUE;
892 
893   if (sfp == NULL
894       || sfp->data.choice != SEQFEAT_CDREGION
895       || (crp = (CdRegionPtr) sfp->data.value.ptrvalue) == NULL) {
896     return;
897   }
898 
899   orig_frame = crp->frame;
900 
901   max = 0;
902   for (i = 1; i <= 3; i++) {
903     crp->frame = i;
904     bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
905     lens[i - 1] = BSLen (bs);
906     str = BSMerge (bs, NULL);
907     if (StringCSpn (str, "*") < lens[i - 1] - 1) {
908       lens[i - 1] = 0;
909     }
910     str = MemFree (str);
911     BSFree (bs);
912     if (lens[i - 1] > max) {
913       max = lens[i - 1];
914       new_frame = i;
915     }
916   }
917   for (i = 1; i <= 3; i++) {
918     if (lens [i - 1] == max && i != new_frame) {
919       retval = FALSE;
920     }
921   }
922   if (retval) {
923     crp->frame = new_frame;
924     RetranslateOneCDS (sfp, sfp->idx.entityID, TRUE, TRUE);
925   } else {
926     crp->frame = orig_frame;
927   }
928 }
929 
930 
RetranslateCdRegionsChooseFrameWithNoStopForEntityID(Uint2 entityID)931 NLM_EXTERN void RetranslateCdRegionsChooseFrameWithNoStopForEntityID (Uint2 entityID)
932 {
933   SeqEntryPtr  sep;
934 
935   sep = GetTopSeqEntryForEntityID (entityID);
936   WatchCursor();
937   Update();
938   VisitFeaturesInSep (sep, NULL, RetranslateForNoStop);
939   ArrowCursor ();
940   Update ();
941   ObjMgrSetDirtyFlag (entityID, TRUE);
942   ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
943 }
944 
945 
RetranslateCdRegionsChooseFrameWithNoStop(IteM i)946 NLM_EXTERN void RetranslateCdRegionsChooseFrameWithNoStop (IteM i)
947 {
948   BaseFormPtr  bfp;
949 
950 #ifdef WIN_MAC
951   bfp = currentFormDataPtr;
952 #else
953   bfp = GetObjectExtra (i);
954 #endif
955   if (bfp == NULL) return;
956   RetranslateCdRegionsChooseFrameWithNoStopForEntityID(bfp->input_entityID);
957 }
958 
959 
960 /*
961  * ApplyCodeBreakToCDS
962  */
963 
ApplyCodeBreakToCDS(SeqFeatPtr sfp,CharPtr codonStr,Uint1 aaNum)964 static Boolean ApplyCodeBreakToCDS (SeqFeatPtr sfp, CharPtr codonStr, Uint1 aaNum)
965 {
966   Uint1            aaChar;
967   SeqLocPtr        aaSlp;
968   Int4             aaPosition;
969   SeqPntPtr        aaSpp;
970   CharPtr          basePtr;
971   CharPtr          bases;
972   CodeBreakPtr     cbp;
973   CdRegionPtr      crp;
974   Int4             dnaLen;
975   SeqLocPtr        dnaSlp;
976   CodeBreakPtr     lastCbp;
977   SeqCodeTablePtr  sctp;
978   Int4             total;
979   Boolean          added_code_breaks = FALSE;
980 
981   if (sfp == NULL || codonStr == NULL)
982   {
983     return FALSE;
984   }
985 
986   /* Get the nucleotide sequence */
987 
988   dnaLen = SeqLocLen (sfp->location);
989   if (dnaLen < 1)
990     return FALSE;
991 
992   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
993 
994   bases = ReadCodingRegionBases (sfp->location, dnaLen, crp->frame, &total);
995 
996   /* Search for the selected codon in the */
997   /* nucleotide sequence.  If found, add  */
998   /* it as a codebreak.                   */
999 
1000   basePtr = bases;
1001   aaPosition = 0;
1002   while (basePtr[0] != '\0') {
1003     if (StringNCmp (basePtr, codonStr, 3) == 0) {
1004 
1005       /* Create a new seq point object with the aa location */
1006 
1007       aaSpp = SeqPntNew ();
1008       aaSpp->point  = aaPosition;
1009       aaSpp->strand = Seq_strand_plus;
1010       aaSpp->id = SeqLocId (sfp->product);
1011       aaSpp->fuzz   = NULL;
1012 
1013       /* Make a SeqLoc using the seq point */
1014 
1015       aaSlp = (SeqLocPtr) ValNodeNew (NULL);
1016       aaSlp->choice = SEQLOC_PNT;
1017       aaSlp->data.ptrvalue = (Pointer) aaSpp;
1018 
1019       /* Convert the seqloc to a DNA location */
1020 
1021       dnaSlp = aaLoc_to_dnaLoc (sfp, aaSlp);
1022 
1023       /* Create the code break using the DNA location */
1024 
1025       cbp = CodeBreakNew ();
1026       cbp->loc = dnaSlp;
1027       sctp = SeqCodeTableFind (Seq_code_ncbieaa);
1028       aaChar = (Uint1) GetSymbolForResidue (sctp, aaNum);
1029       cbp->aa.value.intvalue = aaChar;
1030       cbp->aa.choice = 1; /* ncbieaa */
1031 
1032       /* Insert the code break into the CDS's */
1033       /* existing list of code breaks.        */
1034 
1035       lastCbp = crp->code_break;
1036       if (lastCbp == NULL)
1037       {
1038 	      crp->code_break = cbp;
1039       }
1040       else
1041       {
1042         while (lastCbp->next != NULL)
1043         {
1044           lastCbp = lastCbp->next;
1045         }
1046 	      lastCbp->next = cbp;
1047 	      cbp->next = NULL;
1048       }
1049 
1050       added_code_breaks = TRUE;
1051     }
1052     basePtr += 3;
1053     aaPosition++;
1054   }
1055 
1056   return added_code_breaks;
1057 }
1058 
1059 /*---------------------------------------------------------------------*/
1060 /*                                                                     */
1061 /* ApplyCodeBreak_FeatureCallback () -- Called for each CDS feature in */
1062 /*                                      a Bioseq.  Checks for any      */
1063 /*                                      nucleotide triplets that match */
1064 /*                                      the one in the given code      */
1065 /*                                      break and sets a code break    */
1066 /*                                      for each one that is found.    */
1067 /*                                                                     */
1068 /*---------------------------------------------------------------------*/
1069 
ApplyCodeBreak_FeatureCallback(SeqFeatPtr sfp,SeqMgrFeatContextPtr fcontext)1070 static Boolean LIBCALLBACK ApplyCodeBreak_FeatureCallback (SeqFeatPtr sfp,
1071 					SeqMgrFeatContextPtr fcontext)
1072 {
1073   Uint1            aaNum;
1074   CodeBreakFormPtr cbfp;
1075   Char             codonStr [4];
1076   Int2             i;
1077 
1078   cbfp = (CodeBreakFormPtr) fcontext->userdata;
1079 
1080 
1081   /* Get the selected Amino Acid and codon triplet */
1082 
1083   GetTitle (cbfp->codonText, codonStr, sizeof (codonStr));
1084   for (i = 0; i < 3; i++)
1085     codonStr [i] = TO_UPPER (codonStr [i]);
1086 
1087   aaNum = (Uint1) GetValue (cbfp->aminoAcidPopup);
1088   aaNum += 63;
1089 
1090   /*
1091   if (aaNum >= 74)
1092   {
1093   	aaNum++;
1094   }
1095   if (aaNum >= 79)
1096   {
1097   	aaNum++;
1098   }
1099   */
1100 
1101   if (ApplyCodeBreakToCDS (sfp, codonStr, aaNum))
1102   {
1103     /* Retranslate the CDS */
1104 
1105     RetranslateOneCDS (sfp, fcontext->entityID, TRUE, FALSE);
1106 
1107   }
1108 
1109   /* Return TRUE to continue on to the next CDS feature */
1110 
1111   return TRUE;
1112 }
1113 
1114 /*---------------------------------------------------------------------*/
1115 /*                                                                     */
1116 /* ApplyCodeBreak_BioseqCallback () -- Called by SeqMgrExploreBioseqs  */
1117 /*                                     for each Bioseq.  Searches the  */
1118 /*                                     Bioseq for CDS features and adds*/
1119 /*                                     the given code break to any     */
1120 /*                                     found.                          */
1121 /*                                                                     */
1122 /*---------------------------------------------------------------------*/
1123 
ApplyCodeBreak_BioseqCallback(BioseqPtr bsp,SeqMgrBioseqContextPtr bcontext)1124 static Boolean LIBCALLBACK ApplyCodeBreak_BioseqCallback (BioseqPtr bsp,
1125 					 SeqMgrBioseqContextPtr bcontext)
1126 {
1127   Boolean featureFilterArray [SEQFEAT_MAX];
1128 
1129   /* Set up to explore only CDS features */
1130 
1131   MemSet ((Pointer) (featureFilterArray),
1132 	  (int) FALSE,
1133 	  SEQFEAT_MAX);
1134 
1135   featureFilterArray[SEQFEAT_CDREGION] = TRUE;
1136 
1137   /* Explore the Bioseq's CDS features, marking the */
1138   /* ones with internal stop codons as pseudo.      */
1139 
1140   SeqMgrExploreFeatures (bsp, bcontext->userdata,
1141 			 ApplyCodeBreak_FeatureCallback, NULL,
1142 			 featureFilterArray, NULL);
1143 
1144   /* Return TRUE to continue on to the next Bioseq */
1145 
1146   return TRUE;
1147 }
1148 
1149 /*---------------------------------------------------------------------*/
1150 /*                                                                     */
1151 /* DoAddCodeBreak_Callback () -- Called when the 'Apply' button is     */
1152 /*                               pressed in the "Add Code Break"       */
1153 /*                               window.  Adds the entered code break  */
1154 /*                               to all CDS features.                  */
1155 /*                                                                     */
1156 /*---------------------------------------------------------------------*/
1157 
DoAddCodeBreak_Callback(ButtoN b)1158 static void DoAddCodeBreak_Callback (ButtoN b)
1159 {
1160   CodeBreakFormPtr  cbfp;
1161 
1162   cbfp = (CodeBreakFormPtr) GetObjectExtra (b);
1163 
1164   /* Change to the "working" cursor */
1165 
1166   Hide (cbfp->form);
1167   WatchCursor ();
1168   Update ();
1169 
1170   /* Visit all the Bioseqs, where we will */
1171   /* then explore their CDS features.     */
1172 
1173   SeqMgrExploreBioseqs (cbfp->input_entityID, NULL, (Pointer) cbfp,
1174 			ApplyCodeBreak_BioseqCallback, TRUE, FALSE, TRUE);
1175 
1176   /* Restore the cursor and force an update */
1177 
1178   ArrowCursor ();
1179   Update ();
1180   ObjMgrSetDirtyFlag (cbfp->input_entityID, TRUE);
1181   ObjMgrSendMsg (OM_MSG_UPDATE, cbfp->input_entityID, 0, 0);
1182   Remove (cbfp->form);
1183 }
1184 
1185 /*---------------------------------------------------------------------*/
1186 /*                                                                     */
1187 /* PopulateAAPopup () -- Creates a popup list of amino acids.          */
1188 /*                                                                     */
1189 /*     NOTE : This function is identical to (and identically named as) */
1190 /*            a function in cdrgn.c                                    */
1191 /*                                                                     */
1192 /*---------------------------------------------------------------------*/
1193 
PopulateAAPopup(PopuP AAitem)1194 static void PopulateAAPopup (PopuP AAitem)
1195 
1196 {
1197   Char             ch;
1198   Uint1            first;
1199   Uint1            i;
1200   Char             item [77];
1201   Uint1            last;
1202   SeqCodeTablePtr  sctp;
1203   CharPtr          str;
1204 
1205   sctp = SeqCodeTableFind (Seq_code_ncbieaa);
1206   first = FirstResidueInCode (sctp);
1207   last = LastResidueInCode (sctp);
1208   PopupItem (AAitem, " ");
1209   for (i = 65; i <= last; i++) {
1210     /*
1211     if (i == 74 || i == 79) {
1212       continue;
1213     }
1214     */
1215     ch = GetSymbolForResidue (sctp, i);
1216     str = (CharPtr) GetNameForResidue (sctp, i);
1217     sprintf (item, "%c    %s", ch, str);
1218     PopupItem (AAitem, item);
1219   }
1220   SetValue (AAitem, 1);
1221 }
1222 
1223 /*---------------------------------------------------------------------*/
1224 /*                                                                     */
1225 /* IsLegalCodon () - Determines if a three base string is a legal      */
1226 /*                   codon.                                            */
1227 /*                                                                     */
1228 /*---------------------------------------------------------------------*/
1229 
IsLegalCodon(CharPtr codonStr)1230 static Boolean IsLegalCodon (CharPtr codonStr)
1231 {
1232   Int2 i;
1233   Char baseChar;
1234 
1235   /* Only allow three characters */
1236 
1237   if (StringLen (codonStr) > 3)
1238     return FALSE;
1239 
1240   /* Allow only the character A,C,G,T,U and */
1241   /* convert the U to a T.                  */
1242 
1243   i = 0;
1244   while (i < 3) {
1245 
1246     if (codonStr [i] == '\0')
1247       break;
1248 
1249     baseChar = codonStr [i];
1250 
1251     if (StringChr ("acgtuACGTU", baseChar) == NULL)
1252       return FALSE;
1253     if ('U' == baseChar)
1254       codonStr [i] = 'T';
1255     else if ('u' == baseChar)
1256       codonStr [i] = 't';
1257 
1258     i++;
1259   }
1260 
1261   /* If we made it this far, it's a valid codon */
1262 
1263   return TRUE;
1264 }
1265 
1266 /*---------------------------------------------------------------------*/
1267 /*                                                                     */
1268 /* CodonText_Callback () -- Called whenever a keystoke is entered in   */
1269 /*                          Codon text field.  Validates to see if the */
1270 /*                          keystroke should be allowed.               */
1271 /*                                                                     */
1272 /*---------------------------------------------------------------------*/
1273 
CodonText_Callback(TexT codonText)1274 static void CodonText_Callback (TexT codonText)
1275 
1276 {
1277   CodeBreakFormPtr  cbfp;
1278   Int2              aaNum;
1279   Char              newCodonStr [5];
1280 
1281   /* Get the currect code break data */
1282 
1283   cbfp = (CodeBreakFormPtr) GetObjectExtra (codonText);
1284   if (cbfp == NULL)
1285     return;
1286 
1287   /* If the new codon string is not legal */
1288   /* then reset to the previous text.     */
1289 
1290   GetTitle (codonText, newCodonStr, sizeof (newCodonStr));
1291 
1292   if (!IsLegalCodon (newCodonStr))
1293     StringCpy (newCodonStr, cbfp->currentCodonStr);
1294   else
1295     StringCpy (cbfp->currentCodonStr, newCodonStr);
1296 
1297   SafeSetTitle (cbfp->codonText, newCodonStr);
1298 
1299   /* Only enable the accept button if */
1300   /* we have a full codon.            */
1301 
1302   if (StringLen (newCodonStr) != 3) {
1303     SafeDisable (cbfp->acceptButton);
1304     return;
1305   }
1306 
1307   /* See if an amino acid has been selected yet */
1308 
1309   aaNum = GetValue (cbfp->aminoAcidPopup);
1310   if (aaNum <= 1) {
1311     SafeDisable (cbfp->acceptButton);
1312     return;
1313   }
1314 
1315   /* If we made it this far then we have both a codon and */
1316   /* an amino acid, so enable the accept button.          */
1317 
1318   SafeEnable (cbfp->acceptButton);
1319 }
1320 
1321 /*---------------------------------------------------------------------*/
1322 /*                                                                     */
1323 /* SelectAminoAcid_Callback () -- Called whenever a new amino acid is  */
1324 /*                                selected in the Amino Acid Popup.    */
1325 /*                                Toggles 'Accept' button base on      */
1326 /*                                current state.                       */
1327 /*                                                                     */
1328 /*---------------------------------------------------------------------*/
1329 
SelectAminoAcid_Callback(PopuP p)1330 static void SelectAminoAcid_Callback (PopuP p)
1331 {
1332   CodeBreakFormPtr  cbfp;
1333   Char              codonStr [4];
1334   Int2              aaNum;
1335 
1336   /* Get the currect code break data */
1337 
1338   cbfp = (CodeBreakFormPtr) GetObjectExtra (p);
1339   if (cbfp == NULL)
1340     return;
1341 
1342   /* Only enable the accept button if */
1343   /* we have a full codon.            */
1344 
1345   GetTitle (cbfp->codonText, codonStr, sizeof (codonStr));
1346   if (StringLen (codonStr) != 3) {
1347     SafeDisable (cbfp->acceptButton);
1348     return;
1349   }
1350 
1351   /* Get the newly selected amino acid */
1352 
1353   aaNum = GetValue (cbfp->aminoAcidPopup);
1354 
1355   /* If an amino acid is selected then */
1356   /* enable the accept button.         */
1357 
1358   if (aaNum > 1)
1359     SafeEnable (cbfp->acceptButton);
1360   else
1361     SafeDisable (cbfp->acceptButton);
1362 }
1363 
1364 /*---------------------------------------------------------------------*/
1365 /*                                                                     */
1366 /* AddGlobalCodeBreak () -- Gets a nucleotide triplet and an amino     */
1367 /*                          acid from the user and adds them as        */
1368 /*                          codebreaks for all CDS features.           */
1369 /*                                                                     */
1370 /*---------------------------------------------------------------------*/
1371 
1372 extern void AddGlobalCodeBreak (IteM i);
AddGlobalCodeBreak(IteM i)1373 extern void AddGlobalCodeBreak (IteM i)
1374 
1375 {
1376   BaseFormPtr      bfp;
1377   WindoW           breakWin;
1378   GrouP            mainGroup;
1379   GrouP            buttGroup;
1380   CodeBreakFormPtr cbfp;
1381 
1382   /* Get the current state of things */
1383 
1384 #ifdef WIN_MAC
1385   bfp = currentFormDataPtr;
1386 #else
1387   bfp = GetObjectExtra (i);
1388 #endif
1389   if (bfp == NULL)
1390     return;
1391 
1392   cbfp = (CodeBreakFormPtr) MemNew (sizeof (EvidenceFormData));
1393 
1394   /* Create a window to get the codon and */
1395   /* the Amino acid from the user.        */
1396 
1397   breakWin = FixedWindow (-50, -33, -10, -10,
1398 			  "Add Code Break", StdCloseWindowProc);
1399   SetObjectExtra (breakWin, cbfp, StdCleanupFormProc);
1400   cbfp->form = (ForM) breakWin;
1401   cbfp->formmessage = NULL;
1402   cbfp->input_entityID = bfp->input_entityID;
1403 
1404   mainGroup = HiddenGroup (breakWin, -2, 0, NULL);
1405 
1406   /* Create a text entry box for the nucl. codon */
1407 
1408   StaticPrompt (mainGroup, "Triplet Codon", 0, popupMenuHeight,
1409 		programFont, 'l');
1410   cbfp->codonText = DialogText (mainGroup, "", 3, CodonText_Callback);
1411   SetObjectExtra (cbfp->codonText, cbfp, NULL);
1412   cbfp->currentCodonStr [0] = '\0';
1413 
1414   /* Add a Popup list of Amino Acids */
1415 
1416   StaticPrompt (mainGroup, "Amino Acid", 0, popupMenuHeight,
1417 		programFont, 'l');
1418   cbfp->aminoAcidPopup = PopupList (mainGroup, TRUE,
1419 				    SelectAminoAcid_Callback);
1420   PopulateAAPopup (cbfp->aminoAcidPopup);
1421   SetObjectExtra (cbfp->aminoAcidPopup, cbfp, NULL);
1422 
1423   /* Add Accept and Cancel buttons */
1424 
1425   buttGroup = HiddenGroup (breakWin, 2, 0, NULL);
1426   cbfp->acceptButton = DefaultButton (buttGroup, "Accept",
1427 				   DoAddCodeBreak_Callback);
1428   SetObjectExtra (cbfp->acceptButton, cbfp, NULL);
1429   SafeDisable (cbfp->acceptButton);
1430   PushButton (buttGroup, "Cancel", StdCancelButtonProc);
1431 
1432   /* Line things up and display the window */
1433 
1434   AlignObjects (ALIGN_CENTER, (HANDLE) mainGroup, (HANDLE) buttGroup, NULL);
1435   RealizeWindow (breakWin);
1436   Show (breakWin);
1437   Update ();
1438 
1439 }
1440 
ParseCodonQualToCodeBreakCallback(SeqFeatPtr sfp,Pointer userdata)1441 static void ParseCodonQualToCodeBreakCallback (SeqFeatPtr sfp, Pointer userdata)
1442 {
1443   SeqCodeTablePtr sctp;
1444   GBQualPtr       gqual, prev_qual = NULL, next_qual;
1445   CharPtr         cp;
1446   Char            codon_text[4];
1447   Char            symbol_text [4];
1448   Uint1           aaNum;
1449   Int4            i;
1450   Boolean         converted_qual;
1451 
1452   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION || userdata == NULL)
1453   {
1454     return;
1455   }
1456 
1457   sctp = (SeqCodeTablePtr) userdata;
1458 
1459   for (gqual = sfp->qual; gqual != NULL; gqual = next_qual)
1460   {
1461     next_qual = gqual->next;
1462     converted_qual = FALSE;
1463     if (StringCmp (gqual->qual, "codon") == 0)
1464     {
1465       cp = StringSearch (gqual->val, "seq:\"");
1466       if (cp != NULL)
1467       {
1468         cp += 5;
1469         StringNCpy (codon_text, cp, 3);
1470         codon_text [3] = 0;
1471         for (i = 0; i < 3; i++)
1472           codon_text [i] = TO_UPPER (codon_text [i]);
1473 
1474         cp = StrChr (cp, ':');
1475         if (cp != NULL)
1476         {
1477           cp++;
1478           StringNCpy (symbol_text, cp, 3);
1479           symbol_text [3] = 0;
1480           aaNum = FindResidueByName (symbol_text, sctp);
1481           if (ApplyCodeBreakToCDS (sfp, codon_text, aaNum))
1482           {
1483             /* Retranslate the CDS */
1484 
1485             RetranslateOneCDS (sfp, sfp->idx.entityID, TRUE, FALSE);
1486 
1487             /* remove the codon qual */
1488             if (prev_qual == NULL)
1489             {
1490               sfp->qual = gqual->next;
1491             }
1492             else
1493             {
1494               prev_qual->next = gqual->next;
1495             }
1496             gqual->next = NULL;
1497             GBQualFree (gqual);
1498             converted_qual = TRUE;
1499           }
1500         }
1501       }
1502     }
1503     if (!converted_qual)
1504     {
1505       prev_qual = gqual;
1506     }
1507   }
1508 }
1509 
ParseCodonQualToCodeBreak(IteM i)1510 extern void ParseCodonQualToCodeBreak (IteM i)
1511 {
1512   BaseFormPtr      bfp;
1513   SeqEntryPtr      sep;
1514   SeqCodeTablePtr  sctp;
1515 
1516 #ifdef WIN_MAC
1517   bfp = currentFormDataPtr;
1518 #else
1519   bfp = GetObjectExtra (i);
1520 #endif
1521   if (bfp == NULL) return;
1522 
1523   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1524   if (sep == NULL) return;
1525 
1526   WatchCursor ();
1527   Update ();
1528 
1529   sctp = SeqCodeTableFind (Seq_code_ncbieaa);
1530 
1531   VisitFeaturesInSep (sep, sctp, ParseCodonQualToCodeBreakCallback);
1532   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1533   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1534   ArrowCursor ();
1535   Update ();
1536 }
1537 
SqnGetBioseqGivenSeqLoc(SeqLocPtr slp,Uint2 entityID)1538 static BioseqPtr SqnGetBioseqGivenSeqLoc (SeqLocPtr slp, Uint2 entityID)
1539 
1540 {
1541   BioseqPtr    bsp;
1542   SeqEntryPtr  sep;
1543   SeqIdPtr     sip;
1544   SeqLocPtr    tmp;
1545 
1546   if (slp == NULL) return NULL;
1547   bsp = NULL;
1548   sip = SeqLocId (slp);
1549   if (sip != NULL) {
1550     bsp = BioseqFind (sip);
1551   } else {
1552     tmp = SeqLocFindNext (slp, NULL);
1553     if (tmp != NULL) {
1554       sip = SeqLocId (tmp);
1555       if (sip != NULL) {
1556         bsp = BioseqFind (sip);
1557         if (bsp != NULL) {
1558           sep = SeqMgrGetSeqEntryForData (bsp);
1559           entityID = ObjMgrGetEntityIDForChoice (sep);
1560           bsp = GetBioseqGivenSeqLoc (slp, entityID);
1561         }
1562       }
1563     }
1564   }
1565   return bsp;
1566 }
1567 
GetScore(ScorePtr score)1568 static Int4 GetScore (ScorePtr score)
1569 
1570 {
1571   ObjectIdPtr  id;
1572 
1573   while (score != NULL) {
1574     id = score->id;
1575     if (id != NULL) {
1576       if (StringICmp (id->str, "score") == 0) {
1577         if (score->choice == 1) {
1578           return (score->value.intvalue);
1579         }
1580       }
1581     }
1582     score = score->next;
1583   }
1584   return 0;
1585 }
1586 
FindScore(SeqAlignPtr align)1587 static Int4 FindScore (SeqAlignPtr align)
1588 
1589 {
1590   if (align == NULL) return 0;
1591   if (align->score != NULL) {
1592     return GetScore (align->score);
1593   }
1594   return 0;
1595 }
1596 
SortByScoreCallback(VoidPtr ptr1,VoidPtr ptr2)1597 static int LIBCALLBACK SortByScoreCallback (VoidPtr ptr1, VoidPtr ptr2)
1598 
1599 {
1600   SeqAlignPtr   sap1;
1601   SeqAlignPtr   sap2;
1602   Int4          score1;
1603   Int4          score2;
1604 
1605   if (ptr1 != NULL && ptr2 != NULL) {
1606     sap1 = *((SeqAlignPtr PNTR) ptr1);
1607     sap2 = *((SeqAlignPtr PNTR) ptr2);
1608     if (sap1 != NULL && sap2 != NULL) {
1609       score1 = FindScore (sap1);
1610       score2 = FindScore (sap2);
1611       if (score1 < score2) {
1612         return 1;
1613       } else if (score1 > score2) {
1614         return -1;
1615       } else {
1616         return 0;
1617       }
1618     } else {
1619       return 0;
1620     }
1621   } else {
1622     return 0;
1623   }
1624 }
1625 
SortBySeqAlignScore(SeqAlignPtr list)1626 static SeqAlignPtr SortBySeqAlignScore (SeqAlignPtr list)
1627 
1628 {
1629   SeqAlignPtr  align;
1630   Int4         count, i;
1631   SeqAlignPtr  PNTR head;
1632 
1633   if (list == NULL) return 0;
1634   count = 0;
1635   for (align = list; align != NULL; align = align->next) {
1636     count++;
1637   }
1638   head = MemNew (sizeof (SeqAlignPtr) * (size_t) (count + 1));
1639   if (head == NULL) return 0;
1640   for (align = list, i = 0; align != NULL && i < count; i++) {
1641     head [i] = align;
1642     align = align->next;
1643   }
1644   HeapSort (head, (size_t) count, sizeof (SeqAlignPtr), SortByScoreCallback);
1645   for (i = 0; i < count; i++) {
1646     align = head [i];
1647     align->next = head [i + 1];
1648   }
1649   list = head [0];
1650   MemFree (head);
1651   return list;
1652 }
1653 
TakeTop10Alignments(SeqAnnotPtr sap)1654 static void TakeTop10Alignments (SeqAnnotPtr sap)
1655 
1656 {
1657   SeqAlignPtr  align;
1658   MsgAnswer    ans;
1659   Int2         count;
1660   SeqAlignPtr  next;
1661 
1662   if (sap == NULL || sap->type != 2 || sap->data == NULL) return;
1663   count = 0;
1664   for (align = (SeqAlignPtr) sap->data; align != NULL; align = align->next) {
1665     count++;
1666   }
1667   if (count <= 10) return;
1668   ans = Message (MSG_YN, "Do you want to take only the top 10 (out of %d) alignments?", (int) count);
1669   if (ans == ANS_NO) return;
1670   sap->data = SortBySeqAlignScore ((SeqAlignPtr) sap->data);
1671   for (align = (SeqAlignPtr) sap->data, count = 0; align != NULL && count < 10; align = align->next) {
1672     count++;
1673   }
1674   next = align->next;
1675   align->next = NULL;
1676   align = next;
1677   while (align != NULL) {
1678     next = align->next;
1679     align->next = NULL;
1680     SeqAlignFree (align);
1681     align = next;
1682   }
1683 }
1684 
1685 
LookupPublications(SeqAnnotPtr sap)1686 static void LookupPublications (SeqAnnotPtr sap)
1687 
1688 {
1689   MonitorPtr  mon = NULL;
1690   PubdescPtr  pdp;
1691   SeqFeatPtr  sfp;
1692   ValNodePtr  tmp;
1693   Int4        uid;
1694   Boolean     usingMedarch = FALSE;
1695   ValNodePtr  vnp;
1696 
1697   if (! useMedarch) return;
1698   if (sap == NULL || sap->type != 1) return;
1699   for (sfp = (SeqFeatPtr) sap->data; sfp != NULL; sfp = sfp->next) {
1700     if (sfp->data.choice == SEQFEAT_PUB) {
1701       pdp = (PubdescPtr) sfp->data.value.ptrvalue;
1702       if (pdp != NULL) {
1703         vnp = pdp->pub;
1704         if (vnp != NULL && vnp->next == NULL) {
1705           if (vnp->choice == PUB_Muid || vnp->choice == PUB_PMid) {
1706             if (! usingMedarch) {
1707               WatchCursor ();
1708               mon = MonitorStrNewEx ("Processing Publications", 40, FALSE);
1709               MonitorStrValue (mon, "Connecting to MedArch");
1710               Update ();
1711               if (MedArchInit ()) {
1712                 usingMedarch = TRUE;
1713               } else {
1714                 MonitorFree (mon);
1715                 ArrowCursor ();
1716                 Update ();
1717                 Message (MSG_POST, "Unable to connect to MedArch");
1718                 return;
1719               }
1720             }
1721           }
1722           tmp = NULL;
1723           if (vnp->choice == PUB_Muid) {
1724             uid = vnp->data.intvalue;
1725             tmp = MedArchGetPub (uid);
1726           } else if (vnp->choice == PUB_PMid) {
1727             uid = vnp->data.intvalue;
1728             tmp = MedArchGetPubPmId (uid);
1729           }
1730           if (tmp != NULL) {
1731             MedlineToISO (tmp);
1732             tmp->next = vnp;
1733             pdp->pub = tmp;
1734           }
1735         }
1736       }
1737     }
1738   }
1739   if (usingMedarch) {
1740     MonitorStrValue (mon, "Closing MedArch");
1741     Update ();
1742     MedArchFini ();
1743     MonitorFree (mon);
1744     ArrowCursor ();
1745     Update ();
1746   }
1747 }
1748 
PromotePubs(SeqFeatPtr first,BioseqPtr bsp,Uint2 entityID)1749 static void PromotePubs (SeqFeatPtr first, BioseqPtr bsp, Uint2 entityID)
1750 
1751 {
1752   MsgAnswer    ans;
1753   Boolean      asked = FALSE;
1754   PubdescPtr   pdp;
1755   SeqDescrPtr  sdp;
1756   SeqEntryPtr  sep;
1757   SeqFeatPtr   sfp;
1758   ValNode      vn;
1759 
1760   MemSet ((Pointer) &vn, 0, sizeof (ValNode));
1761   vn.choice = SEQLOC_WHOLE;
1762   vn.data.ptrvalue = (Pointer) SeqIdFindBest (bsp->id, 0);
1763   vn.next = NULL;
1764 
1765   for (sfp = first; sfp != NULL; sfp = sfp->next) {
1766     if (sfp->data.choice == SEQFEAT_PUB) {
1767       if (SeqLocCompare (sfp->location, &vn) == SLC_A_EQ_B) {
1768         if (! asked) {
1769           ans = Message (MSG_YN, "Do you wish to convert full-length publication features to descriptors?");
1770           if (ans == ANS_NO) return;
1771           asked = TRUE;
1772         }
1773       }
1774     }
1775   }
1776 
1777   sep = GetBestTopParentForData (entityID, bsp);
1778   for (sfp = first; sfp != NULL; sfp = sfp->next) {
1779     if (sfp->data.choice == SEQFEAT_PUB) {
1780       if (SeqLocCompare (sfp->location, &vn) == SLC_A_EQ_B) {
1781         sfp->idx.deleteme = TRUE;
1782         sfp->data.choice = SEQFEAT_COMMENT;
1783         pdp = (PubdescPtr) sfp->data.value.ptrvalue;
1784         sfp->data.value.ptrvalue = NULL;
1785         sdp = CreateNewDescriptor (sep, Seq_descr_pub);
1786         if (sdp != NULL) {
1787           sdp->data.ptrvalue = (Pointer) pdp;
1788         }
1789       }
1790     }
1791   }
1792 
1793   DeleteMarkedObjects (entityID, 0, NULL);
1794 }
1795 
SmartAttachSeqAnnotToSeqEntry(Uint2 entityID,SeqAnnotPtr sap,ValNodePtr PNTR err_list)1796 extern Uint2 SmartAttachSeqAnnotToSeqEntry (Uint2 entityID, SeqAnnotPtr sap, ValNodePtr PNTR err_list)
1797 
1798 {
1799   BioseqPtr      bsp;
1800   Int2           genCode;
1801   SeqEntryPtr    oldscope;
1802   OMProcControl  ompc;
1803   SeqEntryPtr    sep;
1804   SeqFeatPtr     sfp = NULL;
1805 
1806   if (sap == NULL) return entityID;
1807   bsp = GetBioseqReferencedByAnnot (sap, entityID);
1808   if (bsp == NULL) {
1809     oldscope = SeqEntrySetScope (NULL);
1810     if (oldscope != NULL) {
1811       bsp = GetBioseqReferencedByAnnot (sap, entityID);
1812       SeqEntrySetScope (oldscope);
1813     }
1814   }
1815   if (bsp != NULL) {
1816     sep = SeqMgrGetSeqEntryForData (bsp);
1817     entityID = ObjMgrGetEntityIDForChoice (sep);
1818     if (sap->type == 1) {
1819       sfp = (SeqFeatPtr) sap->data;
1820       sep = GetBestTopParentForData (entityID, bsp);
1821       genCode = SeqEntryToGeneticCode (sep, NULL, NULL, 0);
1822       SetEmptyGeneticCodes (sap, genCode);
1823       LookupPublications (sap);
1824     } else if (sap->type == 2) {
1825       TakeTop10Alignments (sap);
1826     }
1827     MemSet ((Pointer) &ompc, 0, sizeof (OMProcControl));
1828     ompc.input_entityID = entityID;
1829     ompc.input_itemID = GetItemIDGivenPointer (entityID, OBJ_BIOSEQ, (Pointer) bsp);
1830     ompc.input_itemtype = OBJ_BIOSEQ;
1831     ompc.output_itemtype = OBJ_SEQANNOT;
1832     ompc.output_data = (Pointer) sap;
1833     if (! AttachDataForProc (&ompc, FALSE)) {
1834       if (err_list == NULL) {
1835         Message (MSG_ERROR, "SmartAttachSeqAnnotToSeqEntry failed");
1836       } else {
1837         ValNodeAddPointer  (err_list, 0, StringSave ("SmartAttachSeqAnnotToSeqEntry failed"));
1838       }
1839     } else if (sfp != NULL) {
1840       PromoteXrefs (sfp, bsp, entityID);
1841       PromotePubs (sfp, bsp, entityID);
1842     }
1843   } else {
1844     if (err_list == NULL) {
1845       Message (MSG_ERROR, "Feature table identifiers do not match record");
1846     } else {
1847       ValNodeAddPointer (err_list, 0, StringSave ("Feature table identifiers do not match record"));
1848     }
1849   }
1850   return entityID;
1851 }
1852 
1853 typedef struct removeformdata {
1854   FEATURE_FORM_BLOCK
1855 
1856   Boolean        is_feature;
1857   LisT           objlist;
1858   TexT           findthis;
1859   TexT           fromTxt;
1860   TexT           toTxt;
1861   Uint2          itemtype;
1862   Uint2          subtype;
1863   CharPtr        extra_string;
1864   ValNodePtr     head;
1865   Boolean        stringfound;
1866   Char           findStr [128];
1867   Boolean        take_action_when_string_present;
1868   GrouP          string_constraint_type;
1869   ButtoN         case_insensitive;
1870   Int4           from;
1871   Int4           to;
1872   ValNodePtr     bsplist;
1873   ValNodePtr     bssplist;
1874 } RemoveFormData, PNTR RemoveFormPtr;
1875 
ObjectInRange(SeqFeatPtr sfp,Int4 from,Int4 to)1876 static Boolean ObjectInRange (SeqFeatPtr sfp, Int4 from, Int4 to)
1877 
1878 {
1879   SeqMgrFeatContext  context;
1880 
1881   if (sfp == NULL || from < 0 || to < 0) return TRUE;
1882   if (SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL, 0, 0, sfp, &context) == sfp) {
1883     if (context.left > to) return FALSE;
1884     if (context.right < from) return FALSE;
1885   }
1886   return TRUE;
1887 }
1888 
1889 
RemoveFeatureCallback(SeqFeatPtr sfp,Pointer userdata)1890 static void RemoveFeatureCallback (SeqFeatPtr sfp, Pointer userdata)
1891 {
1892   RemoveFormPtr rfp;
1893   SeqIdPtr      sip;
1894   BioseqPtr     productbsp, productcdna;
1895   BioseqSetPtr  productnps;
1896 
1897   if (sfp == NULL || userdata == NULL) return;
1898 
1899   rfp = (RemoveFormPtr) userdata;
1900   if (rfp == NULL) return;
1901   if (sfp->idx.subtype == rfp->subtype ||
1902       (rfp->subtype == FEATDEF_IMP && IsRealImpFeat (sfp->idx.subtype)) ||
1903       rfp->subtype == ALL_FEATURES)
1904   {
1905     if ((rfp->from == -1 && rfp->to == -1) || ObjectInRange (sfp, rfp->from, rfp->to))
1906     {
1907       if (sfp->data.choice == SEQFEAT_CDREGION)
1908       {
1909         if (sfp->product != NULL)
1910         {
1911           sip = SeqLocId (sfp->product);
1912           if (sip != NULL)
1913           {
1914             productbsp = BioseqFind (sip);
1915             if (productbsp != NULL)
1916             {
1917               ValNodeAddPointer (&(rfp->bsplist), 0, (Pointer) productbsp);
1918             }
1919           }
1920         }
1921       }
1922       else if (sfp->data.choice == SEQFEAT_RNA)
1923       {
1924         if (sfp->product != NULL)
1925         {
1926           sip = SeqLocId (sfp->product);
1927           if (sip != NULL)
1928           {
1929             productcdna = BioseqFind (sip);
1930             if (productcdna != NULL && productcdna->idx.parenttype == OBJ_BIOSEQSET)
1931             {
1932               productnps = (BioseqSetPtr) productcdna->idx.parentptr;
1933               if (productnps != NULL && productnps->_class == BioseqseqSet_class_nuc_prot)
1934               {
1935                 ValNodeAddPointer (&(rfp->bssplist), 0, (Pointer) productnps);
1936               }
1937             }
1938           }
1939         }
1940       }
1941       sfp->idx.deleteme = TRUE;
1942     }
1943   }
1944 }
1945 
RemoveFeatures(SeqEntryPtr sep,RemoveFormPtr rfp)1946 static void RemoveFeatures (SeqEntryPtr sep, RemoveFormPtr rfp)
1947 {
1948   FeaturesWithTextData fd;
1949   Char           str [32];
1950   Int4           swap;
1951   long int       val;
1952 
1953   GetTitle (rfp->findthis, rfp->findStr, sizeof (rfp->findStr) - 1);
1954   fd.search_text = rfp->findStr;
1955   fd.no_text = StringHasNoText (rfp->findStr);
1956   fd.seqFeatChoice = 0;
1957   fd.featDefChoice = 0;
1958   fd.case_insensitive = GetStatus (rfp->case_insensitive);
1959   fd.whole_word = FALSE;
1960   fd.act_when_string_not_present = ! rfp->take_action_when_string_present;
1961   fd.userdata = rfp;
1962   fd.callback = RemoveFeatureCallback;
1963   GetTitle (rfp->fromTxt, str, sizeof (str) - 1);
1964   if ((! StringHasNoText (str)) && sscanf (str, "%ld", &val) == 1 && val >= 0) {
1965     rfp->from = (Int4) val;
1966   } else {
1967     rfp->from = -1;
1968   }
1969   GetTitle (rfp->toTxt, str, sizeof (str) - 1);
1970   if ((! StringHasNoText (str)) && sscanf (str, "%ld", &val) == 1 && val >= 0) {
1971     rfp->to = (Int4) val;
1972   } else {
1973     rfp->to = -1;
1974   }
1975   if (rfp->from > rfp->to) {
1976     swap = rfp->from;
1977     rfp->from = rfp->to;
1978     rfp->to = swap;
1979   }
1980   OperateOnSeqEntryFeaturesWithText (sep, &fd);
1981   DeleteMarkedObjects (rfp->input_entityID, OBJ_SEQENTRY, (Pointer) sep);
1982 }
1983 
1984 
IsUserObjectType(SeqDescrPtr sdp,CharPtr string)1985 static Boolean IsUserObjectType (SeqDescrPtr sdp, CharPtr string)
1986 {
1987   UserObjectPtr uop;
1988   ObjectIdPtr   oip;
1989 
1990   if (sdp == NULL || sdp->choice != Seq_descr_user) return FALSE;
1991   if (StringHasNoText (string)) return TRUE;
1992 
1993   uop = (UserObjectPtr) sdp->data.ptrvalue;
1994   if (uop == NULL) return FALSE;
1995   oip = uop->type;
1996   if (oip == NULL || StringICmp (oip->str, string) != 0) return FALSE;
1997   return TRUE;
1998 }
1999 
2000 
RemoveDescriptorCallback(SeqDescrPtr sdp,Pointer userdata)2001 static void RemoveDescriptorCallback (SeqDescrPtr sdp, Pointer userdata)
2002 {
2003   ObjValNodePtr ovp;
2004   RemoveFormPtr rfp;
2005 
2006   if (sdp == NULL || userdata == NULL || sdp->extended == 0) return;
2007   rfp = (RemoveFormPtr) userdata;
2008   if (rfp == NULL) return;
2009 
2010   ovp = (ObjValNodePtr) sdp;
2011 
2012   if (sdp->choice == rfp->subtype)
2013   {
2014     if (sdp->choice != Seq_descr_user || IsUserObjectType (sdp, rfp->extra_string)) {
2015       ovp->idx.deleteme = TRUE;
2016     }
2017   }
2018 }
2019 
RemoveDescriptors(SeqEntryPtr sep,RemoveFormPtr rfp)2020 static void RemoveDescriptors (SeqEntryPtr sep, RemoveFormPtr rfp)
2021 {
2022   DescriptorsWithTextData dd;
2023   Char                    str [32];
2024   Int4                    swap;
2025   long int                val;
2026 
2027   GetTitle (rfp->findthis, rfp->findStr, sizeof (rfp->findStr) - 1);
2028   dd.search_text = rfp->findStr;
2029   dd.no_text = StringHasNoText (rfp->findStr);
2030   dd.case_insensitive = GetStatus (rfp->case_insensitive);
2031   dd.whole_word = FALSE;
2032   dd.act_when_string_not_present = ! rfp->take_action_when_string_present;
2033   dd.userdata = rfp;
2034   dd.callback = RemoveDescriptorCallback;
2035   GetTitle (rfp->fromTxt, str, sizeof (str) - 1);
2036   if ((! StringHasNoText (str)) && sscanf (str, "%ld", &val) == 1 && val >= 0) {
2037     rfp->from = (Int4) val;
2038   } else {
2039     rfp->from = -1;
2040   }
2041   GetTitle (rfp->toTxt, str, sizeof (str) - 1);
2042   if ((! StringHasNoText (str)) && sscanf (str, "%ld", &val) == 1 && val >= 0) {
2043     rfp->to = (Int4) val;
2044   } else {
2045     rfp->to = -1;
2046   }
2047   if (rfp->from > rfp->to) {
2048     swap = rfp->from;
2049     rfp->from = rfp->to;
2050     rfp->to = swap;
2051   }
2052   OperateOnSeqEntryDescriptorsWithText (sep, &dd);
2053   DeleteMarkedObjects (rfp->input_entityID, OBJ_SEQENTRY, (Pointer) sep);
2054 }
2055 
DoRemoveAsnObject(ButtoN b)2056 static void DoRemoveAsnObject (ButtoN b)
2057 
2058 {
2059   MsgAnswer      ans;
2060   BioseqPtr      bsp;
2061   BioseqSetPtr   bssp;
2062   Uint4          itemID;
2063   OMProcControl  ompc;
2064   RemoveFormPtr  rfp;
2065   SeqEntryPtr    sep;
2066   ValNodePtr     tmp;
2067   Int2           val;
2068   ValNodePtr     vnp;
2069   Boolean        removed_some_features;
2070 
2071   rfp = GetObjectExtra (b);
2072   if (rfp == NULL) return;
2073   sep = GetTopSeqEntryForEntityID (rfp->input_entityID);
2074   if (sep == NULL) return;
2075   Hide (rfp->form);
2076   WatchCursor ();
2077   Update ();
2078   if (rfp->is_feature) {
2079     rfp->itemtype = OBJ_SEQFEAT;
2080   } else {
2081     rfp->itemtype = OBJ_SEQDESC;
2082   }
2083 
2084   if (rfp->itemtype == 0) return;
2085 
2086   removed_some_features = FALSE;
2087 
2088   if (GetValue (rfp->string_constraint_type) == 1)
2089   {
2090   	rfp->take_action_when_string_present = TRUE;
2091   }
2092   else
2093   {
2094     rfp->take_action_when_string_present = FALSE;
2095   }
2096 
2097   val = 1;
2098   for (vnp = rfp->head; vnp != NULL; vnp = vnp->next)
2099   {
2100     if (GetItemStatus (rfp->objlist, val))
2101     {
2102       rfp->subtype = vnp->choice;
2103       rfp->extra_string = NULL;
2104       if (rfp->subtype != 0) {
2105         if (rfp->is_feature) {
2106           RemoveFeatures (sep, rfp);
2107           removed_some_features = TRUE;
2108         } else {
2109           if (rfp->subtype == Seq_descr_user && StringCmp (vnp->data.ptrvalue, "User") != 0) {
2110             rfp->extra_string = vnp->data.ptrvalue;
2111           }
2112           RemoveDescriptors (sep, rfp);
2113         }
2114       }
2115     }
2116     val ++;
2117   }
2118 
2119   if (removed_some_features) {
2120     if (rfp->bsplist != NULL) {
2121       ans = Message (MSG_YN, "Remove protein products?");
2122       if (ans == ANS_YES) {
2123         for (tmp = rfp->bsplist; tmp != NULL; tmp = tmp->next) {
2124           bsp = (BioseqPtr) tmp->data.ptrvalue;
2125           itemID = GetItemIDGivenPointer (rfp->input_entityID, OBJ_BIOSEQ, (Pointer) bsp);
2126           if (itemID > 0) {
2127             MemSet ((Pointer) (&ompc), 0, sizeof (OMProcControl));
2128             ompc.do_not_reload_from_cache = TRUE;
2129             ompc.input_entityID = rfp->input_entityID;
2130             ompc.input_itemID = itemID;
2131             ompc.input_itemtype = OBJ_BIOSEQ;
2132             if (! DetachDataForProc (&ompc, FALSE)) {
2133               Message (MSG_POSTERR, "DetachDataForProc failed");
2134             }
2135             SeqMgrDeleteFromBioseqIndex (bsp);
2136           }
2137         }
2138         ans = Message (MSG_YN, "Renormalize Nuc-Prot sets?");
2139         if (ans == ANS_YES)
2140         {
2141           RemoveOrphanProteins (rfp->input_entityID, sep);
2142           RenormalizeNucProtSets (sep, TRUE);
2143         }
2144       }
2145     }
2146     if (rfp->bssplist != NULL) {
2147       ans = Message (MSG_YN, "Remove cDNA nuc-prot products?");
2148       if (ans == ANS_YES) {
2149         for (tmp = rfp->bssplist; tmp != NULL; tmp = tmp->next) {
2150           bssp = (BioseqSetPtr) tmp->data.ptrvalue;
2151           itemID = GetItemIDGivenPointer (rfp->input_entityID, OBJ_BIOSEQSET, (Pointer) bssp);
2152           if (itemID > 0) {
2153             MemSet ((Pointer) (&ompc), 0, sizeof (OMProcControl));
2154             ompc.do_not_reload_from_cache = TRUE;
2155             ompc.input_entityID = rfp->input_entityID;
2156             ompc.input_itemID = itemID;
2157             ompc.input_itemtype = OBJ_BIOSEQSET;
2158             if (! DetachDataForProc (&ompc, FALSE)) {
2159               Message (MSG_POSTERR, "DetachDataForProc failed");
2160             }
2161           }
2162         }
2163       }
2164     }
2165   }
2166   ArrowCursor ();
2167   Update ();
2168   ObjMgrSetDirtyFlag (rfp->input_entityID, TRUE);
2169   ObjMgrSendMsg (OM_MSG_UPDATE, rfp->input_entityID, 0, 0);
2170   ObjMgrDeSelect (0, 0, 0, 0, NULL);
2171   Remove (rfp->form);
2172 }
2173 
RemoveDefLinesCallback(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)2174 static void RemoveDefLinesCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
2175 
2176 {
2177   BioseqPtr      bsp;
2178   BioseqSetPtr   bssp;
2179   ValNodePtr     nextsdp;
2180   Pointer PNTR   prevsdp;
2181   ValNodePtr     sdp;
2182 
2183   if (sep == NULL || sep->data.ptrvalue == NULL) return;
2184   if (IS_Bioseq (sep)) {
2185     bsp = (BioseqPtr) sep->data.ptrvalue;
2186     sdp = bsp->descr;
2187     prevsdp = (Pointer PNTR) &(bsp->descr);
2188   } else if (IS_Bioseq_set (sep)) {
2189     bssp = (BioseqSetPtr) sep->data.ptrvalue;
2190     sdp = bssp->descr;
2191     prevsdp = (Pointer PNTR) &(bssp->descr);
2192   } else return;
2193 
2194   while (sdp != NULL) {
2195     nextsdp = sdp->next;
2196     if (sdp->choice == Seq_descr_title)
2197     {
2198       *(prevsdp) = sdp->next;
2199       sdp->next = NULL;
2200       SeqDescFree (sdp);
2201     } else {
2202       prevsdp = (Pointer PNTR) &(sdp->next);
2203     }
2204     sdp = nextsdp;
2205   }
2206 }
2207 
RemoveDefLinesToolBtn(ButtoN b)2208 extern void RemoveDefLinesToolBtn (ButtoN b)
2209 {
2210   BaseFormPtr  bfp;
2211   SeqEntryPtr  sep;
2212 
2213   bfp = (BaseFormPtr) GetObjectExtra (b);
2214   if (bfp == NULL) return;
2215 
2216   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2217   if (sep == NULL) return;
2218 
2219   WatchCursor ();
2220   Update ();
2221 
2222   SeqEntryExplore (sep, NULL, RemoveDefLinesCallback);
2223 
2224   ArrowCursor ();
2225   Update ();
2226   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2227   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2228   ObjMgrDeSelect (0, 0, 0, 0, NULL);
2229   CommonApplyToAllProc (bfp, ADD_TITLE);
2230 }
2231 
SortByVnpChoice(VoidPtr ptr1,VoidPtr ptr2)2232 int LIBCALLBACK SortByVnpChoice (VoidPtr ptr1, VoidPtr ptr2)
2233 
2234 {
2235   ValNodePtr   vnp1;
2236   ValNodePtr   vnp2;
2237 
2238   if (ptr1 != NULL && ptr2 != NULL) {
2239     vnp1 = *((ValNodePtr PNTR) ptr1);
2240     vnp2 = *((ValNodePtr PNTR) ptr2);
2241     if (vnp1 != NULL && vnp2 != NULL) {
2242       if (vnp1->choice > vnp2->choice) {
2243         return 1;
2244       } else if (vnp1->choice < vnp2->choice) {
2245         return -1;
2246       } else {
2247         return 0;
2248       }
2249     } else {
2250       return 0;
2251     }
2252   } else {
2253     return 0;
2254   }
2255 }
2256 
RemoveMessageProc(ForM f,Int2 mssg)2257 static void RemoveMessageProc (ForM f, Int2 mssg)
2258 
2259 {
2260   RemoveFormPtr  rfp;
2261 
2262   rfp = (RemoveFormPtr) GetObjectExtra (f);
2263   if (rfp != NULL) {
2264     if (rfp->appmessage != NULL) {
2265       rfp->appmessage (f, mssg);
2266     }
2267   }
2268 }
2269 
CleanupRemovePage(GraphiC g,VoidPtr data)2270 static void CleanupRemovePage (GraphiC g, VoidPtr data)
2271 
2272 {
2273   RemoveFormPtr  rfp;
2274 
2275   rfp = (RemoveFormPtr) data;
2276   if (rfp != NULL) {
2277     ValNodeFreeData (rfp->head);
2278     ValNodeFree (rfp->bsplist);
2279     ValNodeFree (rfp->bssplist);
2280   }
2281   StdCleanupFormProc (g, data);
2282 }
2283 
2284 static CharPtr descNames [] = {
2285   " ", " ", " ", " ", "Name",
2286   "Title", " ", "Comment", "Numbering",
2287   "MapLoc", "PIR", "GenBank", "Publication",
2288   "Region", "User", "SWISS-PROT", "dbXREF",
2289   "EMBL", "Create Date", "Update Date", "PRF",
2290   "PDB", "Heterogen", "BioSource", "MolInfo", NULL
2291 };
2292 
2293 /*
2294 #ifdef INTERNAL_NCBI_SEQUIN
2295 #define LISTHEIGHT 16
2296 #else
2297 #define LISTHEIGHT 8
2298 #endif
2299 */
2300 
2301 CharPtr MostUsedDescriptorList[] = { "Title" };
2302 
isMostUsedDescriptor(CharPtr descname)2303 static Boolean isMostUsedDescriptor (CharPtr descname)
2304 {
2305   Int2 i;
2306 
2307   if (descname == NULL) return FALSE;
2308 
2309   for (i=0; i < sizeof (MostUsedDescriptorList) / sizeof (CharPtr); i++)
2310   {
2311     if (StringCmp (descname, MostUsedDescriptorList[i]) == 0)
2312       return TRUE;
2313   }
2314   return FALSE;
2315 }
2316 
SortMostUsedDescriptorsFirst(VoidPtr ptr1,VoidPtr ptr2)2317 static int LIBCALLBACK SortMostUsedDescriptorsFirst (VoidPtr ptr1, VoidPtr ptr2)
2318 
2319 {
2320   ValNodePtr   vnp1;
2321   ValNodePtr   vnp2;
2322   CharPtr      str1;
2323   CharPtr      str2;
2324   Boolean      str1_is_most_used;
2325   Boolean      str2_is_most_used;
2326 
2327   /* Check parameters */
2328 
2329   if ((NULL == ptr1) || (NULL == ptr2))
2330     return 0;
2331 
2332   vnp1 = *((ValNodePtr PNTR) ptr1);
2333   vnp2 = *((ValNodePtr PNTR) ptr2);
2334   if ((NULL == vnp1) || (NULL == vnp2))
2335     return 0;
2336 
2337   str1 = (CharPtr) vnp1->data.ptrvalue;
2338   str2 = (CharPtr) vnp2->data.ptrvalue;
2339   if ((NULL == str1) || (NULL == str2))
2340     return 0;
2341 
2342   str1_is_most_used = isMostUsedDescriptor (str1);
2343   str2_is_most_used = isMostUsedDescriptor (str2);
2344 
2345   if ((str1_is_most_used && str2_is_most_used)
2346     || (!str1_is_most_used && !str2_is_most_used))
2347   {
2348     return SortVnpByString (ptr1, ptr2);
2349   }
2350   else if (str1_is_most_used)
2351   {
2352     return -1;
2353   }
2354   else
2355   {
2356     return 1;
2357   }
2358 }
2359 
BuildDescriptorValNodeList(void)2360 extern ValNodePtr BuildDescriptorValNodeList (void)
2361 {
2362   Int4 j;
2363   ValNodePtr vnp;
2364   ValNodePtr head = NULL;
2365 
2366   for (j = 1; descNames [j] != NULL; j++) {
2367     if (StringHasNoText (descNames [j])) continue;
2368     vnp = ValNodeNew (head);
2369     if (head == NULL) {
2370       head = vnp;
2371     }
2372     if (vnp != NULL) {
2373       vnp->choice = j;
2374       vnp->data.ptrvalue = StringSave (descNames [j]);
2375     }
2376   }
2377   head = SortValNode (head, SortMostUsedDescriptorsFirst);
2378   return head;
2379 }
2380 
2381 
RemoveAsnObject(IteM i,Boolean feature)2382 static void RemoveAsnObject (IteM i, Boolean feature)
2383 
2384 {
2385   BaseFormPtr        bfp;
2386   ButtoN             b;
2387   GrouP              c;
2388   GrouP              g;
2389   GrouP              h;
2390   ValNodePtr         head;
2391   GrouP              k;
2392   Int2               listHeight;
2393   GrouP              m;
2394   RemoveFormPtr      rfp;
2395   SeqEntryPtr        sep;
2396   StdEditorProcsPtr  sepp;
2397   CharPtr            title;
2398   ValNodePtr         vnp;
2399   WindoW             w;
2400 
2401 #ifdef WIN_MAC
2402   bfp = currentFormDataPtr;
2403 #else
2404   bfp = GetObjectExtra (i);
2405 #endif
2406   if (bfp == NULL) return;
2407   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2408   if (sep == NULL) return;
2409   rfp = (RemoveFormPtr) MemNew (sizeof (RemoveFormData));
2410   if (rfp == NULL) return;
2411   if (feature) {
2412     title = "Feature Removal";
2413   } else {
2414     title = "Descriptor Removal";
2415   }
2416   w = FixedWindow (-50, -33, -10, -10, title, StdCloseWindowProc);
2417   SetObjectExtra (w, rfp, CleanupRemovePage);
2418   rfp->form = (ForM) w;
2419   rfp->formmessage = RemoveMessageProc;
2420 
2421   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2422   if (sepp != NULL) {
2423     SetActivate (w, sepp->activateForm);
2424     rfp->appmessage = sepp->handleMessages;
2425   }
2426 
2427   rfp->input_entityID = bfp->input_entityID;
2428   rfp->input_itemID = bfp->input_itemID;
2429   rfp->input_itemtype = bfp->input_itemtype;
2430 
2431   h = HiddenGroup (w, -1, 0, NULL);
2432   SetGroupSpacing (h, 10, 10);
2433 
2434   g = HiddenGroup (h, 0, 2, NULL);
2435   rfp->is_feature = feature;
2436   if (feature) {
2437     StaticPrompt (g, "Feature", 0, 0, programFont, 'c');
2438   } else {
2439     StaticPrompt (g, "Descriptor", 0, 0, programFont, 'c');
2440   }
2441   if (indexerVersion) {
2442     listHeight = 16;
2443   } else {
2444     listHeight = 8;
2445   }
2446   rfp->objlist = MultiList (g, 16, listHeight, NULL);
2447   head = NULL;
2448   if (feature) {
2449     head = BuildFeatureValNodeList (TRUE, "All", ALL_FEATURES, TRUE, FALSE);
2450   } else {
2451     head = BuildDescriptorValNodeList();
2452     vnp = ValNodeNew (NULL);
2453     vnp->choice = Seq_descr_user;
2454     vnp->data.ptrvalue = StringSave ("StructuredComment");
2455     ValNodeInsert (&(head->next), vnp, SortVnpByString);
2456     vnp = ValNodeNew (NULL);
2457     vnp->choice = Seq_descr_user;
2458     vnp->data.ptrvalue = StringSave ("DBLink");
2459     ValNodeInsert (&(head->next), vnp, SortVnpByString);
2460   }
2461   if (head != NULL) {
2462 
2463     for (vnp = head; vnp != NULL; vnp = vnp->next) {
2464       ListItem (rfp->objlist, (CharPtr) vnp->data.ptrvalue);
2465     }
2466   }
2467   rfp->head = head;
2468   rfp->bsplist = NULL;
2469   rfp->bssplist = NULL;
2470 
2471   k = NormalGroup (h, 0, 3, "Optional string constraint", NULL, NULL);
2472   rfp->string_constraint_type = HiddenGroup (k, 0, 2, NULL);
2473   RadioButton (rfp->string_constraint_type, "Remove when text is present");
2474   RadioButton (rfp->string_constraint_type, "Remove when text is not present");
2475   SetValue (rfp->string_constraint_type, 1);
2476   rfp->findthis = DialogText (k, "", 14, NULL);
2477   rfp->case_insensitive = CheckBox (k, "Case Insensitive", NULL);
2478 
2479   m = NULL;
2480   if (feature) {
2481     m = HiddenGroup (h, 4, 0, NULL);
2482     StaticPrompt (m, "From", 0, dialogTextHeight, programFont, 'l');
2483     rfp->fromTxt = DialogText (m, "", 6, NULL);
2484     StaticPrompt (m, "To", 0, dialogTextHeight, programFont, 'l');
2485     rfp->toTxt = DialogText (m, "", 6, NULL);
2486   }
2487 
2488   c = HiddenGroup (h, 4, 0, NULL);
2489   b = DefaultButton (c, "Accept", DoRemoveAsnObject);
2490   SetObjectExtra (b, rfp, NULL);
2491   PushButton (c, "Cancel", StdCancelButtonProc);
2492 
2493   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) k, (HANDLE) c, (HANDLE) m, NULL);
2494   RealizeWindow (w);
2495   Show (w);
2496   Update ();
2497 }
2498 
RemoveDescriptor(IteM i)2499 extern void RemoveDescriptor (IteM i)
2500 
2501 {
2502   RemoveAsnObject (i, FALSE);
2503 }
2504 
2505 #define SLCT_FEAT    1
2506 #define SLCT_DESC    2
2507 #define SLCT_BIOSEQ  3
2508 #define SLCT_PUB     4
2509 
2510 typedef struct selectformdata {
2511   FEATURE_FORM_BLOCK
2512 
2513   Int2           type;
2514   LisT           objlist;
2515   TexT           findthis;
2516   Uint2          itemtype;
2517   Uint2          subtype;
2518   ObjMgrPtr      omp;
2519   ObjMgrTypePtr  omtp;
2520   ValNodePtr     head;
2521   Boolean        stringfound;
2522   Char           findStr [128];
2523   ButtoN         when_string_not_present;
2524   ButtoN         case_insensitive;
2525 } SelectFormData, PNTR SelectFormPtr;
2526 
FeatureSelectCallback(SeqFeatPtr sfp,Pointer userdata)2527 static void FeatureSelectCallback (SeqFeatPtr sfp, Pointer userdata)
2528 {
2529   Uint1Ptr subtype;
2530   if (sfp == NULL) return;
2531 
2532   if (userdata != NULL)
2533   {
2534   	subtype = (Uint1Ptr) userdata;
2535   	if (*subtype != sfp->idx.subtype) return;
2536   }
2537   ObjMgrAlsoSelect (sfp->idx.entityID, sfp->idx.itemID, OBJ_SEQFEAT, 0, NULL);
2538 }
2539 
DescriptorSelectCallback(SeqDescrPtr sdp,Pointer userdata)2540 static void DescriptorSelectCallback (SeqDescrPtr sdp, Pointer userdata)
2541 {
2542   ObjValNodePtr ovp;
2543   Uint1Ptr subtype;
2544 
2545   if (sdp == NULL || sdp->extended == 0) return;
2546 
2547   ovp = (ObjValNodePtr) sdp;
2548   if (userdata != NULL)
2549   {
2550   	subtype = (Uint1Ptr) userdata;
2551   	if (*subtype != ovp->idx.subtype) return;
2552   }
2553 
2554   ObjMgrAlsoSelect (ovp->idx.entityID, ovp->idx.itemID, OBJ_SEQDESC, 0, NULL);
2555 }
2556 
BioseqSelectCallback(BioseqPtr bsp,Pointer userdata)2557 static void BioseqSelectCallback (BioseqPtr bsp, Pointer userdata)
2558 {
2559   Uint1Ptr subtype;
2560 
2561   if (bsp == NULL) return;
2562 
2563   if (userdata != NULL)
2564   {
2565   	subtype = (Uint1Ptr) userdata;
2566   	if (*subtype != bsp->idx.subtype) return;
2567   }
2568 
2569   ObjMgrAlsoSelect (bsp->idx.entityID, bsp->idx.itemID, bsp->idx.itemtype, 0, NULL);
2570 }
2571 
2572 
DoSelectAsnObject(ButtoN b)2573 static void DoSelectAsnObject (ButtoN b)
2574 
2575 {
2576   SelectFormPtr           selfp;
2577   SeqEntryPtr             sep;
2578   Int2                    val;
2579   ValNodePtr              vnp;
2580   FeaturesWithTextData    fd;
2581   DescriptorsWithTextData dd;
2582   Uint1                   bioseq_choice = Seq_repr_raw;
2583   Uint1                   pub_choice = FEATDEF_PUB;
2584 
2585   selfp = GetObjectExtra (b);
2586   if (selfp == NULL) return;
2587   sep = GetTopSeqEntryForEntityID (selfp->input_entityID);
2588   if (sep == NULL) return;
2589   Hide (selfp->form);
2590 
2591   vnp = NULL;
2592   if (selfp->type == SLCT_FEAT || selfp->type == SLCT_DESC)
2593   {
2594     val = GetValue (selfp->objlist);
2595     if (val > 0) {
2596       vnp = selfp->head;
2597       while (vnp != NULL && val > 1) {
2598         val--;
2599         vnp = vnp->next;
2600       }
2601     }
2602   }
2603 
2604   switch (selfp->type) {
2605     case SLCT_FEAT :
2606       GetTitle (selfp->findthis, selfp->findStr, sizeof (selfp->findStr) - 1);
2607       fd.search_text = selfp->findStr;
2608       fd.no_text = StringHasNoText (selfp->findStr);
2609       fd.seqFeatChoice = 0;
2610       fd.featDefChoice = 0;
2611       fd.case_insensitive = GetStatus (selfp->case_insensitive);
2612       fd.whole_word = FALSE;
2613       fd.act_when_string_not_present = GetStatus (selfp->when_string_not_present);
2614       fd.callback = FeatureSelectCallback;
2615       if (vnp == NULL)
2616       {
2617       	fd.userdata = NULL;
2618       }
2619       else
2620       {
2621         fd.userdata = (Pointer) &(vnp->choice);
2622       }
2623       OperateOnSeqEntryFeaturesWithText (sep, &fd);
2624       break;
2625     case SLCT_DESC :
2626       GetTitle (selfp->findthis, selfp->findStr, sizeof (selfp->findStr) - 1);
2627       dd.search_text = selfp->findStr;
2628       dd.no_text = StringHasNoText (selfp->findStr);
2629       dd.case_insensitive = GetStatus (selfp->case_insensitive);
2630       dd.whole_word = FALSE;
2631       dd.act_when_string_not_present = GetStatus (selfp->when_string_not_present);
2632       dd.callback = DescriptorSelectCallback;
2633       if (vnp == NULL)
2634       {
2635       	dd.userdata = NULL;
2636       }
2637       else
2638       {
2639         dd.userdata = (Pointer) &(vnp->choice);
2640       }
2641       OperateOnSeqEntryDescriptorsWithText (sep, &dd);
2642       break;
2643     case SLCT_BIOSEQ :
2644  	  VisitBioseqsInSep (sep, (Pointer) &bioseq_choice, BioseqSelectCallback);
2645       break;
2646   	case SLCT_PUB:
2647       GetTitle (selfp->findthis, selfp->findStr, sizeof (selfp->findStr) - 1);
2648       fd.search_text = selfp->findStr;
2649       fd.no_text = StringHasNoText (selfp->findStr);
2650       fd.seqFeatChoice = 0;
2651       fd.featDefChoice = 0;
2652       fd.case_insensitive = GetStatus (selfp->case_insensitive);
2653       fd.whole_word = FALSE;
2654       fd.act_when_string_not_present = GetStatus (selfp->when_string_not_present);
2655       fd.callback = FeatureSelectCallback;
2656       fd.userdata = (Pointer) &pub_choice;
2657       OperateOnSeqEntryFeaturesWithText (sep, &fd);
2658       dd.search_text = fd.search_text;
2659       dd.no_text = fd.no_text;
2660       dd.case_insensitive = fd.case_insensitive;
2661       dd.whole_word = fd.whole_word;
2662       dd.act_when_string_not_present = fd.act_when_string_not_present;
2663       dd.callback = DescriptorSelectCallback;
2664       dd.userdata = fd.userdata;
2665       OperateOnSeqEntryDescriptorsWithText (sep, &dd);
2666       break;
2667     default :
2668       Remove (selfp->form);
2669       Update ();
2670       return;
2671   }
2672   WatchCursor ();
2673   Update ();
2674 
2675   ArrowCursor ();
2676   Update ();
2677   /* ObjMgrSendMsg (OM_MSG_UPDATE, selfp->input_entityID, 0, 0); */
2678   Remove (selfp->form);
2679 }
2680 
SelectMessageProc(ForM f,Int2 mssg)2681 static void SelectMessageProc (ForM f, Int2 mssg)
2682 
2683 {
2684   SelectFormPtr  selfp;
2685 
2686   selfp = (SelectFormPtr) GetObjectExtra (f);
2687   if (selfp != NULL) {
2688     if (selfp->appmessage != NULL) {
2689       selfp->appmessage (f, mssg);
2690     }
2691   }
2692 }
2693 
CleanupSelectPage(GraphiC g,VoidPtr data)2694 static void CleanupSelectPage (GraphiC g, VoidPtr data)
2695 
2696 {
2697   SelectFormPtr  selfp;
2698 
2699   selfp = (SelectFormPtr) data;
2700   if (selfp != NULL) {
2701     ValNodeFreeData (selfp->head);
2702   }
2703   StdCleanupFormProc (g, data);
2704 }
2705 
SelectAsnObject(IteM i,Int2 type)2706 static void SelectAsnObject (IteM i, Int2 type)
2707 
2708 {
2709   BaseFormPtr        bfp;
2710   ButtoN             b;
2711   GrouP              c;
2712   GrouP              g;
2713   GrouP              h;
2714   GrouP              k = NULL, m;
2715   ValNodePtr         head;
2716   Uint1              j;
2717   Int2               listHeight;
2718   SelectFormPtr      selfp;
2719   SeqEntryPtr        sep;
2720   StdEditorProcsPtr  sepp;
2721   CharPtr            title;
2722   ValNodePtr         vnp;
2723   WindoW             w;
2724 
2725 #ifdef WIN_MAC
2726   bfp = currentFormDataPtr;
2727 #else
2728   bfp = GetObjectExtra (i);
2729 #endif
2730   if (bfp == NULL) return;
2731   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2732   if (sep == NULL) return;
2733   selfp = (SelectFormPtr) MemNew (sizeof (SelectFormData));
2734   if (selfp == NULL) return;
2735   switch (type) {
2736     case SLCT_FEAT :
2737       title = "Feature Selection";
2738       break;
2739     case SLCT_DESC :
2740       title = "Descriptor Selection";
2741       break;
2742     case SLCT_BIOSEQ :
2743       title = "Sequence Selection";
2744       break;
2745   	case SLCT_PUB:
2746   	  title = "Publication Selection";
2747   	  break;
2748     default :
2749       title = "? Selection";
2750       break;
2751   }
2752   w = FixedWindow (-50, -33, -10, -10, title, StdCloseWindowProc);
2753   SetObjectExtra (w, selfp, CleanupSelectPage);
2754   selfp->form = (ForM) w;
2755   selfp->formmessage = SelectMessageProc;
2756 
2757   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2758   if (sepp != NULL) {
2759     SetActivate (w, sepp->activateForm);
2760     selfp->appmessage = sepp->handleMessages;
2761   }
2762 
2763   selfp->input_entityID = bfp->input_entityID;
2764   selfp->input_itemID = bfp->input_itemID;
2765   selfp->input_itemtype = bfp->input_itemtype;
2766 
2767   h = HiddenGroup (w, -1, 0, NULL);
2768   SetGroupSpacing (h, 10, 10);
2769 
2770   g = HiddenGroup (h, 0, 2, NULL);
2771   selfp->type = type;
2772   switch (type) {
2773     case SLCT_FEAT :
2774       StaticPrompt (g, "Feature", 0, 0, programFont, 'c');
2775       break;
2776     case SLCT_DESC :
2777       StaticPrompt (g, "Descriptor", 0, 0, programFont, 'c');
2778       break;
2779     case SLCT_BIOSEQ :
2780       StaticPrompt (g, "Sequence", 0, 0, programFont, 'c');
2781       break;
2782   	case SLCT_PUB:
2783   	  StaticPrompt (g, "Publication", 0, 0, programFont, 'c');
2784   	  break;
2785     default :
2786       break;
2787   }
2788   if (indexerVersion) {
2789     listHeight = 16;
2790   } else {
2791     listHeight = 8;
2792   }
2793 
2794   if (type != SLCT_PUB)
2795   {
2796     selfp->objlist = SingleList (g, 16, listHeight, NULL);
2797   }
2798   head = NULL;
2799   if (type == SLCT_FEAT) {
2800     head = BuildFeatureValNodeList (TRUE, NULL, ALL_FEATURES, TRUE, FALSE);
2801   } else if (type == SLCT_DESC) {
2802     for (j = 1; descNames [j] != NULL; j++) {
2803       if (StringHasNoText (descNames [j])) continue;
2804       vnp = ValNodeNew (head);
2805       if (head == NULL) {
2806         head = vnp;
2807       }
2808       if (vnp != NULL) {
2809         vnp->choice = j;
2810         vnp->data.ptrvalue = StringSave (descNames [j]);
2811       }
2812     }
2813   }
2814   if (head != NULL) {
2815     if (type != SLCT_FEAT) {
2816       head = SortValNode (head, SortByVnpChoice);
2817     }
2818     for (vnp = head; vnp != NULL; vnp = vnp->next) {
2819       ListItem (selfp->objlist, (CharPtr) vnp->data.ptrvalue);
2820     }
2821   }
2822   selfp->head = head;
2823 
2824   if (selfp->type == SLCT_FEAT || selfp->type == SLCT_DESC || selfp->type == SLCT_PUB)
2825   {
2826     k = HiddenGroup (h, 0, 3, NULL);
2827     StaticPrompt (k, "Optional string constraint", 0, dialogTextHeight, programFont, 'c');
2828     selfp->findthis = DialogText (k, "", 14, NULL);
2829     m = HiddenGroup (k, 2, 0, NULL);
2830     selfp->case_insensitive = CheckBox (m, "Case Insensitive", NULL);
2831     selfp->when_string_not_present = CheckBox (m, "When String Not Present", NULL);
2832   }
2833 
2834   c = HiddenGroup (h, 4, 0, NULL);
2835   b = DefaultButton (c, "Accept", DoSelectAsnObject);
2836   SetObjectExtra (b, selfp, NULL);
2837   PushButton (c, "Cancel", StdCancelButtonProc);
2838 
2839   if (selfp->type == SLCT_FEAT || selfp->type == SLCT_DESC)
2840   {
2841     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) k, NULL);
2842   }
2843   else
2844   {
2845     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
2846   }
2847   RealizeWindow (w);
2848   if (type == SLCT_BIOSEQ) {
2849     DoSelectAsnObject (b);
2850     Update ();
2851     return;
2852   }
2853   Show (w);
2854   Update ();
2855 }
2856 
SelectDescriptor(IteM i)2857 extern void SelectDescriptor (IteM i)
2858 
2859 {
2860   SelectAsnObject (i, SLCT_DESC);
2861 }
2862 
SelectBioseq(IteM i)2863 extern void SelectBioseq (IteM i)
2864 
2865 {
2866   SelectAsnObject (i, SLCT_BIOSEQ);
2867 }
2868 
SelectPubs(IteM i)2869 extern void SelectPubs (IteM i)
2870 
2871 {
2872   SelectAsnObject (i, SLCT_PUB);
2873 }
2874 
2875 typedef struct fuseformdata {
2876   FEATURE_FORM_BLOCK
2877 
2878   LisT           objlist;
2879   DialoG         constraint_dlg;
2880   ButtoN         keep_orig_btn;
2881   Uint2          subtype;
2882   ValNodePtr     head;
2883   ConstraintChoiceSetPtr constraint;
2884   Boolean        keep_orig;
2885 } FuseFormData, PNTR FuseFormPtr;
2886 
FuseTwoLocations(Uint2 entityID,SeqLocPtr slp1,SeqLocPtr slp2)2887 static SeqLocPtr FuseTwoLocations (Uint2 entityID, SeqLocPtr slp1, SeqLocPtr slp2)
2888 {
2889   Boolean           slp1_partial5, slp1_partial3;
2890   Boolean           slp2_partial5, slp2_partial3;
2891   Int4              slp1_start_pos, slp1_stop_pos;
2892   Int4              slp2_start_pos, slp2_stop_pos;
2893   SeqLocPtr         slp_result = NULL, slp2_copy, slp1_copy, slp_list;
2894   BioseqPtr         bsp1, bsp2;
2895 
2896   if (slp1 == NULL || slp2 == NULL)
2897   {
2898     return NULL;
2899   }
2900 
2901   bsp1 = GetBioseqGivenSeqLoc (slp1, entityID);
2902   bsp2 = GetBioseqGivenSeqLoc (slp2, entityID);
2903 
2904   /* preserve partialness of ends */
2905   CheckSeqLocForPartial (slp1, &slp1_partial5, &slp1_partial3);
2906   slp1_start_pos = SeqLocStart (slp1);
2907   slp1_stop_pos = SeqLocStop (slp1);
2908   CheckSeqLocForPartial (slp2, &slp2_partial5, &slp2_partial3);
2909   slp2_start_pos = SeqLocStart (slp2);
2910   slp2_stop_pos = SeqLocStop (slp2);
2911   if (slp1_start_pos > slp2_start_pos)
2912   {
2913     slp1_partial5 = slp2_partial5;
2914   }
2915   if (slp1_stop_pos < slp2_stop_pos)
2916   {
2917     slp1_partial3 = slp2_partial3;
2918   }
2919 
2920   if (bsp1 == bsp2)
2921   {
2922     slp_result = SeqLocMerge (bsp1, slp2, slp1, FALSE, TRUE, FALSE);
2923     SetSeqLocPartial (slp_result, slp1_partial5, slp1_partial3);
2924   }
2925   else
2926   {
2927     /* we are dealing with a segmented set, and both locations are segments */
2928     slp1_copy = (SeqLocPtr) AsnIoMemCopy (slp1, (AsnReadFunc) SeqLocAsnRead,
2929                                           (AsnWriteFunc) SeqLocAsnWrite);
2930     slp2_copy = (SeqLocPtr) AsnIoMemCopy (slp2, (AsnReadFunc) SeqLocAsnRead,
2931                                           (AsnWriteFunc) SeqLocAsnWrite);
2932     if (slp1_copy != NULL && slp2_copy != NULL)
2933     {
2934       /* if the second location is already a mix, don't create a nested
2935        * mixed location.
2936        */
2937       if (slp2_copy->choice == SEQLOC_MIX)
2938       {
2939         slp_list = (SeqLocPtr) slp2_copy->data.ptrvalue;
2940         slp2_copy->data.ptrvalue = NULL;
2941         slp2_copy = SeqLocFree (slp2_copy);
2942         slp2_copy = slp_list;
2943       }
2944 
2945       if (slp1_copy->choice == SEQLOC_MIX)
2946       {
2947         slp_list = slp1_copy->data.ptrvalue;
2948         while (slp_list != NULL && slp_list->next != NULL)
2949         {
2950           slp_list = slp_list->next;
2951         }
2952 
2953 
2954         if (slp_list == NULL)
2955         {
2956           slp1_copy->data.ptrvalue = slp2_copy;
2957         }
2958         else
2959         {
2960           slp_list->next = slp2_copy;
2961         }
2962         slp_result = slp1_copy;
2963       }
2964       else
2965       {
2966         slp_result = ValNodeNew (NULL);
2967         if (slp_result != NULL)
2968         {
2969           slp_result->choice = SEQLOC_MIX;
2970           slp_result->data.ptrvalue = slp1_copy;
2971           slp1_copy->next = slp2_copy;
2972         }
2973       }
2974     }
2975   }
2976 
2977   return slp_result;
2978 }
2979 
CombineProductFeatures(BioseqPtr pbsp1,BioseqPtr pbsp2,Int4 old_len)2980 static void CombineProductFeatures (BioseqPtr pbsp1, BioseqPtr pbsp2, Int4 old_len)
2981 {
2982   SeqAnnotPtr sap1, sap2, last_sap1 = NULL;
2983   SeqFeatPtr  sfp2, sfp_new, last_sfp1 = NULL, main_prot = NULL;
2984   Boolean     partial5_orig = TRUE, partial3_orig = TRUE;
2985   Boolean     partial5_new, partial3_new;
2986   SeqEntryPtr psep;
2987   ProtRefPtr  prp;
2988 
2989   if (pbsp1 == NULL || pbsp2 == NULL)
2990   {
2991     return;
2992   }
2993 
2994   sap2 = pbsp2->annot;
2995   while (sap2 != NULL && sap2->type != 1)
2996   {
2997     sap2 = sap2->next;
2998   }
2999   if (sap2 == NULL || sap2->data == NULL)
3000   {
3001     /* second sequence has no features */
3002     return;
3003   }
3004 
3005   sap1 = pbsp1->annot;
3006   while (sap1 != NULL && sap1->type != 1)
3007   {
3008     last_sap1 = sap1;
3009     sap1 = sap1->next;
3010   }
3011   if (sap1 == NULL)
3012   {
3013     sap1 = SeqAnnotNew();
3014     if (sap1 == NULL)
3015     {
3016       return;
3017     }
3018     sap1->type = 1;
3019     sap1->data = NULL;
3020     if (last_sap1 == NULL)
3021     {
3022       pbsp1->annot = sap1;
3023     }
3024     else
3025     {
3026       last_sap1->next = sap1;
3027     }
3028   }
3029 
3030   last_sfp1 = sap1->data;
3031   if (last_sfp1 != NULL && last_sfp1->idx.subtype == FEATDEF_PROT)
3032   {
3033     main_prot = last_sfp1;
3034     CheckSeqLocForPartial (main_prot->location, &partial5_orig, &partial3_orig);
3035   }
3036   while (last_sfp1 != NULL && last_sfp1->next != NULL)
3037   {
3038     if (main_prot == NULL && last_sfp1->idx.subtype == FEATDEF_PROT)
3039     {
3040       main_prot = last_sfp1;
3041       CheckSeqLocForPartial (main_prot->location, &partial5_orig, &partial3_orig);
3042     }
3043     last_sfp1 = last_sfp1->next;
3044   }
3045   if (last_sfp1 != NULL && main_prot == NULL && last_sfp1->idx.subtype == FEATDEF_PROT)
3046   {
3047     main_prot = last_sfp1;
3048     CheckSeqLocForPartial (main_prot->location, &partial5_orig, &partial3_orig);
3049   }
3050 
3051   partial3_new = partial3_orig;
3052 
3053   while (sap2 != NULL)
3054   {
3055     if (sap2->type == 1)
3056     {
3057       for (sfp2 = sap2->data; sfp2 != NULL; sfp2 = sfp2->next)
3058       {
3059         if (sfp2->idx.subtype == FEATDEF_PROT)
3060         {
3061           CheckSeqLocForPartial (sfp2->location, &partial5_new, &partial3_new);
3062           /* do not create additional full-length protein features */
3063           continue;
3064         }
3065         sfp_new = (SeqFeatPtr) AsnIoMemCopy (sfp2, (AsnReadFunc) SeqFeatAsnRead,
3066                                                (AsnWriteFunc) SeqFeatAsnWrite);
3067         if (sfp_new != NULL)
3068         {
3069           OffsetLocation (sfp_new->location, old_len, pbsp1->id);
3070 
3071           if (last_sfp1 == NULL)
3072           {
3073             sap1->data = sfp_new;
3074           }
3075           else
3076           {
3077             last_sfp1->next = sfp_new;
3078           }
3079           last_sfp1 = sfp_new;
3080         }
3081       }
3082     }
3083     sap2 = sap2->next;
3084   }
3085 
3086   /* make sure there is one full-length protein feature */
3087   if (main_prot == NULL)
3088   {
3089     psep = SeqMgrGetSeqEntryForData (pbsp1);
3090     main_prot = CreateNewFeature (psep, NULL, SEQFEAT_PROT, NULL);
3091     if (main_prot != NULL)
3092     {
3093       prp = ProtRefNew ();
3094       main_prot->data.value.ptrvalue = (Pointer) prp;
3095     }
3096   }
3097   if (main_prot != NULL)
3098   {
3099     if (main_prot->location == NULL || main_prot->location->choice != SEQLOC_INT)
3100     {
3101       main_prot->location = SeqLocFree (main_prot->location);
3102       main_prot->location = SeqLocIntNew (0, pbsp1->length - 1,
3103                                           Seq_strand_plus,
3104                                           SeqIdDup (pbsp1->id));
3105     }
3106     SetSeqLocPartial (main_prot->location, partial5_orig, partial3_new);
3107     main_prot->partial = (Boolean) (partial5_orig || partial3_new);
3108   }
3109 }
3110 
FuseTwoProducts(SeqFeatPtr sfp1,SeqFeatPtr sfp2,Uint2 entityID)3111 static void FuseTwoProducts (SeqFeatPtr sfp1, SeqFeatPtr sfp2, Uint2 entityID)
3112 {
3113   BioseqPtr    pbsp1, pbsp2;
3114   CharPtr      pstr1, pstr2;
3115   ByteStorePtr byte_store, bs2 = NULL;
3116   Int4         old_length, added_length;
3117   SeqIdPtr     sip1;
3118 
3119   if (sfp1 == NULL || sfp2 == NULL
3120       || sfp1->idx.subtype != FEATDEF_CDS
3121       || sfp2->idx.subtype != FEATDEF_CDS)
3122   {
3123     return;
3124   }
3125   pbsp1 = BioseqFindFromSeqLoc (sfp1->product);
3126   pbsp2 = BioseqFindFromSeqLoc (sfp2->product);
3127 
3128   if (pbsp1 == NULL)
3129   {
3130     sip1 = SeqLocId (sfp1->product);
3131     pbsp1 = BioseqFind (sip1);
3132     if (pbsp1 == NULL)
3133     {
3134       RetranslateOneCDS (sfp1, entityID, TRUE, FALSE);
3135       pbsp1 = BioseqFindFromSeqLoc (sfp1->product);
3136       if (pbsp1 == NULL)
3137       {
3138         sip1 = SeqLocId (sfp1->product);
3139         pbsp1 = BioseqFind (sip1);
3140       }
3141     }
3142   }
3143   if (pbsp1 == NULL)
3144   {
3145     return;
3146   }
3147   pstr1 = BSMerge ((ByteStorePtr)(pbsp1->seq_data), NULL);
3148   old_length = pbsp1->length;
3149 
3150   if (pbsp2 == NULL)
3151   {
3152     bs2 = ProteinFromCdRegionEx (sfp2, TRUE, FALSE);
3153     pstr2 = BSMerge (bs2, NULL);
3154     added_length = BSLen (bs2);
3155   }
3156   else
3157   {
3158     pstr2 = BSMerge ((ByteStorePtr)(pbsp2->seq_data), NULL);
3159     added_length = pbsp2->length;
3160   }
3161 
3162   byte_store = BSNew (old_length + added_length);
3163   if (byte_store != NULL)
3164   {
3165     BSWrite (byte_store, pstr1, StringLen (pstr1));
3166     BSWrite (byte_store, pstr2, StringLen (pstr2));
3167     pbsp1->seq_data = SeqDataFree (pbsp1->seq_data, pbsp1->seq_data_type);
3168     pbsp1->seq_data = (SeqDataPtr) byte_store;
3169     pbsp1->length += added_length;
3170 
3171     /* now copy features from the second protein to the first */
3172     CombineProductFeatures (pbsp1, pbsp2, old_length);
3173 
3174     /* remove unused protein */
3175     if (pbsp2 != NULL)
3176     {
3177       pbsp2->idx.deleteme = TRUE;
3178     }
3179   }
3180   bs2 = BSFree (bs2);
3181 }
3182 
FuseFeatureCallback(BioseqPtr bsp,Pointer userdata)3183 static void FuseFeatureCallback (BioseqPtr bsp, Pointer userdata)
3184 {
3185   FuseFormPtr       ffp;
3186   SeqFeatPtr        first = NULL, sfp = NULL, orig = NULL;
3187   SeqMgrFeatContext context;
3188   SeqLocPtr         slp;
3189 
3190   if (bsp == NULL || userdata == NULL)
3191   {
3192     return;
3193   }
3194 
3195   ffp = (FuseFormPtr) userdata;
3196 
3197   sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
3198   while (sfp != NULL)
3199   {
3200     if ((sfp->idx.subtype == ffp->subtype ||
3201            (ffp->subtype == FEATDEF_IMP &&
3202             IsRealImpFeat (sfp->idx.subtype)))
3203         && DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, ffp->constraint))
3204     {
3205       if (first == NULL)
3206       {
3207         first = sfp;
3208       }
3209       else
3210       {
3211         if (ffp->keep_orig && orig == NULL) {
3212           orig = first;
3213           first = AsnIoMemCopy (orig, (AsnReadFunc) SeqFeatAsnRead, (AsnWriteFunc) SeqFeatAsnWrite);
3214           first->next = orig->next;
3215           orig->next = first;
3216         }
3217         slp = FuseTwoLocations (ffp->input_entityID, first->location, sfp->location);
3218         first->location = SeqLocFree (first->location);
3219         first->location = slp;
3220         first->partial = CheckSeqLocForPartial (slp, NULL, NULL);
3221         if (!ffp->keep_orig) {
3222           sfp->idx.deleteme = TRUE;
3223         }
3224         if (sfp->idx.subtype == FEATDEF_CDS)
3225         {
3226           FuseTwoProducts (first, sfp, ffp->input_entityID);
3227         }
3228       }
3229     }
3230     sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
3231   }
3232 }
3233 
3234 
DoFuseFeature(ButtoN b)3235 static void DoFuseFeature (ButtoN b)
3236 
3237 {
3238   FuseFormPtr  ffp;
3239   SeqEntryPtr  sep;
3240   Int2         val;
3241   ValNodePtr   vnp;
3242 
3243   ffp = (FuseFormPtr) GetObjectExtra (b);
3244   if (ffp == NULL) return;
3245   sep = GetTopSeqEntryForEntityID (ffp->input_entityID);
3246   if (sep == NULL) return;
3247   Hide (ffp->form);
3248   WatchCursor ();
3249   Update ();
3250 
3251   ffp->keep_orig = GetStatus (ffp->keep_orig_btn);
3252 
3253   vnp = NULL;
3254   val = GetValue (ffp->objlist);
3255   if (val > 0) {
3256     vnp = ffp->head;
3257     while (vnp != NULL && val > 1) {
3258       val--;
3259       vnp = vnp->next;
3260     }
3261   }
3262   if (vnp != NULL) {
3263     ffp->subtype = vnp->choice;
3264     ffp->constraint = DialogToPointer (ffp->constraint_dlg);
3265     VisitBioseqsInSep (sep, ffp, FuseFeatureCallback);
3266     ffp->constraint = ConstraintChoiceSetFree(ffp->constraint);
3267     DeleteMarkedObjects (ffp->input_entityID, 0, NULL);
3268   }
3269 
3270   ArrowCursor ();
3271   Update ();
3272   ObjMgrSetDirtyFlag (ffp->input_entityID, TRUE);
3273   ObjMgrSendMsg (OM_MSG_UPDATE, ffp->input_entityID, 0, 0);
3274   ObjMgrDeSelect (0, 0, 0, 0, NULL);
3275   Remove (ffp->form);
3276 }
3277 
FuseMessageProc(ForM f,Int2 mssg)3278 static void FuseMessageProc (ForM f, Int2 mssg)
3279 
3280 {
3281   FuseFormPtr  ffp;
3282 
3283   ffp = (FuseFormPtr) GetObjectExtra (f);
3284   if (ffp != NULL) {
3285     if (ffp->appmessage != NULL) {
3286       ffp->appmessage (f, mssg);
3287     }
3288   }
3289 }
3290 
CleanupFusePage(GraphiC g,VoidPtr data)3291 static void CleanupFusePage (GraphiC g, VoidPtr data)
3292 
3293 {
3294   FuseFormPtr  ffp;
3295 
3296   ffp = (FuseFormPtr) data;
3297   if (ffp != NULL) {
3298     ValNodeFreeData (ffp->head);
3299   }
3300   StdCleanupFormProc (g, data);
3301 }
3302 
FuseFeature(IteM i)3303 extern void FuseFeature (IteM i)
3304 
3305 {
3306   BaseFormPtr        bfp;
3307   ButtoN             b;
3308   GrouP              c;
3309   FeatDefPtr         curr;
3310   FuseFormPtr        ffp;
3311   GrouP              g;
3312   GrouP              h;
3313   ValNodePtr         head;
3314   Uint1              key;
3315   CharPtr            label = NULL;
3316   Int2               listHeight;
3317   SeqEntryPtr        sep;
3318   StdEditorProcsPtr  sepp;
3319   Uint1              subtype;
3320   ValNodePtr         vnp;
3321   WindoW             w;
3322 
3323 #ifdef WIN_MAC
3324   bfp = currentFormDataPtr;
3325 #else
3326   bfp = GetObjectExtra (i);
3327 #endif
3328   if (bfp == NULL) return;
3329   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3330   if (sep == NULL) return;
3331   ffp = (FuseFormPtr) MemNew (sizeof (FuseFormData));
3332   if (ffp == NULL) return;
3333   w = FixedWindow (-50, -33, -10, -10, "Fuse Feature", StdCloseWindowProc);
3334   SetObjectExtra (w, ffp, CleanupFusePage);
3335   ffp->form = (ForM) w;
3336   ffp->formmessage = FuseMessageProc;
3337 
3338   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3339   if (sepp != NULL) {
3340     SetActivate (w, sepp->activateForm);
3341     ffp->appmessage = sepp->handleMessages;
3342   }
3343 
3344   ffp->input_entityID = bfp->input_entityID;
3345   ffp->input_itemID = bfp->input_itemID;
3346   ffp->input_itemtype = bfp->input_itemtype;
3347 
3348   h = HiddenGroup (w, -1, 0, NULL);
3349   SetGroupSpacing (h, 10, 10);
3350 
3351   g = HiddenGroup (h, 0, 2, NULL);
3352   StaticPrompt (g, "Feature", 0, 0, programFont, 'c');
3353   if (indexerVersion) {
3354     listHeight = 16;
3355   } else {
3356     listHeight = 8;
3357   }
3358   ffp->objlist = SingleList (g, 16, listHeight, NULL);
3359   head = NULL;
3360   curr = FeatDefFindNext (NULL, &key, &label, FEATDEF_ANY, TRUE);
3361   while (curr != NULL) {
3362     if (key != FEATDEF_BAD) {
3363       subtype = curr->featdef_key;
3364       if (subtype != FEATDEF_misc_RNA &&
3365           subtype != FEATDEF_precursor_RNA &&
3366           subtype != FEATDEF_mat_peptide &&
3367           subtype != FEATDEF_sig_peptide &&
3368           subtype != FEATDEF_transit_peptide &&
3369           subtype != FEATDEF_Imp_CDS &&
3370           !IsUnwantedFeatureType(subtype)) {
3371         vnp = ValNodeNew (head);
3372         if (head == NULL) {
3373           head = vnp;
3374         }
3375         if (vnp != NULL) {
3376           vnp->choice = subtype;
3377           vnp->data.ptrvalue = StringSave (curr->typelabel);
3378         }
3379       }
3380     }
3381     curr = FeatDefFindNext (curr, &key, &label, FEATDEF_ANY, TRUE);
3382   }
3383   if (head != NULL) {
3384     head = SortValNode (head, SortByVnpChoice);
3385     for (vnp = head; vnp != NULL; vnp = vnp->next) {
3386       ListItem (ffp->objlist, (CharPtr) vnp->data.ptrvalue);
3387     }
3388   }
3389   ffp->head = head;
3390 
3391   ffp->keep_orig_btn = CheckBox (h, "Keep original feature", NULL);
3392 
3393   ffp->constraint_dlg = ComplexConstraintDialog(h, NULL, NULL);
3394   ChangeComplexConstraintFieldType (ffp->constraint_dlg, FieldType_feature_field, NULL, Macro_feature_type_any);
3395 
3396   c = HiddenGroup (h, 4, 0, NULL);
3397   b = DefaultButton (c, "Accept", DoFuseFeature);
3398   SetObjectExtra (b, ffp, NULL);
3399   PushButton (c, "Cancel", StdCancelButtonProc);
3400 
3401   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) ffp->keep_orig_btn, (HANDLE) ffp->constraint_dlg, (HANDLE) c, NULL);
3402   RealizeWindow (w);
3403   Show (w);
3404   Update ();
3405 }
3406 
3407 
3408 
3409 
3410 
3411 typedef struct genomeprojiduserdialog {
3412   DIALOG_MESSAGE_BLOCK
3413   DialoG        ids;
3414 } GenomeprojidUserDialog, PNTR GenomeprojidUserDialogPtr;
3415 
3416 typedef struct genomeprojiduserform {
3417   FEATURE_FORM_BLOCK
3418   SeqEntryPtr   sep;
3419 } GenomeprojidUserForm, PNTR GenomeprojidUserFormPtr;
3420 
UserObjectPtrToGenomeprojidDialog(DialoG d,Pointer data)3421 static void UserObjectPtrToGenomeprojidDialog (DialoG d, Pointer data)
3422 
3423 {
3424   Char                       buf [64];
3425   UserFieldPtr               curr;
3426   ValNodePtr                 head = NULL;
3427   ObjectIdPtr                oip;
3428   Int4                       parentID;
3429   Int4                       projectID;
3430   GenomeprojidUserDialogPtr  rdp;
3431   UserObjectPtr              uop;
3432   Int4                       val;
3433 
3434   rdp = (GenomeprojidUserDialogPtr) GetObjectExtra (d);
3435   if (rdp == NULL) return;
3436   uop = (UserObjectPtr) data;
3437   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "GenomeProjectsDB") != 0) {
3438     PointerToDialog (rdp->ids, NULL);
3439     return;
3440   }
3441   projectID = 0;
3442   parentID = 0;
3443   for (curr = uop->data; curr != NULL; curr = curr->next) {
3444     oip = curr->label;
3445     if (oip == NULL) continue;
3446     if (StringICmp (oip->str, "ProjectID") == 0) {
3447       if (curr->choice == 2) {
3448         val = (Int4) curr->data.intvalue;
3449         if (projectID > 0) {
3450           sprintf (buf, "%ld\t%ld", (long) projectID, (long) parentID);
3451           ValNodeCopyStr (&head, 0, buf);
3452           parentID = 0;
3453         }
3454         projectID = val;
3455       }
3456     } else if (StringICmp (oip->str, "ParentID") == 0) {
3457       if (curr->choice == 2) {
3458         val = (Int4) curr->data.intvalue;
3459         parentID = val;
3460       }
3461     }
3462   }
3463   if (projectID > 0) {
3464     sprintf (buf, "%ld\t%ld", (long) projectID, (long) parentID);
3465     ValNodeCopyStr (&head, 0, buf);
3466   }
3467 
3468   PointerToDialog (rdp->ids, (Pointer) head);
3469   ValNodeFreeData (head);
3470 }
3471 
GenomeprojidDialogToUserObjectPtr(DialoG d)3472 static Pointer GenomeprojidDialogToUserObjectPtr (DialoG d)
3473 
3474 {
3475   Char                       buf [64];
3476   ValNodePtr                 head;
3477   Int4                       parentID;
3478   Int4                       projectID;
3479   CharPtr                    ptr1;
3480   CharPtr                    ptr2;
3481   GenomeprojidUserDialogPtr  rdp;
3482   CharPtr                    str;
3483   UserObjectPtr              uop;
3484   long int                   val;
3485   ValNodePtr                 vnp;
3486 
3487   rdp = (GenomeprojidUserDialogPtr) GetObjectExtra (d);
3488   if (rdp == NULL) return NULL;
3489 
3490   uop = CreateGenomeProjectsDBUserObject ();
3491   if (uop == NULL) return NULL;
3492 
3493   head = (ValNodePtr) DialogToPointer (rdp->ids);
3494   if (head == NULL) return NULL;
3495 
3496   for (vnp = head; vnp != NULL; vnp = vnp->next) {
3497     projectID = 0;
3498     parentID = 0;
3499     str = (CharPtr) vnp->data.ptrvalue;
3500     if (StringHasNoText (str)) continue;
3501     StringNCpy_0 (buf, str, sizeof (buf));
3502     ptr1 = StringChr (buf, '\t');
3503     if (ptr1 != NULL) {
3504       *ptr1 = '\0';
3505       ptr1++;
3506       ptr2 = StringChr (ptr1, '\n');
3507       if (ptr2 == NULL) {
3508         ptr2 = StringChr (ptr1, '\t');
3509       }
3510       if (ptr2 != NULL) {
3511         *ptr2 = '\0';
3512       }
3513       if (sscanf (buf, "%ld", &val) == 1 && val > 0) {
3514         projectID = (Int4) val;
3515         if (sscanf (ptr1, "%ld", &val) == 1 && val > 0) {
3516           parentID = (Int4) val;
3517         }
3518         AddIDsToGenomeProjectsDBUserObject (uop, projectID, parentID);
3519       }
3520     }
3521   }
3522 
3523   ValNodeFreeData (head);
3524 
3525   return uop;
3526 }
3527 
ValNodePtrToGenomeprojidDialog(DialoG d,Pointer data)3528 static void ValNodePtrToGenomeprojidDialog (DialoG d, Pointer data)
3529 
3530 {
3531   ValNodePtr   head;
3532   Int2         j;
3533   ValNodePtr   list;
3534   CharPtr      str;
3535   TagListPtr   tlp;
3536   ValNodePtr   vnp;
3537 
3538   tlp = (TagListPtr) GetObjectExtra (d);
3539   list = (ValNodePtr) data;
3540   if (tlp != NULL) {
3541     head = NULL;
3542     while (list != NULL) {
3543       vnp = ValNodeNew (head);
3544       if (head == NULL) {
3545         head = vnp;
3546       }
3547       if (vnp != NULL) {
3548         str = MemNew (StringLen ((CharPtr) list->data.ptrvalue) + 3);
3549         if (str != NULL) {
3550           StringCpy (str, (CharPtr) list->data.ptrvalue);
3551           StringCat (str, "\n");
3552         }
3553         vnp->data.ptrvalue = str;
3554       }
3555       list = list->next;
3556     }
3557     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
3558     tlp->vnp = head;
3559     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
3560     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
3561     }
3562     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
3563     CorrectBarMax (tlp->bar, tlp->max);
3564     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
3565   }
3566 }
3567 
GenomeprojidDialogToValNodePtr(DialoG d)3568 static Pointer GenomeprojidDialogToValNodePtr (DialoG d)
3569 
3570 {
3571   Char         ch;
3572   ValNodePtr   head;
3573   Int2         j;
3574   Int2         len;
3575   ValNodePtr   list;
3576   Boolean      okay;
3577   CharPtr      str;
3578   TagListPtr   tlp;
3579   ValNodePtr   vnp;
3580 
3581   head = NULL;
3582   tlp = (TagListPtr) GetObjectExtra (d);
3583   if (tlp != NULL && tlp->vnp != NULL) {
3584     list = NULL;
3585     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
3586       str = (CharPtr) vnp->data.ptrvalue;
3587       okay = FALSE;
3588       len = StringLen (str);
3589       for (j = 0; j < len; j++) {
3590         ch = str [j];
3591         if (ch != ' ' && ch != '\t' && ch != '\n') {
3592           okay = TRUE;
3593         }
3594       }
3595       if (okay) {
3596         list = ValNodeNew (list);
3597         if (head == NULL) {
3598           head = list;
3599         }
3600         if (list != NULL) {
3601           list->choice = 0;
3602           list->data.ptrvalue = StringSave (str);
3603         }
3604       }
3605     }
3606   }
3607   return (Pointer) head;
3608 }
3609 
3610 Uint2 genproj_types [] = {
3611   TAGLIST_TEXT, TAGLIST_TEXT
3612 };
3613 
3614 Uint2 genproj_widths [] = {
3615   10, 10, 0
3616 };
3617 
CreateGenomeProjectsDBDialog(GrouP g)3618 static DialoG CreateGenomeProjectsDBDialog (GrouP g)
3619 
3620 {
3621   GrouP                      p;
3622   GenomeprojidUserDialogPtr  rdp;
3623   GrouP                      x;
3624   GrouP                      y;
3625 
3626   p = HiddenGroup (g, -1, 0, NULL);
3627   SetGroupSpacing (p, 10, 10);
3628 
3629   rdp = (GenomeprojidUserDialogPtr) MemNew (sizeof (GenomeprojidUserDialog));
3630   if (rdp == NULL) return NULL;
3631 
3632   SetObjectExtra (p, rdp, NULL);
3633   rdp->dialog = (DialoG) p;
3634   rdp->todialog = UserObjectPtrToGenomeprojidDialog;
3635   rdp->fromdialog = GenomeprojidDialogToUserObjectPtr;
3636 
3637   x = HiddenGroup (p, 0, 2, NULL);
3638   y = HiddenGroup (x, 3, 0, NULL);
3639   StaticPrompt (y, "Project ID", 10 * stdCharWidth, 0, programFont, 'c');
3640   StaticPrompt (y, "Parent ID", 10 * stdCharWidth, 0, programFont, 'c');
3641 
3642   rdp->ids = CreateTagListDialog (x, 3, 2, -1,
3643                                   genproj_types, genproj_widths, NULL,
3644                                   ValNodePtrToGenomeprojidDialog,
3645                                   GenomeprojidDialogToValNodePtr);
3646 
3647   return (DialoG) p;
3648 }
3649 
GenomeProjectsDBUserFormMessage(ForM f,Int2 mssg)3650 static void GenomeProjectsDBUserFormMessage (ForM f, Int2 mssg)
3651 
3652 {
3653   GenomeprojidUserFormPtr  rfp;
3654 
3655   rfp = (GenomeprojidUserFormPtr) GetObjectExtra (f);
3656   if (rfp != NULL) {
3657     switch (mssg) {
3658       case VIB_MSG_CLOSE :
3659         Remove (f);
3660         break;
3661       case VIB_MSG_CUT :
3662         StdCutTextProc (NULL);
3663         break;
3664       case VIB_MSG_COPY :
3665         StdCopyTextProc (NULL);
3666         break;
3667       case VIB_MSG_PASTE :
3668         StdPasteTextProc (NULL);
3669         break;
3670       case VIB_MSG_DELETE :
3671         StdDeleteTextProc (NULL);
3672         break;
3673       default :
3674         if (rfp->appmessage != NULL) {
3675           rfp->appmessage (f, mssg);
3676         }
3677         break;
3678     }
3679   }
3680 }
3681 
CreateGenomeProjectsDBDescForm(Int2 left,Int2 top,Int2 width,Int2 height,CharPtr title,ValNodePtr sdp,SeqEntryPtr sep,FormActnFunc actproc)3682 static ForM CreateGenomeProjectsDBDescForm (Int2 left, Int2 top, Int2 width,
3683                                            Int2 height, CharPtr title, ValNodePtr sdp,
3684                                            SeqEntryPtr sep, FormActnFunc actproc)
3685 
3686 {
3687   ButtoN                   b;
3688   GrouP                    c;
3689   GrouP                    g;
3690   GenomeprojidUserFormPtr  rfp;
3691   StdEditorProcsPtr        sepp;
3692   WindoW                   w;
3693 
3694   w = NULL;
3695   rfp = (GenomeprojidUserFormPtr) MemNew (sizeof (GenomeprojidUserForm));
3696   if (rfp != NULL) {
3697     w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
3698     SetObjectExtra (w, rfp, StdDescFormCleanupProc);
3699     rfp->form = (ForM) w;
3700     rfp->actproc = actproc;
3701     rfp->formmessage = GenomeProjectsDBUserFormMessage;
3702 
3703     rfp->sep = sep;
3704 
3705 #ifndef WIN_MAC
3706     CreateStdEditorFormMenus (w);
3707 #endif
3708     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3709     if (sepp != NULL) {
3710       SetActivate (w, sepp->activateForm);
3711       rfp->appmessage = sepp->handleMessages;
3712     }
3713 
3714     g = HiddenGroup (w, -1, 0, NULL);
3715     rfp->data = CreateGenomeProjectsDBDialog (g);
3716 
3717     c = HiddenGroup (w, 2, 0, NULL);
3718     b = DefaultButton (c, "Accept", StdAcceptFormButtonProc);
3719     SetObjectExtra (b, rfp, NULL);
3720     PushButton (c, "Cancel", StdCancelButtonProc);
3721     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
3722     RealizeWindow (w);
3723   }
3724   return (ForM) w;
3725 }
3726 
3727 extern Int2 LIBCALLBACK GenomeProjectsDBUserGenFunc (Pointer data);
GenomeProjectsDBUserGenFunc(Pointer data)3728 extern Int2 LIBCALLBACK GenomeProjectsDBUserGenFunc (Pointer data)
3729 
3730 {
3731   ObjectIdPtr              oip;
3732   OMProcControlPtr         ompcp;
3733   OMUserDataPtr            omudp;
3734   ObjMgrProcPtr            proc;
3735   GenomeprojidUserFormPtr  rfp;
3736   ValNodePtr               sdp;
3737   SeqEntryPtr              sep;
3738   UserObjectPtr            uop = NULL;
3739   WindoW                   w;
3740 
3741   ompcp = (OMProcControlPtr) data;
3742   w = NULL;
3743   sdp = NULL;
3744   sep = NULL;
3745   uop = NULL;
3746   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
3747   proc = ompcp->proc;
3748   switch (ompcp->input_itemtype) {
3749     case OBJ_SEQDESC :
3750       sdp = (ValNodePtr) ompcp->input_data;
3751       if (sdp != NULL && sdp->choice != Seq_descr_user) {
3752         return OM_MSG_RET_ERROR;
3753       }
3754       if (sdp != NULL) {
3755         uop = (UserObjectPtr) sdp->data.ptrvalue;
3756       }
3757       break;
3758     case OBJ_BIOSEQ :
3759       break;
3760     case OBJ_BIOSEQSET :
3761       break;
3762     case 0 :
3763       break;
3764     default :
3765       return OM_MSG_RET_ERROR;
3766   }
3767   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
3768                                 ompcp->input_itemtype, ompcp->proc->procid);
3769   if (omudp != NULL) {
3770     if (StringCmp (proc->procname, "Edit GenomeProjectsDB User Desc") == 0) {
3771       rfp = (GenomeprojidUserFormPtr) omudp->userdata.ptrvalue;
3772       if (rfp != NULL) {
3773         Select (rfp->form);
3774       }
3775       return OM_MSG_RET_DONE;
3776     } else {
3777       return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
3778     }
3779   }
3780   if (uop != NULL) {
3781     oip = uop->type;
3782     if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
3783     if (StringCmp (oip->str, "GenomeProjectsDB") != 0) return OM_MSG_RET_OK;
3784   }
3785   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
3786   w = (WindoW) CreateGenomeProjectsDBDescForm (-50, -33, -10, -10,
3787                                                "Genome Projects DB", sdp, sep,
3788                                                StdDescFormActnProc);
3789   rfp = (GenomeprojidUserFormPtr) GetObjectExtra (w);
3790   if (rfp != NULL) {
3791     rfp->input_entityID = ompcp->input_entityID;
3792     rfp->input_itemID = ompcp->input_itemID;
3793     rfp->input_itemtype = ompcp->input_itemtype;
3794     rfp->this_itemtype = OBJ_SEQDESC;
3795     rfp->this_subtype = Seq_descr_user;
3796     rfp->procid = ompcp->proc->procid;
3797     rfp->proctype = ompcp->proc->proctype;
3798     rfp->userkey = OMGetNextUserKey ();
3799     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
3800 	                           OMPROC_EDIT, rfp->userkey);
3801     if (omudp != NULL) {
3802       omudp->userdata.ptrvalue = (Pointer) rfp;
3803       omudp->messagefunc = StdVibrantEditorMsgFunc;
3804     }
3805     SendMessageToForm (rfp->form, VIB_MSG_INIT);
3806     if (sdp != NULL) {
3807       PointerToDialog (rfp->data, (Pointer) sdp->data.ptrvalue);
3808       SetClosestParentIfDuplicating ((BaseFormPtr) rfp);
3809     }
3810   }
3811   Show (w);
3812   Select (w);
3813   return OM_MSG_RET_DONE;
3814 }
3815 
3816 
3817 
3818 typedef struct unverifieduserdialog {
3819   DIALOG_MESSAGE_BLOCK
3820   ButtoN  unverified_types[eUnverifiedType_Max];
3821 } UnverifiedUserDialog, PNTR UnverifiedUserDialogPtr;
3822 
3823 typedef struct unverifieduserform {
3824   FEATURE_FORM_BLOCK
3825   SeqEntryPtr   sep;
3826 } UnverifiedUserForm, PNTR UnverifiedUserFormPtr;
3827 
UserObjectPtrToUnverifiedDialog(DialoG d,Pointer data)3828 static void UserObjectPtrToUnverifiedDialog (DialoG d, Pointer data)
3829 
3830 {
3831   UserFieldPtr             curr;
3832   ObjectIdPtr              oip;
3833   UnverifiedUserDialogPtr  rdp;
3834   CharPtr                  str;
3835   UserObjectPtr            uop;
3836   Int4                     i;
3837 
3838   rdp = (UnverifiedUserDialogPtr) GetObjectExtra (d);
3839   if (rdp == NULL) return;
3840   uop = (UserObjectPtr) data;
3841   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "Unverified") != 0) {
3842     return;
3843   }
3844   for (i = 0; i < eUnverifiedType_Max; i++) {
3845     SetStatus (rdp->unverified_types[i], FALSE);
3846   }
3847   for (curr = uop->data; curr != NULL; curr = curr->next) {
3848     oip = curr->label;
3849     if (oip != NULL && StringICmp (oip->str, "Type") == 0) {
3850       if (curr != NULL && curr->choice == 1) {
3851         str = (CharPtr) curr->data.ptrvalue;
3852         for (i = 0; i < eUnverifiedType_Max; i++) {
3853           if (StringICmp (str, GetUnverifiedMatchName (i)) == 0) {
3854             SetStatus (rdp->unverified_types[i], TRUE);
3855             break;
3856           }
3857         }
3858       }
3859     }
3860   }
3861 }
3862 
UnverifiedDialogToUserObjectPtr(DialoG d)3863 static Pointer UnverifiedDialogToUserObjectPtr (DialoG d)
3864 
3865 {
3866   UnverifiedUserDialogPtr  rdp;
3867   UserObjectPtr            uop;
3868   Int4                     i;
3869   Boolean                  any = FALSE;
3870 
3871   rdp = (UnverifiedUserDialogPtr) GetObjectExtra (d);
3872   if (rdp == NULL) return NULL;
3873 
3874   uop = CreateUnverifiedUserObject ();
3875   if (uop == NULL) return NULL;
3876 
3877   for (i = 0; i < eUnverifiedType_Max; i++) {
3878     if (GetStatus (rdp->unverified_types[i])) {
3879       AddStringToUnverifiedUserObject (uop, "Type", GetUnverifiedMatchName (i));
3880       any = TRUE;
3881     }
3882   }
3883   if (!any) {
3884     uop = UserObjectFree (uop);
3885   }
3886 
3887   return uop;
3888 }
3889 
3890 
TestUnverifiedDialog(DialoG d)3891 static ValNodePtr TestUnverifiedDialog (DialoG d)
3892 {
3893   UnverifiedUserDialogPtr  rdp;
3894   ValNodePtr               err = NULL;
3895   Int4                     i;
3896   Boolean                  any = FALSE;
3897 
3898   rdp = (UnverifiedUserDialogPtr) GetObjectExtra (d);
3899   if (rdp == NULL) return NULL;
3900 
3901   for (i = 0; i < eUnverifiedType_Max; i++) {
3902     if (GetStatus (rdp->unverified_types[i])) {
3903       any = TRUE;
3904     }
3905   }
3906   if (!any) {
3907     ValNodeAddPointer (&err, 0, "Must select at least one type of unverified data!");
3908   }
3909 
3910   return err;
3911 }
3912 
3913 
CreateUnverifiedDialog(GrouP g)3914 static DialoG CreateUnverifiedDialog (GrouP g)
3915 
3916 {
3917   GrouP                      p;
3918   UnverifiedUserDialogPtr  rdp;
3919   Int4                     i;
3920 
3921   p = HiddenGroup (g, 1, 0, NULL);
3922   SetGroupSpacing (p, 10, 10);
3923 
3924   rdp = (UnverifiedUserDialogPtr) MemNew (sizeof (UnverifiedUserDialog));
3925   if (rdp == NULL) return NULL;
3926 
3927   SetObjectExtra (p, rdp, NULL);
3928   rdp->dialog = (DialoG) p;
3929   rdp->todialog = UserObjectPtrToUnverifiedDialog;
3930   rdp->fromdialog = UnverifiedDialogToUserObjectPtr;
3931   rdp->testdialog = TestUnverifiedDialog;
3932 
3933   for (i = 0; i < eUnverifiedType_Max; i++) {
3934     rdp->unverified_types[i] = CheckBox (p, GetUnverifiedMatchName (i), NULL);
3935   }
3936 
3937   return (DialoG) p;
3938 }
3939 
UnverifiedUserFormMessage(ForM f,Int2 mssg)3940 static void UnverifiedUserFormMessage (ForM f, Int2 mssg)
3941 
3942 {
3943   UnverifiedUserFormPtr  rfp;
3944 
3945   rfp = (UnverifiedUserFormPtr) GetObjectExtra (f);
3946   if (rfp != NULL) {
3947     switch (mssg) {
3948       case VIB_MSG_CLOSE :
3949         Remove (f);
3950         break;
3951       case VIB_MSG_CUT :
3952         StdCutTextProc (NULL);
3953         break;
3954       case VIB_MSG_COPY :
3955         StdCopyTextProc (NULL);
3956         break;
3957       case VIB_MSG_PASTE :
3958         StdPasteTextProc (NULL);
3959         break;
3960       case VIB_MSG_DELETE :
3961         StdDeleteTextProc (NULL);
3962         break;
3963       default :
3964         if (rfp->appmessage != NULL) {
3965           rfp->appmessage (f, mssg);
3966         }
3967         break;
3968     }
3969   }
3970 }
3971 
3972 
AcceptUnverifiedDescForm(ButtoN b)3973 static void AcceptUnverifiedDescForm (ButtoN b)
3974 {
3975   UnverifiedUserFormPtr  rfp;
3976   ValNodePtr err;
3977 
3978   rfp = (UnverifiedUserFormPtr) GetObjectExtra (b);
3979   if (rfp == NULL) {
3980     return;
3981   }
3982   err = TestDialog (rfp->data);
3983   if (err != NULL) {
3984     Message (MSG_ERROR, "%s", err->data.ptrvalue);
3985     err = ValNodeFree (err);
3986     return;
3987   }
3988   StdAcceptFormButtonProc (b);
3989 }
3990 
3991 
CreateUnverifiedDescForm(Int2 left,Int2 top,Int2 width,Int2 height,CharPtr title,ValNodePtr sdp,SeqEntryPtr sep,FormActnFunc actproc)3992 static ForM CreateUnverifiedDescForm (Int2 left, Int2 top, Int2 width,
3993                                       Int2 height, CharPtr title, ValNodePtr sdp,
3994                                       SeqEntryPtr sep, FormActnFunc actproc)
3995 
3996 {
3997   ButtoN                 b;
3998   GrouP                  c;
3999   GrouP                  g;
4000   UnverifiedUserFormPtr  rfp;
4001   StdEditorProcsPtr      sepp;
4002   WindoW                 w;
4003 
4004   w = NULL;
4005   rfp = (UnverifiedUserFormPtr) MemNew (sizeof (UnverifiedUserForm));
4006   if (rfp != NULL) {
4007     w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
4008     SetObjectExtra (w, rfp, StdDescFormCleanupProc);
4009     rfp->form = (ForM) w;
4010     rfp->actproc = actproc;
4011     rfp->formmessage = UnverifiedUserFormMessage;
4012 
4013     rfp->sep = sep;
4014 
4015 #ifndef WIN_MAC
4016     CreateStdEditorFormMenus (w);
4017 #endif
4018     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
4019     if (sepp != NULL) {
4020       SetActivate (w, sepp->activateForm);
4021       rfp->appmessage = sepp->handleMessages;
4022     }
4023 
4024     g = HiddenGroup (w, -1, 0, NULL);
4025     rfp->data = CreateUnverifiedDialog (g);
4026 
4027     c = HiddenGroup (w, 2, 0, NULL);
4028     b = DefaultButton (c, "Accept", AcceptUnverifiedDescForm);
4029     SetObjectExtra (b, rfp, NULL);
4030     PushButton (c, "Cancel", StdCancelButtonProc);
4031     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
4032     RealizeWindow (w);
4033   }
4034   return (ForM) w;
4035 }
4036 
4037 extern Int2 LIBCALLBACK UnverifiedUserGenFunc (Pointer data);
UnverifiedUserGenFunc(Pointer data)4038 extern Int2 LIBCALLBACK UnverifiedUserGenFunc (Pointer data)
4039 
4040 {
4041   ObjectIdPtr            oip;
4042   OMProcControlPtr       ompcp;
4043   OMUserDataPtr          omudp;
4044   ObjMgrProcPtr          proc;
4045   UnverifiedUserFormPtr  rfp;
4046   ValNodePtr             sdp;
4047   SeqEntryPtr            sep;
4048   UserObjectPtr          uop = NULL;
4049   WindoW                 w;
4050 
4051   ompcp = (OMProcControlPtr) data;
4052   w = NULL;
4053   sdp = NULL;
4054   sep = NULL;
4055   uop = NULL;
4056   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
4057   proc = ompcp->proc;
4058   switch (ompcp->input_itemtype) {
4059     case OBJ_SEQDESC :
4060       sdp = (ValNodePtr) ompcp->input_data;
4061       if (sdp != NULL && sdp->choice != Seq_descr_user) {
4062         return OM_MSG_RET_ERROR;
4063       }
4064       if (sdp != NULL) {
4065         uop = (UserObjectPtr) sdp->data.ptrvalue;
4066       }
4067       break;
4068     case OBJ_BIOSEQ :
4069       break;
4070     case OBJ_BIOSEQSET :
4071       break;
4072     case 0 :
4073       break;
4074     default :
4075       return OM_MSG_RET_ERROR;
4076   }
4077   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
4078                                 ompcp->input_itemtype, ompcp->proc->procid);
4079   if (omudp != NULL) {
4080     if (StringCmp (proc->procname, "Edit Unverified User Desc") == 0) {
4081       rfp = (UnverifiedUserFormPtr) omudp->userdata.ptrvalue;
4082       if (rfp != NULL) {
4083         Select (rfp->form);
4084       }
4085       return OM_MSG_RET_DONE;
4086     } else {
4087       return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
4088     }
4089   }
4090   if (uop != NULL) {
4091     oip = uop->type;
4092     if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
4093     if (StringCmp (oip->str, "Unverified") != 0) return OM_MSG_RET_OK;
4094   }
4095   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
4096   w = (WindoW) CreateUnverifiedDescForm (-50, -33, -10, -10,
4097                                                "Unverified", sdp, sep,
4098                                                StdDescFormActnProc);
4099   rfp = (UnverifiedUserFormPtr) GetObjectExtra (w);
4100   if (rfp != NULL) {
4101     rfp->input_entityID = ompcp->input_entityID;
4102     rfp->input_itemID = ompcp->input_itemID;
4103     rfp->input_itemtype = ompcp->input_itemtype;
4104     rfp->this_itemtype = OBJ_SEQDESC;
4105     rfp->this_subtype = Seq_descr_user;
4106     rfp->procid = ompcp->proc->procid;
4107     rfp->proctype = ompcp->proc->proctype;
4108     rfp->userkey = OMGetNextUserKey ();
4109     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
4110 	                           OMPROC_EDIT, rfp->userkey);
4111     if (omudp != NULL) {
4112       omudp->userdata.ptrvalue = (Pointer) rfp;
4113       omudp->messagefunc = StdVibrantEditorMsgFunc;
4114     }
4115     SendMessageToForm (rfp->form, VIB_MSG_INIT);
4116     if (sdp != NULL) {
4117       PointerToDialog (rfp->data, (Pointer) sdp->data.ptrvalue);
4118       SetClosestParentIfDuplicating ((BaseFormPtr) rfp);
4119     }
4120   }
4121   Show (w);
4122   Select (w);
4123   return OM_MSG_RET_DONE;
4124 }
4125 
4126 
4127 
4128 
4129 typedef struct replaceuserobject {
4130   UserObjectPtr   deleteThis;
4131   UserObjectPtr   replaceWith;
4132 } ReplaceUserObjectData, PNTR ReplaceUserObjectPtr;
4133 
4134 
ReplaceAllUserObjectsCallback(SeqDescrPtr sdp,Pointer data)4135 static void ReplaceAllUserObjectsCallback (SeqDescrPtr sdp, Pointer data)
4136 
4137 {
4138   ReplaceUserObjectPtr   rp;
4139 
4140   if ((rp = (ReplaceUserObjectPtr) data) == NULL || sdp == NULL || sdp->choice != Seq_descr_user) {
4141     return;
4142   }
4143 
4144   if (AsnIoMemComp (sdp->data.ptrvalue, rp->deleteThis, (AsnWriteFunc) UserObjectAsnWrite)) {
4145     sdp->data.ptrvalue = UserObjectFree (sdp->data.ptrvalue);
4146     sdp->data.ptrvalue = AsnIoMemCopy (rp->replaceWith, (AsnReadFunc) UserObjectAsnRead, (AsnWriteFunc) UserObjectAsnWrite);
4147   }
4148 }
4149 
4150 
4151 typedef struct dblinkdialog {
4152   DIALOG_MESSAGE_BLOCK
4153   DialoG  traceassm;
4154   DialoG  biosample;
4155   DialoG  probedb;
4156   DialoG  seqreadarch;
4157   DialoG  bioproject;
4158   DialoG  assembly;
4159 } DblinkDialog, PNTR DblinkDialogPtr;
4160 
GetStringListFromField(UserFieldPtr curr)4161 static ValNodePtr GetStringListFromField (UserFieldPtr curr)
4162 {
4163   ValNodePtr head = NULL;
4164   CharPtr PNTR cpp;
4165   CharPtr str;
4166   Int4    num, i, val;
4167   Int4Ptr ip;
4168   Char    buf [32];
4169 
4170   if (curr->choice == 1) {
4171     str = (CharPtr) curr->data.ptrvalue;;
4172     if (StringDoesHaveText (str)) {
4173       ValNodeCopyStr (&head, 0, str);
4174     }
4175   } else if (curr->choice == 2) {
4176     val = (Int4) curr->data.intvalue;
4177     if (val > 0) {
4178       sprintf (buf, "%ld", (long) val);
4179       ValNodeCopyStr (&head, 0, buf);
4180     }
4181   } else if (curr->choice == 7) {
4182     num = curr->num;
4183     cpp = (CharPtr PNTR) curr->data.ptrvalue;
4184     if (num > 0 && cpp != NULL) {
4185       for (i = 0; i < num; i++) {
4186         str = cpp [i];
4187         if (StringDoesHaveText (str)) {
4188           ValNodeCopyStr (&head, 0, str);
4189         }
4190       }
4191     }
4192   } else if (curr->choice == 8) {
4193     num = curr->num;
4194     ip = (Int4Ptr) curr->data.ptrvalue;
4195     if (num > 0 && ip != NULL) {
4196       head = NULL;
4197       for (i = 0; i < num; i++) {
4198         val = ip [i];
4199         if (val > 0) {
4200           sprintf (buf, "%ld", (long) val);
4201           ValNodeCopyStr (&head, 0, buf);
4202         }
4203       }
4204     }
4205   }
4206 
4207   return head;
4208 }
4209 
4210 
4211 typedef struct dblinkform {
4212   FEATURE_FORM_BLOCK
4213   SeqEntryPtr   sep;
4214 } DblinkForm, PNTR DblinkFormPtr;
4215 
UserObjectPtrToDblinkDialog(DialoG d,Pointer data)4216 static void UserObjectPtrToDblinkDialog (
4217   DialoG d,
4218   Pointer data
4219 )
4220 
4221 {
4222   UserFieldPtr     curr;
4223   DblinkDialogPtr  ddp;
4224   ValNodePtr       head;
4225   ObjectIdPtr      oip;
4226   UserObjectPtr    uop;
4227 
4228   ddp = (DblinkDialogPtr) GetObjectExtra (d);
4229   if (ddp == NULL) return;
4230 
4231   uop = (UserObjectPtr) data;
4232   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "DBLink") != 0) {
4233     PointerToDialog (ddp->traceassm, NULL);
4234     PointerToDialog (ddp->biosample, NULL);
4235     PointerToDialog (ddp->probedb, NULL);
4236     PointerToDialog (ddp->seqreadarch, NULL);
4237     PointerToDialog (ddp->bioproject, NULL);
4238     PointerToDialog (ddp->assembly, NULL);
4239     return;
4240   }
4241 
4242   for (curr = uop->data; curr != NULL; curr = curr->next) {
4243     oip = curr->label;
4244     if (oip == NULL) continue;
4245     if (StringICmp (oip->str, "Trace Assembly Archive") == 0) {
4246       head = GetStringListFromField(curr);
4247       PointerToDialog (ddp->traceassm, (Pointer) head);
4248       head = ValNodeFreeData (head);
4249     } else if (StringICmp (oip->str, "BioSample") == 0) {
4250       head = GetStringListFromField(curr);
4251       PointerToDialog (ddp->biosample, (Pointer) head);
4252       head = ValNodeFreeData (head);
4253     } else if (StringICmp (oip->str, "ProbeDB") == 0) {
4254       head = GetStringListFromField(curr);
4255       PointerToDialog (ddp->probedb, (Pointer) head);
4256       head = ValNodeFreeData (head);
4257     } else if (StringICmp (oip->str, "Sequence Read Archive") == 0) {
4258       head = GetStringListFromField(curr);
4259       PointerToDialog (ddp->seqreadarch, (Pointer) head);
4260       head = ValNodeFreeData (head);
4261     } else if (StringICmp (oip->str, "BioProject") == 0) {
4262       head = GetStringListFromField(curr);
4263       PointerToDialog (ddp->bioproject, (Pointer) head);
4264       head = ValNodeFreeData (head);
4265     } else if (StringICmp (oip->str, "Assembly") == 0) {
4266       head = GetStringListFromField(curr);
4267       PointerToDialog (ddp->assembly, (Pointer) head);
4268       head = ValNodeFreeData (head);
4269     }
4270   }
4271 }
4272 
4273 
GetStringsFromList(DialoG strings,CharPtr field_name,UserObjectPtr uop)4274 static Boolean GetStringsFromList (DialoG strings, CharPtr field_name, UserObjectPtr uop)
4275 {
4276   CharPtr PNTR     cpp;
4277   ValNodePtr       head, vnp;
4278   Int4             i, num;
4279   Boolean          okay = FALSE;
4280   CharPtr          str;
4281 
4282   head = (ValNodePtr) DialogToPointer (strings);
4283   if (head != NULL) {
4284     num = 0;
4285     for (vnp = head; vnp != NULL; vnp = vnp->next) {
4286       str = (CharPtr) vnp->data.ptrvalue;
4287       if (StringHasNoText (str)) continue;
4288       num++;
4289     }
4290     if (num > 0) {
4291       cpp = (CharPtr PNTR) MemNew (sizeof (CharPtr) * num);
4292       if (cpp != NULL) {
4293         i = 0;
4294         for (vnp = head; vnp != NULL; vnp = vnp->next) {
4295           str = (CharPtr) vnp->data.ptrvalue;
4296           if (StringHasNoText (str)) continue;
4297           cpp [i] = str;
4298           i++;
4299         }
4300         if (i > 0) {
4301           AddStringListFieldToDBLinkUserObject (uop, i, cpp, field_name);
4302           okay = TRUE;
4303         }
4304       }
4305     }
4306   }
4307   ValNodeFreeData (head);
4308   return okay;
4309 }
4310 
4311 
GetIntsFromList(DialoG strings,CharPtr field_name,UserObjectPtr uop)4312 static Boolean GetIntsFromList (DialoG strings, CharPtr field_name, UserObjectPtr uop)
4313 {
4314   ValNodePtr       head, vnp;
4315   Int4             i, num;
4316   Int4Ptr          ipp;
4317   Boolean          okay = FALSE;
4318   CharPtr          str;
4319   long int         val;
4320 
4321   head = (ValNodePtr) DialogToPointer (strings);
4322   if (head != NULL) {
4323     num = 0;
4324     for (vnp = head; vnp != NULL; vnp = vnp->next) {
4325       str = (CharPtr) vnp->data.ptrvalue;
4326       if (StringHasNoText (str)) continue;
4327       num++;
4328     }
4329     if (num > 0) {
4330       ipp = (Int4Ptr) MemNew (sizeof (Int4) * num);
4331       if (ipp != NULL) {
4332         i = 0;
4333         for (vnp = head; vnp != NULL; vnp = vnp->next) {
4334           str = (CharPtr) vnp->data.ptrvalue;
4335           if (StringHasNoText (str)) continue;
4336           if (sscanf (str, "%ld", &val) == 1) {
4337             ipp [i] = (Int4) val;
4338             i++;
4339           }
4340         }
4341         if (i > 0) {
4342           AddIntListFieldToDBLinkUserObject(uop, i, ipp, field_name);
4343           okay = TRUE;
4344         }
4345       }
4346     }
4347   }
4348   ValNodeFreeData (head);
4349   return okay;
4350 }
4351 
4352 
DblinkDialogToUserObjectPtr(DialoG d)4353 static Pointer DblinkDialogToUserObjectPtr (
4354   DialoG d
4355 )
4356 
4357 {
4358   DblinkDialogPtr  ddp;
4359   Boolean          okay = FALSE;
4360   UserObjectPtr    uop;
4361 
4362   ddp = (DblinkDialogPtr) GetObjectExtra (d);
4363   if (ddp == NULL) return NULL;
4364 
4365   uop = CreateDBLinkUserObject ();
4366   if (uop == NULL) return NULL;
4367 
4368   okay |= GetStringsFromList(ddp->bioproject, "BioProject", uop);
4369   okay |= GetStringsFromList(ddp->biosample, "BioSample", uop);
4370   okay |= GetStringsFromList(ddp->probedb, "ProbeDB", uop);
4371   okay |= GetStringsFromList(ddp->seqreadarch, "Sequence Read Archive", uop);
4372   okay |= GetIntsFromList(ddp->traceassm, "Trace Assembly Archive", uop);
4373   okay |= GetStringsFromList(ddp->assembly, "Assembly", uop);
4374 
4375   if (! okay) {
4376     uop = UserObjectFree (uop);
4377   }
4378 
4379   return uop;
4380 }
4381 
CreateDblinkDialog(GrouP g)4382 static DialoG CreateDblinkDialog (
4383   GrouP g
4384 )
4385 
4386 {
4387   DblinkDialogPtr  ddp;
4388   GrouP            p, x;
4389 
4390   p = HiddenGroup (g, -1, 0, NULL);
4391   SetGroupSpacing (p, 10, 10);
4392 
4393   ddp = (DblinkDialogPtr) MemNew (sizeof (DblinkDialog));
4394   if (ddp == NULL) return NULL;
4395 
4396   SetObjectExtra (p, ddp, NULL);
4397   ddp->dialog = (DialoG) p;
4398   ddp->todialog = UserObjectPtrToDblinkDialog;
4399   ddp->fromdialog = DblinkDialogToUserObjectPtr;
4400 
4401   x = HiddenGroup (p, 0, 12, NULL);
4402 
4403   StaticPrompt (x, "BioProject", 10 * stdCharWidth, 0, programFont, 'c');
4404   ddp->bioproject = CreateVisibleStringDialog (x, 3, -1, 15);
4405 
4406   StaticPrompt (x, "BioSample", 10 * stdCharWidth, 0, programFont, 'c');
4407   ddp->biosample = CreateVisibleStringDialog (x, 3, -1, 15);
4408 
4409   StaticPrompt (x, "ProbeDB", 10 * stdCharWidth, 0, programFont, 'c');
4410   ddp->probedb = CreateVisibleStringDialog (x, 3, -1, 15);
4411 
4412   StaticPrompt (x, "Trace Assembly", 10 * stdCharWidth, 0, programFont, 'c');
4413   ddp->traceassm = CreateVisibleStringDialog (x, 3, -1, 15);
4414 
4415   StaticPrompt (x, "Sequence Read Archive", 10 * stdCharWidth, 0, programFont, 'c');
4416   ddp->seqreadarch = CreateVisibleStringDialog (x, 3, -1, 15);
4417 
4418   StaticPrompt (x, "Assembly", 10 * stdCharWidth, 0, programFont, 'c');
4419   ddp->assembly = CreateVisibleStringDialog (x, 3, -1, 15);
4420 
4421   return (DialoG) p;
4422 }
4423 
DblinkFormMessage(ForM f,Int2 mssg)4424 static void DblinkFormMessage (
4425   ForM f,
4426   Int2 mssg
4427 )
4428 
4429 {
4430   DblinkFormPtr  dfp;
4431 
4432   dfp = (DblinkFormPtr) GetObjectExtra (f);
4433   if (dfp != NULL) {
4434     switch (mssg) {
4435       case VIB_MSG_CLOSE :
4436         Remove (f);
4437         break;
4438       case VIB_MSG_CUT :
4439         StdCutTextProc (NULL);
4440         break;
4441       case VIB_MSG_COPY :
4442         StdCopyTextProc (NULL);
4443         break;
4444       case VIB_MSG_PASTE :
4445         StdPasteTextProc (NULL);
4446         break;
4447       case VIB_MSG_DELETE :
4448         StdDeleteTextProc (NULL);
4449         break;
4450       default :
4451         if (dfp->appmessage != NULL) {
4452           dfp->appmessage (f, mssg);
4453         }
4454         break;
4455     }
4456   }
4457 }
4458 
4459 
ReplaceAllDBLinksButtonProc(ButtoN b)4460 static void ReplaceAllDBLinksButtonProc (ButtoN b)
4461 {
4462   DblinkFormPtr      dfp;
4463   SeqEntryPtr   sep;
4464   ReplaceUserObjectData rd;
4465   SeqDescrPtr       sdp_orig;
4466   SeqMgrDescContext context;
4467 
4468   dfp = (DblinkFormPtr) GetObjectExtra (b);
4469   if (dfp == NULL) {
4470     return;
4471   }
4472 
4473   rd.replaceWith = DialogToPointer (dfp->data);
4474   if (rd.replaceWith == NULL) {
4475     Message (MSG_ERROR, "Must supply text!");
4476     rd.replaceWith = UserObjectFree (rd.replaceWith);
4477     return;
4478   }
4479 
4480   sdp_orig = SeqMgrGetDesiredDescriptor (dfp->input_entityID, NULL, dfp->input_itemID, 0, NULL, &context);
4481   if (sdp_orig == NULL || sdp_orig->choice != Seq_descr_user) {
4482     Message (MSG_ERROR, "Unable to find original descriptor!");
4483     Remove (dfp->form);
4484     rd.replaceWith = UserObjectFree (rd.replaceWith);
4485     return;
4486   }
4487   rd.deleteThis = AsnIoMemCopy (sdp_orig->data.ptrvalue, (AsnReadFunc)UserObjectAsnRead, (AsnWriteFunc) UserObjectAsnWrite);
4488 
4489   sep = GetTopSeqEntryForEntityID (dfp->input_entityID);
4490   VisitDescriptorsInSep (sep, &rd, ReplaceAllUserObjectsCallback);
4491 
4492   rd.deleteThis = UserObjectFree (rd.deleteThis);
4493   rd.replaceWith = UserObjectFree (rd.replaceWith);
4494 
4495   ObjMgrSetDirtyFlag (dfp->input_entityID, TRUE);
4496   ObjMgrSendMsg (OM_MSG_UPDATE, dfp->input_entityID,
4497                   dfp->input_itemID, dfp->input_itemtype);
4498   Remove (dfp->form);
4499 }
4500 
4501 
CreateDblinkDescForm(Int2 left,Int2 top,Int2 width,Int2 height,CharPtr title,ValNodePtr sdp,SeqEntryPtr sep,FormActnFunc actproc)4502 static ForM CreateDblinkDescForm (
4503   Int2 left,
4504   Int2 top,
4505   Int2 width,
4506   Int2 height,
4507   CharPtr title,
4508   ValNodePtr sdp,
4509   SeqEntryPtr sep,
4510   FormActnFunc actproc
4511 )
4512 
4513 {
4514   ButtoN             b;
4515   DblinkFormPtr      dfp;
4516   GrouP              c, g;
4517   StdEditorProcsPtr  sepp;
4518   WindoW             w;
4519 
4520   w = NULL;
4521   dfp = (DblinkFormPtr) MemNew (sizeof (DblinkForm));
4522 
4523   if (dfp != NULL) {
4524     w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
4525     SetObjectExtra (w, dfp, StdDescFormCleanupProc);
4526     dfp->form = (ForM) w;
4527     dfp->actproc = actproc;
4528     dfp->formmessage = DblinkFormMessage;
4529 
4530     dfp->sep = sep;
4531 
4532 #ifndef WIN_MAC
4533     CreateStdEditorFormMenus (w);
4534 #endif
4535     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
4536     if (sepp != NULL) {
4537       SetActivate (w, sepp->activateForm);
4538       dfp->appmessage = sepp->handleMessages;
4539     }
4540 
4541     g = HiddenGroup (w, -1, 0, NULL);
4542     dfp->data = CreateDblinkDialog (g);
4543 
4544     c = HiddenGroup (w, 3, 0, NULL);
4545 
4546     if (sdp == NULL) {
4547       b = DefaultButton (c, "Accept", StdAcceptFormButtonProc);
4548       SetObjectExtra (b, dfp, NULL);
4549     } else {
4550       b = PushButton (c, "Replace All", ReplaceAllDBLinksButtonProc);
4551       SetObjectExtra (b, dfp, NULL);
4552       b = DefaultButton (c, "Replace This", StdAcceptFormButtonProc);
4553       SetObjectExtra (b, dfp, NULL);
4554     }
4555 
4556     PushButton (c, "Cancel", StdCancelButtonProc);
4557     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
4558     RealizeWindow (w);
4559   }
4560 
4561   return (ForM) w;
4562 }
4563 
4564 extern Int2 LIBCALLBACK DBlinkUserGenFunc (Pointer data);
DBlinkUserGenFunc(Pointer data)4565 extern Int2 LIBCALLBACK DBlinkUserGenFunc (Pointer data)
4566 
4567 {
4568   ObjectIdPtr              oip;
4569   OMProcControlPtr         ompcp;
4570   OMUserDataPtr            omudp;
4571   ObjMgrProcPtr            proc;
4572   DblinkFormPtr            dfp;
4573   ValNodePtr               sdp;
4574   SeqEntryPtr              sep;
4575   UserObjectPtr            uop = NULL;
4576   WindoW                   w;
4577 
4578   ompcp = (OMProcControlPtr) data;
4579   w = NULL;
4580   sdp = NULL;
4581   sep = NULL;
4582   uop = NULL;
4583   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
4584   proc = ompcp->proc;
4585   switch (ompcp->input_itemtype) {
4586     case OBJ_SEQDESC :
4587       sdp = (ValNodePtr) ompcp->input_data;
4588       if (sdp != NULL && sdp->choice != Seq_descr_user) {
4589         return OM_MSG_RET_ERROR;
4590       }
4591       if (sdp != NULL) {
4592         uop = (UserObjectPtr) sdp->data.ptrvalue;
4593       }
4594       break;
4595     case OBJ_BIOSEQ :
4596       break;
4597     case OBJ_BIOSEQSET :
4598       break;
4599     case 0 :
4600       break;
4601     default :
4602       return OM_MSG_RET_ERROR;
4603   }
4604   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
4605                                 ompcp->input_itemtype, ompcp->proc->procid);
4606   if (omudp != NULL) {
4607     if (StringCmp (proc->procname, "Edit DBLink User Desc") == 0) {
4608       dfp = (DblinkFormPtr) omudp->userdata.ptrvalue;
4609       if (dfp != NULL) {
4610         Select (dfp->form);
4611       }
4612       return OM_MSG_RET_DONE;
4613     } else {
4614       return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
4615     }
4616   }
4617   if (uop != NULL) {
4618     oip = uop->type;
4619     if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
4620     if (StringCmp (oip->str, "DBLink") != 0) return OM_MSG_RET_OK;
4621   }
4622   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
4623   w = (WindoW) CreateDblinkDescForm (-50, -33, -10, -10,
4624                                      "DBLink", sdp, sep,
4625                                      StdDescFormActnProc);
4626   dfp = (DblinkFormPtr) GetObjectExtra (w);
4627   if (dfp != NULL) {
4628     dfp->input_entityID = ompcp->input_entityID;
4629     dfp->input_itemID = ompcp->input_itemID;
4630     dfp->input_itemtype = ompcp->input_itemtype;
4631     dfp->this_itemtype = OBJ_SEQDESC;
4632     dfp->this_subtype = Seq_descr_user;
4633     dfp->procid = ompcp->proc->procid;
4634     dfp->proctype = ompcp->proc->proctype;
4635     dfp->userkey = OMGetNextUserKey ();
4636     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
4637 	                           OMPROC_EDIT, dfp->userkey);
4638     if (omudp != NULL) {
4639       omudp->userdata.ptrvalue = (Pointer) dfp;
4640       omudp->messagefunc = StdVibrantEditorMsgFunc;
4641     }
4642     SendMessageToForm (dfp->form, VIB_MSG_INIT);
4643     if (sdp != NULL) {
4644       PointerToDialog (dfp->data, (Pointer) sdp->data.ptrvalue);
4645       SetClosestParentIfDuplicating ((BaseFormPtr) dfp);
4646     }
4647   }
4648   Show (w);
4649   Select (w);
4650   return OM_MSG_RET_DONE;
4651 }
4652 
4653 
4654 extern Int2 LIBCALLBACK RefGeneUserGenFunc (Pointer data);
4655 
4656 #define REFGENE_ASSEMBLY   1
4657 #define REFGENE_RELATED    2
4658 #define REFGENE_SPLICEVAR  3
4659 #define REFGENE_RELDREK    4
4660 #define REFGENE_REJECT     5
4661 #define REFGENE_IDENTICAL  6
4662 #define REFGENE_UNKNOWN    7
4663 
4664 typedef struct refgeneuserdialog {
4665   DIALOG_MESSAGE_BLOCK
4666   GrouP         status;
4667   ButtoN        generated;
4668   TexT          curator;
4669   TexT          url;
4670   TexT          source;
4671   Int2          indexer;
4672   DialoG        fields;
4673   ButtoN        pipebtn;
4674 } RefgeneUserDialog, PNTR RefgeneUserDialogPtr;
4675 
4676 typedef struct refgeneuserform {
4677   FEATURE_FORM_BLOCK
4678   SeqEntryPtr   sep;
4679 } RefgeneUserForm, PNTR RefgeneUserFormPtr;
4680 
ENUM_ALIST(refgene_alist)4681 static ENUM_ALIST(refgene_alist)
4682   {" ",          0},
4683   {"Assembly",    REFGENE_ASSEMBLY},
4684   {"Related",     REFGENE_RELATED},
4685   {"SpliceVar",   REFGENE_SPLICEVAR},
4686   {"RelatedDrek", REFGENE_RELDREK},
4687   {"Reject",      REFGENE_REJECT},
4688   {"Identical",   REFGENE_IDENTICAL},
4689   {"Unknown",     REFGENE_UNKNOWN},
4690 END_ENUM_ALIST
4691 
4692 static Uint2 refgene_types [] = {
4693   TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_POPUP
4694 };
4695 
4696 static Uint2 refgene_widths [] = {
4697   9, 7, 7, 7, 8, 0
4698 };
4699 
4700 static EnumFieldAssocPtr refgene_popups [] = {
4701   NULL, NULL, NULL, NULL, NULL, refgene_alist
4702 };
4703 
4704 static CharPtr refgene_labels [] = {
4705   "", "Assembly", "Related", "SpliceVar", "RelatedDrek", "Reject", "IdenticalTo", "Unknown", NULL
4706 };
4707 
4708 static CharPtr refgene_fields [] = {
4709   "Accession", "GI", "Start", "Stop", "Comment", "Type", NULL
4710 };
4711 
AccessionUserFieldPtrToVisStringDialog(DialoG d,Pointer data)4712 static void AccessionUserFieldPtrToVisStringDialog (DialoG d, Pointer data)
4713 
4714 {
4715   CharPtr       accession;
4716   CharPtr       comment;
4717   UserFieldPtr  curr;
4718   UserFieldPtr  entry;
4719   Int2          field;
4720   Char          fm [16];
4721   Int4          from;
4722   Int4          gi;
4723   ValNodePtr    head;
4724   Int2          i;
4725   Int2          j;
4726   CharPtr       name;
4727   ObjectIdPtr   oip;
4728   CharPtr       str;
4729   TagListPtr    tlp;
4730   Int4          to;
4731   Char          tu [16];
4732   UserFieldPtr  ufp;
4733   ValNodePtr    vnp;
4734 
4735   tlp = (TagListPtr) GetObjectExtra (d);
4736   if (tlp == NULL) return;
4737   str = MemNew (sizeof (Char) * 1024);
4738   head = NULL;
4739   curr = (UserFieldPtr) data;
4740   while (curr != NULL) {
4741     oip = curr->label;
4742     if (oip != NULL) {
4743       field = 0;
4744       for (i = REFGENE_ASSEMBLY; i <= REFGENE_UNKNOWN; i++) {
4745         if (StringICmp (oip->str, refgene_labels [i]) == 0 && curr->choice == 11) {
4746           field = i;
4747         }
4748       }
4749       if (field > 0) {
4750         entry = (UserFieldPtr) curr->data.ptrvalue;
4751         while (entry != NULL && entry->choice == 11) {
4752           accession = NULL;
4753           comment = NULL;
4754           name = NULL;
4755           gi = 0;
4756           from = 0;
4757           to = 0;
4758           ufp = (UserFieldPtr) entry->data.ptrvalue;
4759           while (ufp != NULL) {
4760             oip = ufp->label;
4761             if (oip != NULL && oip->str != NULL) {
4762               if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
4763                 accession = (CharPtr) ufp->data.ptrvalue;
4764               } else if (StringICmp (oip->str, "gi") == 0 && ufp->choice == 2) {
4765                 gi = ufp->data.intvalue;
4766               } else if (StringICmp (oip->str, "from") == 0 && ufp->choice == 2) {
4767                 from = ufp->data.intvalue;
4768               } else if (StringICmp (oip->str, "to") == 0 && ufp->choice == 2) {
4769                 to = ufp->data.intvalue;
4770               } else if (StringICmp (oip->str, "comment") == 0 && ufp->choice == 1) {
4771                 comment = (CharPtr) ufp->data.ptrvalue;
4772               } else if (StringICmp (oip->str, "name") == 0 && ufp->choice == 1) {
4773                 name = (CharPtr) ufp->data.ptrvalue;
4774               }
4775             }
4776             ufp = ufp->next;
4777           }
4778           if (accession != NULL) {
4779             if (comment == NULL) {
4780               comment = "";
4781             }
4782             fm [0] = '\0';
4783             tu [0] = '\0';
4784             if (from > 0 && to > 0) {
4785               sprintf (fm, "%ld", (long) from);
4786               sprintf (tu, "%ld", (long) to);
4787             }
4788             sprintf (str, "%s\t%ld\t%s\t%s\t%s\t%d\n", accession,
4789                      (long) gi, fm, tu, comment, (int) field);
4790             vnp = ValNodeNew (head);
4791             if (head == NULL) {
4792               head = vnp;
4793             }
4794             if (vnp != NULL) {
4795               vnp->data.ptrvalue = StringSave (str);
4796             }
4797           } else if (name != NULL) {
4798             sprintf (str, "\t\t\t\t%s\t%d\n", name, (int) field);
4799             vnp = ValNodeNew (head);
4800             if (head == NULL) {
4801               head = vnp;
4802             }
4803             if (vnp != NULL) {
4804               vnp->data.ptrvalue = StringSave (str);
4805             }
4806           }
4807           entry = entry->next;
4808         }
4809       }
4810     }
4811     curr = curr->next;
4812   }
4813   MemFree (str);
4814   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
4815   tlp->vnp = head;
4816   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
4817   for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
4818   }
4819   tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
4820   CorrectBarMax (tlp->bar, tlp->max);
4821   CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
4822 }
4823 
VisStringDialogToUserFieldPtr(DialoG d)4824 static Pointer VisStringDialogToUserFieldPtr (DialoG d)
4825 
4826 {
4827   return NULL;
4828 }
4829 
4830 
4831 static CharPtr s_RefGeneStatusStrings[] = {
4832   "Inferred",
4833   "Predicted",
4834   "Provisional",
4835   "Validated",
4836   "Reviewed",
4837   "Model",
4838   "WGS",
4839   "Pipeline",
4840   NULL};
4841 
4842 
GetPosForRefGeneStatusString(CharPtr str)4843 static Int2 GetPosForRefGeneStatusString (CharPtr str)
4844 {
4845   Int2 i;
4846 
4847   for (i = 0; s_RefGeneStatusStrings[i] != NULL; i++) {
4848     if (StringICmp (str, s_RefGeneStatusStrings[i]) == 0) {
4849       return i + 1;
4850     }
4851   }
4852   return 0;
4853 }
4854 
4855 
GetRefGeneStatusFromPos(Int2 status)4856 static CharPtr GetRefGeneStatusFromPos (Int2 status)
4857 {
4858   if (status > 0 && status < sizeof (s_RefGeneStatusStrings) / sizeof (CharPtr)) {
4859     return s_RefGeneStatusStrings[status - 1];
4860   } else {
4861     return NULL;
4862   }
4863 }
4864 
4865 
UserObjectPtrToRefGeneDialog(DialoG d,Pointer data)4866 static void UserObjectPtrToRefGeneDialog (DialoG d, Pointer data)
4867 
4868 {
4869   UserFieldPtr          curr;
4870   Boolean               gen;
4871   ObjectIdPtr           oip;
4872   RefgeneUserDialogPtr  rdp;
4873   Int2                  status = 0;
4874   CharPtr               str;
4875   UserObjectPtr         uop;
4876 
4877   rdp = (RefgeneUserDialogPtr) GetObjectExtra (d);
4878   if (rdp == NULL) return;
4879   uop = (UserObjectPtr) data;
4880   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "RefGeneTracking") != 0) {
4881     SetValue (rdp->status, 0);
4882     PointerToDialog (rdp->fields, NULL);
4883     return;
4884   }
4885   PointerToDialog (rdp->fields, uop->data);
4886   for (curr = uop->data; curr != NULL; curr = curr->next) {
4887     oip = curr->label;
4888     if (oip != NULL && StringICmp (oip->str, "Status") == 0) {
4889       break;
4890     }
4891   }
4892   if (curr != NULL && curr->choice == 1) {
4893     str = (CharPtr) curr->data.ptrvalue;
4894     status = GetPosForRefGeneStatusString(str);
4895     if (status == 8) {
4896       SafeEnable (rdp->pipebtn);
4897     }
4898   }
4899   for (curr = uop->data; curr != NULL; curr = curr->next) {
4900     oip = curr->label;
4901     if (oip != NULL && StringICmp (oip->str, "Generated") == 0) {
4902       break;
4903     }
4904   }
4905   if (curr != NULL && curr->choice == 4) {
4906     gen = curr->data.boolvalue;
4907     SetStatus (rdp->generated, gen);
4908   }
4909   for (curr = uop->data; curr != NULL; curr = curr->next) {
4910     oip = curr->label;
4911     if (oip != NULL && StringICmp (oip->str, "Collaborator") == 0) {
4912       break;
4913     }
4914   }
4915   if (curr != NULL && curr->choice == 1) {
4916     str = (CharPtr) curr->data.ptrvalue;
4917     SetTitle (rdp->curator, str);
4918   }
4919 
4920   for (curr = uop->data; curr != NULL; curr = curr->next) {
4921     oip = curr->label;
4922     if (oip != NULL && StringICmp (oip->str, "CollaboratorURL") == 0) {
4923       break;
4924     }
4925   }
4926   if (curr != NULL && curr->choice == 1) {
4927     str = (CharPtr) curr->data.ptrvalue;
4928     SetTitle (rdp->url, str);
4929   }
4930 
4931   for (curr = uop->data; curr != NULL; curr = curr->next) {
4932     oip = curr->label;
4933     if (oip != NULL && StringICmp (oip->str, "GenomicSource") == 0) {
4934       break;
4935     }
4936   }
4937   if (curr != NULL && curr->choice == 1) {
4938     str = (CharPtr) curr->data.ptrvalue;
4939     SetTitle (rdp->source, str);
4940   }
4941   SetValue (rdp->status, status);
4942   for (curr = uop->data; curr != NULL; curr = curr->next) {
4943     oip = curr->label;
4944     if (oip != NULL && StringICmp (oip->str, "Indexer") == 0) {
4945       break;
4946     }
4947   }
4948   if (curr != NULL && curr->choice == 2) {
4949     rdp->indexer = (Int2) curr->data.intvalue;
4950   }
4951 }
4952 
AddIndexerToRefGeneTrackUserObject(UserObjectPtr uop,Int2 indexer)4953 static void AddIndexerToRefGeneTrackUserObject (UserObjectPtr uop, Int2 indexer)
4954 
4955 {
4956   UserFieldPtr  curr;
4957   ObjectIdPtr   oip;
4958 
4959   if (uop == NULL || indexer < 1) return;
4960   oip = uop->type;
4961   if (oip == NULL || StringICmp (oip->str, "RefGeneTracking") != 0) return;
4962 
4963   for (curr = uop->data; curr != NULL; curr = curr->next) {
4964     oip = curr->label;
4965     if (oip != NULL && StringICmp (oip->str, "Indexer") == 0) {
4966       break;
4967     }
4968   }
4969 
4970   if (curr == NULL) {
4971     curr = UserFieldNew ();
4972     oip = ObjectIdNew ();
4973     oip->str = StringSave ("Indexer");
4974     curr->label = oip;
4975     curr->choice = 2; /* integer */
4976 
4977     /* link indexer at beginning of list */
4978 
4979     curr->next = uop->data;
4980     uop->data = curr;
4981   }
4982 
4983   if (curr == NULL || curr->choice != 2) return;
4984 
4985   /* replace any existing indexer indication */
4986 
4987   curr->data.intvalue = (Int4) indexer;
4988 }
4989 
RefGeneDialogToUserObjectPtr(DialoG d)4990 static Pointer RefGeneDialogToUserObjectPtr (DialoG d)
4991 
4992 {
4993   Char                  ch;
4994   Char                  curator [256];
4995   Int2                  i;
4996   Uint2                 j;
4997   size_t                len;
4998   Int4                  num [6];
4999   Boolean               okay;
5000   RefgeneUserDialogPtr  rdp;
5001   Char                  source [64];
5002   CharPtr               status;
5003   CharPtr               str;
5004   TagListPtr            tlp;
5005   CharPtr               txt [6];
5006   UserObjectPtr         uop;
5007   Char                  url [512];
5008   long int              val;
5009   ValNodePtr            vnp;
5010 
5011   rdp = (RefgeneUserDialogPtr) GetObjectExtra (d);
5012   if (rdp == NULL) return NULL;
5013 
5014   uop = CreateRefGeneTrackUserObject ();
5015   if (uop == NULL) return NULL;
5016 
5017   status = GetRefGeneStatusFromPos(GetValue (rdp->status));
5018   if (status != NULL) {
5019     AddStatusToRefGeneTrackUserObject (uop, status);
5020   }
5021 
5022   GetTitle (rdp->source, source, sizeof (source));
5023   if (! StringHasNoText (source)) {
5024     AddSourceToRefGeneTrackUserObject (uop, source);
5025   }
5026 
5027   if (GetStatus (rdp->generated)) {
5028     AddGeneratedToRefGeneTrackUserObject (uop, TRUE);
5029   }
5030 
5031   GetTitle (rdp->curator, curator, sizeof (curator));
5032   if (! StringHasNoText (curator)) {
5033     AddCuratorToRefGeneTrackUserObject (uop, curator);
5034   }
5035 
5036   GetTitle (rdp->url, url, sizeof (url));
5037   if (! StringHasNoText (url)) {
5038     AddCuratorURLToRefGeneTrackUserObject (uop, url);
5039   }
5040 
5041   if (rdp->indexer > 0) {
5042     AddIndexerToRefGeneTrackUserObject (uop, rdp->indexer);
5043   }
5044 
5045   tlp = (TagListPtr) GetObjectExtra (rdp->fields);
5046   if (tlp != NULL && tlp->vnp != NULL) {
5047     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
5048       str = (CharPtr) vnp->data.ptrvalue;
5049       okay = FALSE;
5050       len = StringLen (str);
5051       for (j = 0; j < len; j++) {
5052         ch = str [j];
5053         if (ch != ' ' && ch != '\t' && ch != '\n') {
5054           okay = TRUE;
5055         }
5056       }
5057       if (okay) {
5058         for (j = 0; j < 6; j++) {
5059           txt [j] = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, j);
5060           num [j] = 0;
5061         }
5062         for (j = 1; j < 4; j++) {
5063           num [j] = 0;
5064           if (txt [j] != NULL && sscanf (txt [j], "%ld", &val) == 1) {
5065             num [j] = val;
5066           }
5067         }
5068         if (txt [5] != NULL && sscanf (txt [5], "%ld", &val) == 1) {
5069           num [5] = val;
5070         }
5071         i = num [5];
5072         if (i >= REFGENE_ASSEMBLY && i <= REFGENE_UNKNOWN) {
5073           if (! StringHasNoText (txt [0])) {
5074             AddAccessionToRefGeneTrackUserObject (uop, refgene_labels [i],
5075                                                   txt [0], num [1], num [2],
5076                                                   num [3], txt [4]);
5077           } else if (! StringHasNoText (txt [4])) {
5078             /* comment by itself goes into name */
5079             AddAccessionToRefGeneTrackUserObject (uop, refgene_labels [i],
5080                                                   NULL, num [1], num [2],
5081                                                   num [3], txt [4]);
5082           }
5083         }
5084         for (j = 0; j < 6; j++) {
5085           txt [j] = MemFree (txt [j]);
5086         }
5087       }
5088     }
5089   }
5090 
5091   return uop;
5092 }
5093 
CreateRefGeneDialog(GrouP g)5094 static DialoG CreateRefGeneDialog (GrouP g)
5095 
5096 {
5097   Int2                  i;
5098   PrompT                lastppt;
5099   GrouP                 p;
5100   PrompT                ppt;
5101   GrouP                 q;
5102   RefgeneUserDialogPtr  rdp;
5103   TagListPtr            tlp;
5104   GrouP                 x;
5105   GrouP                 y;
5106   GrouP                 z;
5107   ButtoN                b;
5108 
5109   p = HiddenGroup (g, -1, 0, NULL);
5110   SetGroupSpacing (p, 10, 10);
5111 
5112   rdp = (RefgeneUserDialogPtr) MemNew (sizeof (RefgeneUserDialog));
5113   if (rdp == NULL) return NULL;
5114 
5115   SetObjectExtra (p, rdp, NULL);
5116   rdp->dialog = (DialoG) p;
5117   rdp->todialog = UserObjectPtrToRefGeneDialog;
5118   rdp->fromdialog = RefGeneDialogToUserObjectPtr;
5119 
5120   x = HiddenGroup (p, 4, 0, NULL);
5121   /* StaticPrompt (x, "Status", 0, stdLineHeight, programFont, 'l'); */
5122   rdp->status = HiddenGroup (x, 8, 0, NULL);
5123   SetObjectExtra (rdp->status, rdp, NULL);
5124   for (i = 0; s_RefGeneStatusStrings[i] != NULL; i++) {
5125     b = RadioButton (rdp->status, s_RefGeneStatusStrings[i]);
5126     if (StringICmp (s_RefGeneStatusStrings[i], "Pipeline") == 0) {
5127       rdp->pipebtn = b;
5128     }
5129   }
5130   Disable (rdp->pipebtn);
5131 
5132   y = HiddenGroup (p, 6, 0, NULL);
5133   rdp->generated = CheckBox (y, "Generated", NULL);
5134   z = HiddenGroup (y, 2, 0, NULL);
5135   StaticPrompt (z, "Curator", 0, dialogTextHeight, programFont, 'l');
5136   rdp->curator = DialogText (z, "", 14, NULL);
5137   StaticPrompt (z, "URL", 0, dialogTextHeight, programFont, 'r');
5138   rdp->url = DialogText (z, "", 14, NULL);
5139   StaticPrompt (y, "Genomic Source", 0, dialogTextHeight, programFont, 'l');
5140   rdp->source = DialogText (y, "", 7, NULL);
5141 
5142   rdp->indexer = 0;
5143 
5144   q = HiddenGroup (p, -7, 0, NULL);
5145   lastppt = NULL;
5146   ppt = NULL;
5147   for (i = 0; i < 6; i++) {
5148     lastppt = ppt;
5149     ppt = StaticPrompt (q, refgene_fields [i], refgene_widths [i] * stdCharWidth, 0, systemFont, 'c');
5150   }
5151   rdp->fields = CreateTagListDialog (p, 6, 6, STD_TAG_SPACING,
5152                                      refgene_types, refgene_widths, refgene_popups,
5153                                      AccessionUserFieldPtrToVisStringDialog,
5154                                      VisStringDialogToUserFieldPtr);
5155 
5156   tlp = (TagListPtr) GetObjectExtra (rdp->fields);
5157   if (tlp != NULL) {
5158     AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [4], (HANDLE) lastppt, NULL);
5159     AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [5], (HANDLE) ppt, NULL);
5160   }
5161 
5162   AlignObjects (ALIGN_CENTER, (HANDLE) x, (HANDLE) y, (HANDLE) q, (HANDLE) rdp->fields, NULL);
5163   return (DialoG) p;
5164 }
5165 
RefgeneUserFormMessage(ForM f,Int2 mssg)5166 static void RefgeneUserFormMessage (ForM f, Int2 mssg)
5167 
5168 {
5169   RefgeneUserFormPtr  rfp;
5170 
5171   rfp = (RefgeneUserFormPtr) GetObjectExtra (f);
5172   if (rfp != NULL) {
5173     switch (mssg) {
5174       case VIB_MSG_CLOSE :
5175         Remove (f);
5176         break;
5177       case VIB_MSG_CUT :
5178         StdCutTextProc (NULL);
5179         break;
5180       case VIB_MSG_COPY :
5181         StdCopyTextProc (NULL);
5182         break;
5183       case VIB_MSG_PASTE :
5184         StdPasteTextProc (NULL);
5185         break;
5186       case VIB_MSG_DELETE :
5187         StdDeleteTextProc (NULL);
5188         break;
5189       default :
5190         if (rfp->appmessage != NULL) {
5191           rfp->appmessage (f, mssg);
5192         }
5193         break;
5194     }
5195   }
5196 }
5197 
CreateRefGeneDescForm(Int2 left,Int2 top,Int2 width,Int2 height,CharPtr title,ValNodePtr sdp,SeqEntryPtr sep,FormActnFunc actproc)5198 static ForM CreateRefGeneDescForm (Int2 left, Int2 top, Int2 width,
5199                                    Int2 height, CharPtr title, ValNodePtr sdp,
5200                                    SeqEntryPtr sep, FormActnFunc actproc)
5201 
5202 {
5203   ButtoN              b;
5204   GrouP               c;
5205   GrouP               g;
5206   RefgeneUserFormPtr  rfp;
5207   StdEditorProcsPtr   sepp;
5208   WindoW              w;
5209 
5210   w = NULL;
5211   rfp = (RefgeneUserFormPtr) MemNew (sizeof (RefgeneUserForm));
5212   if (rfp != NULL) {
5213     w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
5214     SetObjectExtra (w, rfp, StdDescFormCleanupProc);
5215     rfp->form = (ForM) w;
5216     rfp->actproc = actproc;
5217     rfp->formmessage = RefgeneUserFormMessage;
5218 
5219     rfp->sep = sep;
5220 
5221 #ifndef WIN_MAC
5222     CreateStdEditorFormMenus (w);
5223 #endif
5224     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
5225     if (sepp != NULL) {
5226       SetActivate (w, sepp->activateForm);
5227       rfp->appmessage = sepp->handleMessages;
5228     }
5229 
5230     g = HiddenGroup (w, -1, 0, NULL);
5231     rfp->data = CreateRefGeneDialog (g);
5232 
5233     c = HiddenGroup (w, 2, 0, NULL);
5234     b = DefaultButton (c, "Accept", StdAcceptFormButtonProc);
5235     SetObjectExtra (b, rfp, NULL);
5236     PushButton (c, "Cancel", StdCancelButtonProc);
5237     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
5238     RealizeWindow (w);
5239   }
5240   return (ForM) w;
5241 }
5242 
RefGeneUserGenFunc(Pointer data)5243 extern Int2 LIBCALLBACK RefGeneUserGenFunc (Pointer data)
5244 
5245 {
5246   ObjectIdPtr         oip;
5247   OMProcControlPtr    ompcp;
5248   OMUserDataPtr       omudp;
5249   ObjMgrProcPtr       proc;
5250   RefgeneUserFormPtr  rfp;
5251   ValNodePtr          sdp;
5252   SeqEntryPtr         sep;
5253   UserObjectPtr       uop = NULL;
5254   WindoW              w;
5255 
5256   ompcp = (OMProcControlPtr) data;
5257   w = NULL;
5258   sdp = NULL;
5259   sep = NULL;
5260   uop = NULL;
5261   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
5262   proc = ompcp->proc;
5263   switch (ompcp->input_itemtype) {
5264     case OBJ_SEQDESC :
5265       sdp = (ValNodePtr) ompcp->input_data;
5266       if (sdp != NULL && sdp->choice != Seq_descr_user) {
5267         return OM_MSG_RET_ERROR;
5268       }
5269       if (sdp != NULL) {
5270         uop = (UserObjectPtr) sdp->data.ptrvalue;
5271       }
5272       break;
5273     case OBJ_BIOSEQ :
5274       break;
5275     case OBJ_BIOSEQSET :
5276       break;
5277     case 0 :
5278       break;
5279     default :
5280       return OM_MSG_RET_ERROR;
5281   }
5282   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
5283                                 ompcp->input_itemtype, ompcp->proc->procid);
5284   if (omudp != NULL) {
5285     if (StringCmp (proc->procname, "Edit RefGene UserTrack Desc") == 0) {
5286       rfp = (RefgeneUserFormPtr) omudp->userdata.ptrvalue;
5287       if (rfp != NULL) {
5288         Select (rfp->form);
5289       }
5290       return OM_MSG_RET_DONE;
5291     } else {
5292       return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
5293     }
5294   }
5295   if (uop != NULL) {
5296     oip = uop->type;
5297     if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
5298     if (StringCmp (oip->str, "RefGeneTracking") != 0) return OM_MSG_RET_OK;
5299   }
5300   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
5301   w = (WindoW) CreateRefGeneDescForm (-50, -33, -10, -10,
5302                                       "Reference Gene Tracking", sdp, sep,
5303                                       StdDescFormActnProc);
5304   rfp = (RefgeneUserFormPtr) GetObjectExtra (w);
5305   if (rfp != NULL) {
5306     rfp->input_entityID = ompcp->input_entityID;
5307     rfp->input_itemID = ompcp->input_itemID;
5308     rfp->input_itemtype = ompcp->input_itemtype;
5309     rfp->this_itemtype = OBJ_SEQDESC;
5310     rfp->this_subtype = Seq_descr_user;
5311     rfp->procid = ompcp->proc->procid;
5312     rfp->proctype = ompcp->proc->proctype;
5313     rfp->userkey = OMGetNextUserKey ();
5314     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
5315 	                           OMPROC_EDIT, rfp->userkey);
5316     if (omudp != NULL) {
5317       omudp->userdata.ptrvalue = (Pointer) rfp;
5318       omudp->messagefunc = StdVibrantEditorMsgFunc;
5319     }
5320     SendMessageToForm (rfp->form, VIB_MSG_INIT);
5321     if (sdp != NULL) {
5322       PointerToDialog (rfp->data, (Pointer) sdp->data.ptrvalue);
5323       SetClosestParentIfDuplicating ((BaseFormPtr) rfp);
5324     }
5325   }
5326   Show (w);
5327   Select (w);
5328   return OM_MSG_RET_DONE;
5329 }
5330 
5331 
SetGlobalRefGeneStatusCallback(SeqDescPtr sdp,Pointer data)5332 static void SetGlobalRefGeneStatusCallback (SeqDescPtr sdp, Pointer data)
5333 {
5334   CharPtr status;
5335   UserObjectPtr uop;
5336   if (sdp != NULL && sdp->choice == Seq_descr_user && (uop = (UserObjectPtr) sdp->data.ptrvalue) != NULL
5337       && (status = (CharPtr) data) != NULL) {
5338     AddStatusToRefGeneTrackUserObject (uop, status);
5339   }
5340 }
5341 
5342 
5343 typedef struct globalrefgenestatusfrm {
5344   FORM_MESSAGE_BLOCK
5345   GrouP status;
5346 } GlobalRefGeneStatusFrmData, PNTR GlobalRefGeneStatusFrmPtr;
5347 
5348 
DoSetGlobalRefGeneStatus(ButtoN b)5349 static void DoSetGlobalRefGeneStatus (ButtoN b)
5350 {
5351   GlobalRefGeneStatusFrmPtr frm;
5352   CharPtr status;
5353   SeqEntryPtr sep;
5354 
5355   frm = (GlobalRefGeneStatusFrmPtr) GetObjectExtra (b);
5356   if (frm == NULL) {
5357     return;
5358   }
5359 
5360   status = GetRefGeneStatusFromPos(GetValue (frm->status));
5361   if (status != NULL) {
5362     sep = GetTopSeqEntryForEntityID (frm->input_entityID);
5363     VisitDescriptorsInSep (sep, status, SetGlobalRefGeneStatusCallback);
5364     ObjMgrSetDirtyFlag (frm->input_entityID, TRUE);
5365     ObjMgrSendMsg (OM_MSG_UPDATE, frm->input_entityID, 0, 0);
5366     Remove (frm->form);
5367   }
5368 
5369 }
5370 
5371 
SetGlobalRefGeneStatus(IteM i)5372 NLM_EXTERN void SetGlobalRefGeneStatus (IteM i)
5373 {
5374   BaseFormPtr        bfp;
5375   GlobalRefGeneStatusFrmPtr frm;
5376   WindoW w;
5377   GrouP  h, c;
5378   ButtoN b;
5379   Int2   j;
5380 
5381 #ifdef WIN_MAC
5382   bfp = currentFormDataPtr;
5383 #else
5384   bfp = GetObjectExtra (i);
5385 #endif
5386   if (bfp == NULL) return;
5387 
5388   frm = (GlobalRefGeneStatusFrmPtr) MemNew (sizeof (GlobalRefGeneStatusFrmData));
5389   w = FixedWindow (-50, -33, -10, -10, "Set Global Ref Gene Status", StdCloseWindowProc);
5390   h = HiddenGroup (w, -1, 0, NULL);
5391   SetGroupSpacing (h, 10, 10);
5392   frm->form = (ForM) w;
5393   frm->input_entityID = bfp->input_entityID;
5394 
5395   frm->status = HiddenGroup (h, 8, 0, NULL);
5396   SetObjectExtra (frm->status, frm, NULL);
5397   for (j = 0; s_RefGeneStatusStrings[j] != NULL; j++) {
5398     RadioButton (frm->status, s_RefGeneStatusStrings[j]);
5399   }
5400 
5401   c = HiddenGroup (w, 2, 0, NULL);
5402   SetGroupSpacing (c, 5, 5);
5403   b = DefaultButton (c, "Accept", DoSetGlobalRefGeneStatus);
5404   SetObjectExtra (b, frm, NULL);
5405   PushButton (c, "Cancel", StdCancelButtonProc);
5406   AlignObjects (ALIGN_CENTER, (HANDLE) frm->status, (HANDLE) c, NULL);
5407   RealizeWindow (w);
5408   Show (w);
5409   Select (w);
5410 }
5411 
5412 
5413 extern Int2 LIBCALLBACK StruCommUserGenFunc (Pointer data);
5414 
5415 typedef struct strucommuserdialog {
5416   DIALOG_MESSAGE_BLOCK
5417   DialoG        fields;
5418 } StruCommUserDialog, PNTR StruCommUserDialogPtr;
5419 
5420 typedef struct strucommuserform {
5421   FEATURE_FORM_BLOCK
5422   SeqEntryPtr   sep;
5423 } StruCommUserForm, PNTR StruCommUserFormPtr;
5424 
UserObjectPtrToStruCommDialog(DialoG d,Pointer data)5425 static void UserObjectPtrToStruCommDialog (DialoG d, Pointer data)
5426 
5427 {
5428   UserFieldPtr           curr;
5429   CharPtr                field;
5430   ValNodePtr             head = NULL;
5431   ObjectIdPtr            oip;
5432   StruCommUserDialogPtr  sdp;
5433   CharPtr                str;
5434   CharPtr                tmp;
5435   UserObjectPtr          uop;
5436 
5437   sdp = (StruCommUserDialogPtr) GetObjectExtra (d);
5438   if (sdp == NULL) return;
5439 
5440   uop = (UserObjectPtr) data;
5441   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "StructuredComment") != 0) {
5442     PointerToDialog (sdp->fields, NULL);
5443     return;
5444   }
5445 
5446   for (curr = uop->data; curr != NULL; curr = curr->next) {
5447    if (curr->choice != 1) continue;
5448     oip = curr->label;
5449     if (oip == NULL) continue;
5450     field = oip->str;
5451     if (StringHasNoText (field)) continue;
5452     str = (CharPtr) curr->data.ptrvalue;
5453     if (StringHasNoText (str)) continue;
5454     tmp = MemNew (StringLen (field) + StringLen (str) + 5);
5455     if (tmp == NULL) continue;
5456     sprintf (tmp, "%s\t%s", field, str);
5457     ValNodeAddStr (&head, 0, (Pointer) tmp);
5458   }
5459 
5460   PointerToDialog (sdp->fields, (Pointer) head);
5461   ValNodeFreeData (head);
5462 }
5463 
FixSpecialCharactersInStructuredCommentUserObject(UserObjectPtr uop,BoolPtr changed)5464 static void FixSpecialCharactersInStructuredCommentUserObject (UserObjectPtr uop, BoolPtr changed)
5465 {
5466   UserFieldPtr           curr;
5467   CharPtr                field;
5468   ValNodePtr             find_list = NULL;
5469   ObjectIdPtr            oip;
5470   CharPtr                str;
5471 
5472 
5473   if (changed != NULL) {
5474     *changed = FALSE;
5475   }
5476   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "StructuredComment") != 0) {
5477     return;
5478   }
5479 
5480   for (curr = uop->data; curr != NULL; curr = curr->next) {
5481    if (curr->choice != 1) continue;
5482     oip = curr->label;
5483     if (oip == NULL) continue;
5484     field = oip->str;
5485     if (StringHasNoText (field)) continue;
5486     str = (CharPtr) curr->data.ptrvalue;
5487     if (StringHasNoText (str)) continue;
5488 
5489     SpecialCharFindWithContext ((CharPtr PNTR) (&(oip->str)), &find_list, NULL, NULL);
5490     SpecialCharFindWithContext ((CharPtr PNTR) (&(curr->data.ptrvalue)), &find_list, NULL, NULL);
5491   }
5492   FixSpecialCharactersForStringsInList (find_list, "Special characters are not permitted.", TRUE);
5493   if (find_list != NULL)
5494   {
5495     if (changed != NULL) {
5496       *changed = TRUE;
5497     }
5498     find_list = FreeContextList (find_list);
5499   }
5500 }
5501 
5502 
StruCommDialogToUserObjectPtr(DialoG d)5503 static Pointer StruCommDialogToUserObjectPtr (DialoG d)
5504 
5505 {
5506   CharPtr                field;
5507   ValNodePtr             head;
5508   CharPtr                item;
5509   UserObjectPtr          uop;
5510   StruCommUserDialogPtr  sdp;
5511   CharPtr                str;
5512   ValNodePtr             vnp;
5513   Boolean                fixed_special = FALSE;
5514 
5515   sdp = (StruCommUserDialogPtr) GetObjectExtra (d);
5516   if (sdp == NULL) return NULL;
5517 
5518   uop = CreateStructuredCommentUserObject (NULL, NULL);
5519   if (uop == NULL) return NULL;
5520 
5521   head = (ValNodePtr) DialogToPointer (sdp->fields);
5522   if (head == NULL) return NULL;
5523 
5524   for (vnp = head; vnp != NULL; vnp = vnp->next) {
5525     str = (CharPtr) vnp->data.ptrvalue;
5526     if (StringHasNoText (str)) continue;
5527     field = ExtractTagListColumn (str, 0);
5528     item = ExtractTagListColumn (str, 1);
5529     if (StringDoesHaveText (field) && StringDoesHaveText (item)) {
5530       AddItemStructuredCommentUserObject (uop, field, item);
5531     }
5532     MemFree (field);
5533     MemFree (item);
5534   }
5535 
5536   ValNodeFreeData (head);
5537 
5538   FixSpecialCharactersInStructuredCommentUserObject (uop, &fixed_special);
5539   if (fixed_special) {
5540     PointerToDialog (d, uop);
5541   }
5542 
5543   return uop;
5544 }
5545 
ValNodePtrToStruCommDialog(DialoG d,Pointer data)5546 static void ValNodePtrToStruCommDialog (DialoG d, Pointer data)
5547 
5548 {
5549   ValNodePtr   head;
5550   Int2         j;
5551   ValNodePtr   list;
5552   CharPtr      str;
5553   TagListPtr   tlp;
5554   ValNodePtr   vnp;
5555 
5556   tlp = (TagListPtr) GetObjectExtra (d);
5557   list = (ValNodePtr) data;
5558   if (tlp != NULL) {
5559     head = NULL;
5560     while (list != NULL) {
5561       vnp = ValNodeNew (head);
5562       if (head == NULL) {
5563         head = vnp;
5564       }
5565       if (vnp != NULL) {
5566         str = MemNew (StringLen ((CharPtr) list->data.ptrvalue) + 3);
5567         if (str != NULL) {
5568           StringCpy (str, (CharPtr) list->data.ptrvalue);
5569           StringCat (str, "\n");
5570         }
5571         vnp->data.ptrvalue = str;
5572       }
5573       list = list->next;
5574     }
5575     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
5576     tlp->vnp = head;
5577     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
5578     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
5579     }
5580     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
5581     CorrectBarMax (tlp->bar, tlp->max);
5582     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
5583   }
5584 }
5585 
StruCommDialogToValNodePtr(DialoG d)5586 static Pointer StruCommDialogToValNodePtr (DialoG d)
5587 
5588 {
5589   Char         ch;
5590   ValNodePtr   head;
5591   Int2         j;
5592   Int2         len;
5593   ValNodePtr   list;
5594   Boolean      okay;
5595   CharPtr      str;
5596   TagListPtr   tlp;
5597   ValNodePtr   vnp;
5598 
5599   head = NULL;
5600   tlp = (TagListPtr) GetObjectExtra (d);
5601   if (tlp != NULL && tlp->vnp != NULL) {
5602     list = NULL;
5603     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
5604       str = (CharPtr) vnp->data.ptrvalue;
5605       okay = FALSE;
5606       len = StringLen (str);
5607       for (j = 0; j < len; j++) {
5608         ch = str [j];
5609         if (ch != ' ' && ch != '\t' && ch != '\n') {
5610           okay = TRUE;
5611         }
5612       }
5613       if (okay) {
5614         list = ValNodeNew (list);
5615         if (head == NULL) {
5616           head = list;
5617         }
5618         if (list != NULL) {
5619           list->choice = 0;
5620           list->data.ptrvalue = StringSave ((CharPtr) vnp->data.ptrvalue);
5621         }
5622       }
5623     }
5624   }
5625   return (Pointer) head;
5626 }
5627 
5628 Uint2 strccmm_types [] = {
5629   TAGLIST_TEXT, TAGLIST_TEXT
5630 };
5631 
5632 Uint2 strccmm_widths [] = {
5633   16, 16, 0
5634 };
5635 
CreateStruCommDialog(GrouP g)5636 static DialoG CreateStruCommDialog (GrouP g)
5637 
5638 {
5639   StruCommUserDialogPtr  sdp;
5640   GrouP                  p;
5641   GrouP                  x;
5642   GrouP                  y;
5643 
5644   p = HiddenGroup (g, -1, 0, NULL);
5645   SetGroupSpacing (p, 10, 10);
5646 
5647   sdp = (StruCommUserDialogPtr) MemNew (sizeof (StruCommUserDialog));
5648   if (sdp == NULL) return NULL;
5649 
5650   SetObjectExtra (p, sdp, NULL);
5651   sdp->dialog = (DialoG) p;
5652   sdp->todialog = UserObjectPtrToStruCommDialog;
5653   sdp->fromdialog = StruCommDialogToUserObjectPtr;
5654 
5655   x = HiddenGroup (p, 0, 2, NULL);
5656   y = HiddenGroup (x, 3, 0, NULL);
5657   StaticPrompt (y, "Field", 16 * stdCharWidth, 0, programFont, 'c');
5658   StaticPrompt (y, "Text", 16 * stdCharWidth, 0, programFont, 'c');
5659 
5660   sdp->fields = CreateTagListDialogEx3 (x, 8, 2, -1,
5661                                      strccmm_types, strccmm_widths, NULL,
5662                                      TRUE, FALSE,
5663                                      ValNodePtrToStruCommDialog,
5664                                      StruCommDialogToValNodePtr, NULL, NULL, FALSE, TRUE);
5665 
5666   return (DialoG) p;
5667 }
5668 
5669 
ExportStructuredCommentForm(ForM f,CharPtr filename)5670 static Boolean ExportStructuredCommentForm (ForM f, CharPtr filename)
5671 {
5672   StruCommUserFormPtr  sfp;
5673   Char            path [PATH_MAX];
5674   UserObjectPtr   uop;
5675   AsnIoPtr        aip;
5676   Boolean         rval = FALSE;
5677 #ifdef WIN_MAC
5678   FILE            *fp;
5679 #endif
5680 
5681   sfp = (StruCommUserFormPtr) GetObjectExtra (f);
5682   if (sfp == NULL) {
5683     return FALSE;
5684   }
5685 
5686   uop = DialogToPointer (sfp->data);
5687   if (uop == NULL) {
5688     Message (MSG_ERROR, "Don't have a valid structured comment yet!");
5689     return FALSE;
5690   }
5691 
5692   path [0] = '\0';
5693   StringNCpy_0 (path, filename, sizeof (path));
5694   if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
5695 #ifdef WIN_MAC
5696     fp = FileOpen (path, "r");
5697     if (fp != NULL) {
5698       FileClose (fp);
5699     } else {
5700       FileCreate (path, "TEXT", "ttxt");
5701     }
5702 #endif
5703   }
5704   aip = AsnIoOpen (path, "w");
5705   if (aip == NULL) {
5706     Message (MSG_ERROR, "Unable to create file %s", path);
5707   } else {
5708     UserObjectAsnWrite (uop, aip, NULL);
5709     AsnIoClose (aip);
5710     rval = TRUE;
5711   }
5712   uop = UserObjectFree (uop);
5713   return rval;
5714 }
5715 
5716 
StructuredCommentFromTabFile(CharPtr path)5717 static UserObjectPtr StructuredCommentFromTabFile (CharPtr path)
5718 {
5719   FILE *fp;
5720   ValNodePtr table, tmp, header, line;
5721   UserObjectPtr uop = NULL;
5722 
5723   fp = FileOpen (path, "r");
5724   if (fp == NULL) {
5725     return NULL;
5726   }
5727 
5728   table = ReadTabTableFromFile (fp);
5729   FileClose (fp);
5730   if (table == NULL || table->next == NULL
5731       || table->data.ptrvalue == NULL
5732       || table->next->data.ptrvalue == NULL) {
5733     table = FreeTabTable (table);
5734     return NULL;
5735   }
5736   tmp = FlipTabTableAxes (table);
5737   table = FreeTabTable (table);
5738   table = tmp;
5739 
5740   header = table->data.ptrvalue;
5741   if (header == NULL || header->data.ptrvalue == NULL || header->next == NULL) {
5742     table = FreeTabTable (table);
5743     return NULL;
5744   }
5745   line = table->next;
5746 
5747   tmp = CreateStructuredCommentsFromRow (header, line->data.ptrvalue, NULL, NULL);
5748   table = FreeTabTable (table);
5749   if (tmp != NULL) {
5750     uop = (UserObjectPtr) tmp->data.ptrvalue;
5751     tmp->data.ptrvalue = NULL;
5752     for (line = tmp->next; line != NULL; line = line->next) {
5753       line->data.ptrvalue = UserObjectFree (line->data.ptrvalue);
5754     }
5755     tmp = ValNodeFree (tmp);
5756   }
5757   return uop;
5758 }
5759 
5760 
ImportStructuredCommentForm(ForM f,CharPtr filename)5761 static Boolean ImportStructuredCommentForm  (ForM f, CharPtr filename)
5762 {
5763   StruCommUserFormPtr  sfp;
5764   Char            path [PATH_MAX];
5765   UserObjectPtr   uop = NULL;
5766   AsnIoPtr        aip = NULL;
5767   Boolean         rval = FALSE;
5768 
5769   sfp = (StruCommUserFormPtr) GetObjectExtra (f);
5770   if (sfp == NULL) {
5771     return FALSE;
5772   }
5773 
5774   path [0] = '\0';
5775   StringNCpy_0 (path, filename, sizeof (path));
5776   if (path [0] == '\0') {
5777     if (!GetInputFileName (path, sizeof (path), "", "TEXT")) {
5778       return FALSE;
5779     }
5780   }
5781 
5782   aip = AsnIoOpen (path, "r");
5783   if (aip == NULL) {
5784     Message (MSG_ERROR, "Unable to read file %s", path);
5785   } else {
5786     uop = UserObjectAsnRead (aip, NULL);
5787     AsnIoClose (aip);
5788     if (uop == NULL) {
5789       /* try reading as though it were a table */
5790       uop = StructuredCommentFromTabFile(path);
5791     }
5792     if (uop == NULL) {
5793       Message (MSG_ERROR, "Unable to read structured comment ASN.1 from file");
5794     }
5795   }
5796   if (uop != NULL) {
5797     PointerToDialog (sfp->data, uop);
5798     uop = UserObjectFree (uop);
5799     rval = TRUE;
5800   }
5801   return rval;
5802 }
5803 
5804 
StruCommUserFormMessage(ForM f,Int2 mssg)5805 static void StruCommUserFormMessage (ForM f, Int2 mssg)
5806 
5807 {
5808   StruCommUserFormPtr  sfp;
5809 
5810   sfp = (StruCommUserFormPtr) GetObjectExtra (f);
5811   if (sfp != NULL) {
5812     switch (mssg) {
5813       case VIB_MSG_CLOSE :
5814         Remove (f);
5815         break;
5816       case VIB_MSG_CUT :
5817         StdCutTextProc (NULL);
5818         break;
5819       case VIB_MSG_COPY :
5820         StdCopyTextProc (NULL);
5821         break;
5822       case VIB_MSG_PASTE :
5823         StdPasteTextProc (NULL);
5824         break;
5825       case VIB_MSG_DELETE :
5826         StdDeleteTextProc (NULL);
5827         break;
5828       case VIB_MSG_EXPORT :
5829         ExportStructuredCommentForm (f, NULL);
5830         break;
5831       case VIB_MSG_IMPORT :
5832         ImportStructuredCommentForm (f, NULL);
5833         break;
5834       default :
5835         if (sfp->appmessage != NULL) {
5836           sfp->appmessage (f, mssg);
5837         }
5838         break;
5839     }
5840   }
5841 }
5842 
5843 
ReplaceAllStructuredCommentsButtonProc(ButtoN b)5844 static void ReplaceAllStructuredCommentsButtonProc (ButtoN b)
5845 {
5846   StruCommUserFormPtr sfp;
5847   SeqEntryPtr   sep;
5848   ReplaceUserObjectData rd;
5849   SeqDescrPtr       sdp_orig;
5850   SeqMgrDescContext context;
5851 
5852   sfp = (StruCommUserFormPtr) GetObjectExtra (b);
5853   if (sfp == NULL) {
5854     return;
5855   }
5856 
5857   rd.replaceWith = DialogToPointer (sfp->data);
5858   if (rd.replaceWith == NULL) {
5859     Message (MSG_ERROR, "Must supply text!");
5860     rd.replaceWith = UserObjectFree (rd.replaceWith);
5861     return;
5862   }
5863 
5864   sdp_orig = SeqMgrGetDesiredDescriptor (sfp->input_entityID, NULL, sfp->input_itemID, 0, NULL, &context);
5865   if (sdp_orig == NULL || sdp_orig->choice != Seq_descr_user) {
5866     Message (MSG_ERROR, "Unable to find original descriptor!");
5867     Remove (sfp->form);
5868     rd.replaceWith = UserObjectFree (rd.replaceWith);
5869     return;
5870   }
5871   rd.deleteThis = AsnIoMemCopy (sdp_orig->data.ptrvalue, (AsnReadFunc)UserObjectAsnRead, (AsnWriteFunc) UserObjectAsnWrite);
5872 
5873   sep = GetTopSeqEntryForEntityID (sfp->input_entityID);
5874   VisitDescriptorsInSep (sep, &rd, ReplaceAllUserObjectsCallback);
5875 
5876   rd.deleteThis = UserObjectFree (rd.deleteThis);
5877   rd.replaceWith = UserObjectFree (rd.replaceWith);
5878 
5879   ObjMgrSetDirtyFlag (sfp->input_entityID, TRUE);
5880   ObjMgrSendMsg (OM_MSG_UPDATE, sfp->input_entityID,
5881                   sfp->input_itemID, sfp->input_itemtype);
5882   Remove (sfp->form);
5883 }
5884 
5885 
CreateStruCommDescForm(Int2 left,Int2 top,Int2 width,Int2 height,CharPtr title,ValNodePtr sdp,SeqEntryPtr sep,FormActnFunc actproc)5886 static ForM CreateStruCommDescForm (Int2 left, Int2 top, Int2 width,
5887                                      Int2 height, CharPtr title, ValNodePtr sdp,
5888                                      SeqEntryPtr sep, FormActnFunc actproc)
5889 
5890 {
5891   ButtoN               b;
5892   GrouP                c;
5893   GrouP                g;
5894   StdEditorProcsPtr    sepp;
5895   StruCommUserFormPtr  sfp;
5896   WindoW               w;
5897 
5898   w = NULL;
5899   sfp = (StruCommUserFormPtr) MemNew (sizeof (StruCommUserForm));
5900   if (sfp != NULL) {
5901     w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
5902     SetObjectExtra (w, sfp, StdDescFormCleanupProc);
5903     sfp->form = (ForM) w;
5904     sfp->actproc = actproc;
5905     sfp->formmessage = StruCommUserFormMessage;
5906     sfp->exportform = ExportStructuredCommentForm;
5907     sfp->importform = ImportStructuredCommentForm;
5908     sfp->sep = sep;
5909 
5910 #ifndef WIN_MAC
5911     CreateStdEditorFormMenus (w);
5912 #endif
5913     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
5914     if (sepp != NULL) {
5915       SetActivate (w, sepp->activateForm);
5916       sfp->appmessage = sepp->handleMessages;
5917     }
5918 
5919     g = HiddenGroup (w, -1, 0, NULL);
5920     sfp->data = CreateStruCommDialog (g);
5921 
5922     c = HiddenGroup (w, 3, 0, NULL);
5923     if (sdp == NULL) {
5924       b = DefaultButton (c, "Accept", StdAcceptFormButtonProc);
5925       SetObjectExtra (b, sfp, NULL);
5926     } else {
5927       b = PushButton (c, "Replace All", ReplaceAllStructuredCommentsButtonProc);
5928       SetObjectExtra (b, sfp, NULL);
5929       b = DefaultButton (c, "Replace This", StdAcceptFormButtonProc);
5930       SetObjectExtra (b, sfp, NULL);
5931     }
5932 
5933     PushButton (c, "Cancel", StdCancelButtonProc);
5934 
5935     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
5936     RealizeWindow (w);
5937   }
5938   return (ForM) w;
5939 }
5940 
StruCommUserGenFunc(Pointer data)5941 extern Int2 LIBCALLBACK StruCommUserGenFunc (Pointer data)
5942 
5943 {
5944   ObjectIdPtr          oip;
5945   OMProcControlPtr     ompcp;
5946   OMUserDataPtr        omudp;
5947   ObjMgrProcPtr        proc;
5948   ValNodePtr           sdp;
5949   SeqEntryPtr          sep;
5950   StruCommUserFormPtr  sfp;
5951   UserObjectPtr        uop = NULL;
5952   WindoW               w;
5953 
5954   ompcp = (OMProcControlPtr) data;
5955   w = NULL;
5956   sdp = NULL;
5957   sep = NULL;
5958   uop = NULL;
5959   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
5960   proc = ompcp->proc;
5961   switch (ompcp->input_itemtype) {
5962     case OBJ_SEQDESC :
5963       sdp = (ValNodePtr) ompcp->input_data;
5964       if (sdp != NULL && sdp->choice != Seq_descr_user) {
5965         return OM_MSG_RET_ERROR;
5966       }
5967       if (sdp != NULL) {
5968         uop = (UserObjectPtr) sdp->data.ptrvalue;
5969       }
5970       break;
5971     case OBJ_BIOSEQ :
5972       break;
5973     case OBJ_BIOSEQSET :
5974       break;
5975     case 0 :
5976       break;
5977     default :
5978       return OM_MSG_RET_ERROR;
5979   }
5980   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
5981                                 ompcp->input_itemtype, ompcp->proc->procid);
5982   if (omudp != NULL) {
5983     if (StringCmp (proc->procname, "Edit StructuredComment User Desc") == 0) {
5984       sfp = (StruCommUserFormPtr) omudp->userdata.ptrvalue;
5985       if (sfp != NULL) {
5986         Select (sfp->form);
5987       }
5988       return OM_MSG_RET_DONE;
5989     } else {
5990       return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
5991     }
5992   }
5993   if (uop != NULL) {
5994     oip = uop->type;
5995     if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
5996     if (StringCmp (oip->str, "StructuredComment") != 0) return OM_MSG_RET_OK;
5997   }
5998   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
5999   w = (WindoW) CreateStruCommDescForm (-50, -33, -10, -10,
6000                                        "Structured Comment", sdp, sep,
6001                                        StdDescFormActnProc);
6002   sfp = (StruCommUserFormPtr) GetObjectExtra (w);
6003   if (sfp != NULL) {
6004     sfp->input_entityID = ompcp->input_entityID;
6005     sfp->input_itemID = ompcp->input_itemID;
6006     sfp->input_itemtype = ompcp->input_itemtype;
6007     sfp->this_itemtype = OBJ_SEQDESC;
6008     sfp->this_subtype = Seq_descr_user;
6009     sfp->procid = ompcp->proc->procid;
6010     sfp->proctype = ompcp->proc->proctype;
6011     sfp->userkey = OMGetNextUserKey ();
6012     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
6013 	                           OMPROC_EDIT, sfp->userkey);
6014     if (omudp != NULL) {
6015       omudp->userdata.ptrvalue = (Pointer) sfp;
6016       omudp->messagefunc = StdVibrantEditorMsgFunc;
6017     }
6018     SendMessageToForm (sfp->form, VIB_MSG_INIT);
6019     if (sdp != NULL) {
6020       PointerToDialog (sfp->data, (Pointer) sdp->data.ptrvalue);
6021       SetClosestParentIfDuplicating ((BaseFormPtr) sfp);
6022     }
6023   }
6024   Show (w);
6025   Select (w);
6026   return OM_MSG_RET_DONE;
6027 }
6028 
6029 
6030 /*
6031 static void TestGeneRefStuff (void)
6032 
6033 {
6034   UserObjectPtr uop;
6035   ValNodePtr    sdp;
6036 
6037   uop = CreateRefGeneTrackUserObject ();
6038   AddAccessionToRefGeneTrackUserObject (uop, "Assembly", "U12345", 57, 29, 1995);
6039   AddAccessionToRefGeneTrackUserObject (uop, "Assembly", "L97531", 142, 66, 963);
6040   AddAccessionToRefGeneTrackUserObject (uop, "Assembly", "M66778", 823, 7677, 343);
6041   AddAccessionToRefGeneTrackUserObject (uop, "Related", "P34345", 445, 0, 0);
6042   AddAccessionToRefGeneTrackUserObject (uop, "Reject", "S19635", 1765, 0, 0);
6043   AddAccessionToRefGeneTrackUserObject (uop, "Related", "Q14884", 664, 35, 97);
6044   sdp = ValNodeNew (NULL);
6045   sdp->choice = Seq_descr_user;
6046   sdp->data.ptrvalue = (Pointer) uop;
6047   if (! ObjMgrRegister (OBJ_SEQDESC, (Pointer) sdp)) {
6048      ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrRegister failed.");
6049   }
6050 }
6051 */
6052 
6053 #define CKA_GAPLEN  50 /* max allowed unaligned gap size */
6054 
6055 typedef struct cka_acc {
6056    CharPtr      accession;
6057    SeqIdPtr     sip_whole;
6058    SeqAlignPtr  sap;
6059    Int4         start_acc;
6060    Int4         stop_acc;
6061    Int4         start_seq;
6062    Int4         stop_seq;
6063    Uint1        strand;
6064    Int4         num;
6065    struct cka_acc PNTR next;
6066 } CKA_Acc, PNTR CKA_AccPtr;
6067 
6068 typedef struct ckablastopts {
6069   Int4 wordsize;
6070   FloatHi expect_value;
6071   Boolean allow_repeats;
6072 } CKABlastOptsData, PNTR CKABlastOptsPtr;
6073 
6074 static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr lip, CKABlastOptsPtr opts);
6075 
SPI_GetAccessionFromSeqId(SeqIdPtr sip,Int4Ptr gi,CharPtr PNTR id)6076 static Boolean SPI_GetAccessionFromSeqId(SeqIdPtr sip, Int4Ptr gi, CharPtr PNTR id)
6077 {
6078    Boolean numeric_id_type = FALSE;
6079    Int2 id_len;
6080    GiimPtr gip;
6081    ObjectIdPtr oip;
6082    TextSeqIdPtr textsip;
6083    DbtagPtr dbtag;
6084    PatentSeqIdPtr psip;
6085    PDBSeqIdPtr pdbsip;
6086 
6087    *id = NULL;
6088    *gi = 0;
6089 
6090    switch (sip->choice) {
6091    case SEQID_GI: case SEQID_GIBBSQ: case SEQID_GIBBMT:
6092       *gi = sip->data.intvalue;
6093       numeric_id_type = TRUE;
6094       break;
6095    case SEQID_GIIM:
6096       gip = (GiimPtr) sip->data.ptrvalue;
6097       *gi = gip->id;
6098       numeric_id_type = TRUE;
6099       break;
6100    case SEQID_LOCAL:
6101       oip = (ObjectIdPtr) sip->data.ptrvalue;
6102 
6103       if (oip->str) {
6104          id_len = StringLen(oip->str);
6105          *id = (CharPtr) MemNew(id_len+1);
6106          sprintf(*id, "%s", oip->str);
6107       } else {
6108          *id = (CharPtr) MemNew(6);
6109          sprintf(*id, "%d", oip->id);
6110       }
6111       break;
6112    case SEQID_GENBANK: case SEQID_EMBL: case SEQID_PIR: case SEQID_TPG: case SEQID_TPE: case SEQID_TPD:
6113    case SEQID_SWISSPROT: case SEQID_DDBJ: case SEQID_PRF:
6114    case SEQID_OTHER: case SEQID_GPIPE:
6115       textsip = (TextSeqIdPtr)sip->data.ptrvalue;
6116       id_len = StringLen(textsip->accession);
6117       *id = (CharPtr) MemNew(id_len+1);
6118       if (textsip->version > 0)
6119          sprintf(*id, "%s.%d", textsip->accession, textsip->version);
6120       else
6121          sprintf(*id, "%s", textsip->accession);
6122       break;
6123    case SEQID_GENERAL:
6124       dbtag = (DbtagPtr) sip->data.ptrvalue;
6125       if (dbtag->tag->str == NULL) {
6126          numeric_id_type = TRUE;
6127          *gi = dbtag->tag->id;
6128       } else {
6129          id_len = StringLen(dbtag->tag->str);
6130          *id = (CharPtr) MemNew(id_len+1);
6131          sprintf(*id, "%s", dbtag->tag->str);
6132       }
6133       break;
6134    case SEQID_PATENT:
6135       psip = (PatentSeqIdPtr) sip->data.ptrvalue;
6136       *gi = (Int4) psip->seqid;
6137       numeric_id_type = TRUE;
6138       break;
6139    case SEQID_PDB:
6140       pdbsip = (PDBSeqIdPtr) sip->data.ptrvalue;
6141       id_len = StringLen(pdbsip->mol);
6142       *id = (CharPtr) MemNew(id_len+4);
6143       sprintf(*id, "%s%d", pdbsip->mol, pdbsip->chain);
6144       break;
6145    default: break;
6146    }
6147 
6148    return numeric_id_type;
6149 }
6150 
CKA_FindAllTpaDescr(SeqEntryPtr sep,Pointer data,Int4 index,Int2 indent)6151 static void CKA_FindAllTpaDescr(SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
6152 {
6153    CKA_AccPtr         acc;
6154    CKA_AccPtr         PNTR acc_head;
6155    CKA_AccPtr         acc_prev;
6156    BioseqPtr          bsp;
6157    SeqMgrDescContext  context;
6158    UserFieldPtr       curr;
6159    ObjectIdPtr        oip;
6160    SeqDescrPtr        sdp;
6161    UserFieldPtr       ufp;
6162    UserObjectPtr      uop;
6163 
6164    acc_head = (CKA_AccPtr PNTR)data;
6165    acc_prev = *acc_head;
6166    while (acc_prev != NULL && acc_prev->next != NULL)
6167    {
6168       acc_prev = acc_prev->next;
6169    }
6170    sdp = NULL;
6171    if (IS_Bioseq(sep))
6172    {
6173       bsp = (BioseqPtr)sep->data.ptrvalue;
6174       if (ISA_na(bsp->mol))
6175       {
6176          while ((sdp = SeqMgrGetNextDescriptor(bsp, sdp, Seq_descr_user, &context)) != NULL)
6177          {
6178             uop = (UserObjectPtr)sdp->data.ptrvalue;
6179             if (!StringICmp(uop->type->str, "TpaAssembly"))
6180             {
6181                for (curr = uop->data; curr != NULL; curr = curr->next)
6182                {
6183                   if (curr->choice != 11) continue;
6184 
6185                   acc = (CKA_AccPtr)MemNew(sizeof(CKA_Acc));
6186                   acc->sip_whole = SeqIdSetDup(bsp->id);
6187                   /* will use these to mark the span for blast2seq */
6188                   acc->start_acc = acc->stop_acc = -1;
6189                   if (acc_prev == NULL)
6190                     *acc_head = acc_prev = acc;
6191                   else {
6192                     acc_prev->next = acc;
6193                     acc_prev = acc;
6194                   }
6195 
6196                   for (ufp = curr->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
6197                     oip = ufp->label;
6198                     if (oip == NULL) continue;
6199                     if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
6200                       acc->accession = StringSave((CharPtr)ufp->data.ptrvalue);
6201                     } else if (StringICmp (oip->str, "from") == 0 && ufp->choice == 2) {
6202                       acc->start_acc = (Int4) ufp->data.intvalue;
6203                     } else if (StringICmp (oip->str, "to") == 0 && ufp->choice == 2) {
6204                       acc->stop_acc = (Int4) ufp->data.intvalue;
6205                     }
6206                   }
6207                }
6208             }
6209          }
6210       }
6211    }
6212 }
6213 
CKA_SortAccs(VoidPtr ptr1,VoidPtr ptr2)6214 static int LIBCALLBACK CKA_SortAccs(VoidPtr ptr1, VoidPtr ptr2)
6215 {
6216    CKA_AccPtr  acc1;
6217    CKA_AccPtr  acc2;
6218 
6219    acc1 = *((CKA_AccPtr PNTR)ptr1);
6220    acc2 = *((CKA_AccPtr PNTR)ptr2);
6221    if (acc1->start_seq < acc2->start_seq)
6222       return -1;
6223    else if (acc1->start_seq > acc2->start_seq)
6224       return 1;
6225    else if (acc1->stop_seq < acc2->stop_seq)
6226       return -1;
6227    else if (acc1->stop_seq > acc2->stop_seq)
6228       return 1;
6229    else
6230       return 0; /* no alignment */
6231 }
6232 
SqnSeqIdFindBestAccession(SeqIdPtr sip)6233 static SeqIdPtr SqnSeqIdFindBestAccession (SeqIdPtr sip)
6234 {
6235 	Uint1 order[NUM_SEQID];
6236 
6237 	if (sip == NULL)
6238 		return NULL;
6239 	SeqIdBestRank(order, NUM_SEQID);
6240         order[SEQID_GI]=order[SEQID_LOCAL]+2;
6241         order[SEQID_PATENT]=order[SEQID_LOCAL]+1;
6242 	return SeqIdSelect (sip, order, NUM_SEQID);
6243 }
6244 
6245 
ValidateTPAHistAlign(BioseqPtr bsp,ValNodePtr PNTR errors)6246 NLM_EXTERN Boolean ValidateTPAHistAlign (BioseqPtr bsp, ValNodePtr PNTR errors)
6247 {
6248   ValNodePtr new_errors;
6249   Boolean    retval = TRUE;
6250   SeqAlignPtr salp;
6251 
6252   if (bsp == NULL || bsp->hist == NULL || bsp->hist->assembly == NULL) {
6253     return FALSE;
6254   }
6255 
6256   for (salp = bsp->hist->assembly; salp != NULL; salp = salp->next) {
6257     AlnMgr2IndexSingleChildSeqAlign(salp);
6258   }
6259 
6260   new_errors = ReportCoverageForBioseqSeqHist (bsp);
6261   if (new_errors != NULL) {
6262     ValNodeLink (errors, new_errors);
6263     retval = FALSE;
6264   }
6265   return retval;
6266 }
6267 
6268 
CKA_ValidateSeqAlign(SeqAlignPtr sap,CKA_AccPtr acc_head,Int4 bioseqlen,ValNodePtr PNTR errors)6269 static Boolean CKA_ValidateSeqAlign(SeqAlignPtr sap, CKA_AccPtr acc_head, Int4 bioseqlen, ValNodePtr PNTR errors)
6270 {
6271    CKA_AccPtr        acc;
6272    CKA_AccPtr        PNTR accarray;
6273    AMAlignIndex2Ptr  amaip;
6274    Int4              first, first_align = 0;
6275    Boolean           found;
6276    Int4              gi;
6277    Int4              i;
6278    Int4              j;
6279    Int4              k;
6280    Int4              last;
6281    Int4              longest = 0;
6282    Int4              max;
6283    Int4              n;
6284    Int4              prev;
6285    Boolean           retval = TRUE;
6286    CharPtr           textid;
6287    Char              textid2[42];
6288    CharPtr           err_msg;
6289    CharPtr           no_cover_fmt = "Primary accessions do not completely cover the bioseq %s:\n %s aligns to %d-%d but next aln is %s to %d-%d\n";
6290    CharPtr           no_cover_ok_gap_fmt = "Primary accessions do not completely cover the bioseq %s:\n %s aligns to %d-%d but the next aln is %s to %d-%d;\n the gap is less than %d and is acceptable.\n";
6291    CharPtr           bad_start_fmt = "Primary accessions do not completely cover the bioseq %s:\n %s (the first aln) starts at position %d\n";
6292    CharPtr           bad_start_ok_gap_fmt = "Primary accessions do not completely cover the bioseq %s:\n %s (the first alignment) starts at position %d, but the gap is less than %d and is acceptable.\n";
6293    CharPtr           bad_end_fmt = "Primary accessions do not completely cover the bioseq %s:\n %s (the last aln) goes to %d, bioseq length is %d\n";
6294    CharPtr           bad_end_ok_gap_fmt = "Primary accessions do not completely cover the bioseq %s:\n %s (the last alignment) goes to %d, bioseq length is %d, but the gap is less than %d and is acceptable.\n";
6295 
6296    if (sap == NULL || sap->saip == NULL || sap->saip->indextype != INDEX_PARENT || errors == NULL)
6297       return FALSE;
6298 
6299    amaip = (AMAlignIndex2Ptr)(sap->saip);
6300    for (i=0; i<amaip->numsaps; i++)
6301    {
6302       acc = acc_head;
6303       found = FALSE;
6304       while (acc != NULL && !found)
6305       {
6306          if (amaip->saps[i] == acc->sap)
6307             found = TRUE;
6308          if (!found)
6309             acc = acc->next;
6310       }
6311       if (!found) /* big error */
6312          return FALSE;
6313       acc->num = i+1;
6314       AlnMgr2GetNthSeqRangeInSA(amaip->saps[i], 1, &acc->start_seq, &acc->stop_seq);
6315       AlnMgr2GetNthSeqRangeInSA(amaip->saps[i], 2, &acc->start_acc, &acc->stop_acc);
6316       acc->strand = AlnMgr2GetNthStrand(amaip->saps[i], 2);
6317       acc->start_seq++;
6318       acc->stop_seq++;
6319       acc->start_acc++;
6320       acc->stop_acc++;
6321    }
6322    acc = acc_head;
6323    i = 0;
6324    while (acc != NULL)
6325    {
6326       if (acc->start_seq == 0 && acc->stop_seq == 0)
6327       {
6328          AlnMgr2GetNthSeqRangeInSA(acc->sap, 1, &acc->start_seq, &acc->stop_seq);
6329          AlnMgr2GetNthSeqRangeInSA(acc->sap, 2, &acc->start_acc, &acc->stop_acc);
6330          acc->strand = AlnMgr2GetNthStrand(acc->sap, 2);
6331          acc->start_seq++;
6332          acc->stop_seq++;
6333          acc->start_acc++;
6334          acc->stop_acc++;
6335       }
6336       if (acc->num == 0)
6337          acc->num = amaip->numsaps; /* sort these guys all to the end */
6338       i++;
6339       acc = acc->next;
6340    }
6341    accarray = (CKA_AccPtr PNTR)MemNew(i*sizeof(CKA_AccPtr));
6342    i = 0;
6343    acc = acc_head;
6344    while (acc != NULL)
6345    {
6346       accarray[i] = acc;
6347       i++;
6348       acc = acc->next;
6349    }
6350    HeapSort(accarray, i, sizeof(CKA_AccPtr), CKA_SortAccs);
6351    n=0;
6352    while (accarray[n]->sap == NULL && n < i)
6353    {
6354       n++;
6355    }
6356    SPI_GetAccessionFromSeqId(SqnSeqIdFindBestAccession(accarray[0]->sip_whole), &gi, &textid);
6357    if (textid == NULL)
6358    {
6359       sprintf(textid2, "%d", gi);
6360       textid = textid2;
6361    }
6362    first = last = -1;
6363    prev = -1;
6364    retval = TRUE;
6365    for (j=0; j<i /*&& first <=0*/ ; j++)
6366    {
6367       acc = accarray[j];
6368       if (acc->sap != NULL)
6369       {
6370         if (first == -1) {
6371           first = acc->start_seq;
6372           first_align = j;
6373         }
6374         last = MAX(last, acc->stop_seq);
6375       } else {
6376         continue;
6377       }
6378       if (prev != -1)
6379       {
6380          if (acc->start_seq > prev + CKA_GAPLEN)
6381          {
6382             err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (no_cover_fmt) + StringLen (textid) + StringLen (accarray[j-1]->accession)
6383                                                          + StringLen (acc->accession) + 60));
6384             sprintf (err_msg, no_cover_fmt,
6385                      textid, accarray[j-1]->accession, accarray[j-1]->start_seq, accarray[j-1]->stop_seq, acc->accession, acc->start_seq, acc->stop_seq);
6386             ValNodeAddPointer (errors, 0, err_msg);
6387             retval = FALSE;
6388          }
6389          else if (acc->start_seq > prev)
6390          {
6391             err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (no_cover_ok_gap_fmt) + StringLen (textid)
6392                                                          + StringLen (accarray[j-1]->accession)
6393                                                          + StringLen (acc->accession)
6394                                                          + 75));
6395             sprintf (err_msg, no_cover_ok_gap_fmt,
6396                      textid, accarray[j-1]->accession, accarray[j-1]->start_seq, accarray[j-1]->stop_seq, acc->accession, acc->start_seq, acc->stop_seq, CKA_GAPLEN);
6397             ValNodeAddPointer (errors, 0, err_msg);
6398             retval = FALSE;
6399          }
6400       }
6401       prev = acc->stop_seq+1;
6402    }
6403    if (first != 1 || last != bioseqlen)
6404    {
6405       if (first > CKA_GAPLEN)
6406       {
6407          err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_start_fmt) + StringLen (textid)
6408                                                       + StringLen (accarray[first_align]->accession)
6409                                                      + 15));
6410          sprintf (err_msg, bad_start_fmt,
6411                           textid, accarray[first_align]->accession, accarray[first_align]->start_seq);
6412          ValNodeAddPointer (errors, 0, err_msg);
6413          retval = FALSE;
6414       }
6415       else if (first != 1)
6416       {
6417          err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_start_ok_gap_fmt)
6418                                                       + StringLen (textid)
6419                                                       + StringLen (accarray[first_align]->accession)
6420                                                       + 30));
6421          sprintf (err_msg, bad_start_ok_gap_fmt,
6422                   textid, accarray[first_align]->accession, accarray[first_align]->start_seq, CKA_GAPLEN);
6423          ValNodeAddPointer (errors, 0, err_msg);
6424       }
6425       max = 0;
6426       for (k=0; k<i; k++)
6427       {
6428          if (accarray[k]->stop_seq > max)
6429          {
6430             max = accarray[k]->stop_seq;
6431             longest = k;
6432          }
6433       }
6434       if (accarray[longest]->stop_seq < bioseqlen-CKA_GAPLEN)
6435       {
6436          err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_end_fmt)
6437                                                       + StringLen (textid)
6438                                                       + StringLen (accarray[longest]->accession)
6439                                                       + 30));
6440          sprintf (err_msg, bad_end_fmt,
6441                           textid, accarray[longest]->accession, accarray[longest]->stop_seq, bioseqlen);
6442          ValNodeAddPointer (errors, 0, err_msg);
6443          retval = FALSE;
6444       }
6445       else if (accarray[longest]->stop_seq < bioseqlen)
6446       {
6447          err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_end_ok_gap_fmt)
6448                                                       + StringLen (textid)
6449                                                       + StringLen (accarray[longest]->accession)
6450                                                       + 45));
6451          sprintf (err_msg, bad_end_ok_gap_fmt,
6452                            textid, accarray[longest]->accession, accarray[longest]->stop_seq, bioseqlen, CKA_GAPLEN);
6453          ValNodeAddPointer (errors, 0, err_msg);
6454       }
6455       MemFree(accarray);
6456       accarray = NULL;
6457    }
6458    MemFree(accarray);
6459    return retval;
6460 }
6461 
FrameVwr(VieweR vwr,SegmenT pict)6462 static void FrameVwr (
6463   VieweR vwr,
6464   SegmenT pict
6465 )
6466 
6467 {
6468   RecT  r;
6469 
6470   ResetClip ();
6471   ObjectRect (vwr, &r);
6472   FrameRect (&r);
6473 }
6474 
CKA_ShowAln(SeqAlignPtr sap,CKA_AccPtr acc_head)6475 static void CKA_ShowAln(SeqAlignPtr sap, CKA_AccPtr acc_head)
6476 {
6477    CKA_AccPtr   acc;
6478    BioseqPtr    bsp;
6479    DenseSegPtr  dsp = NULL;
6480    Boolean      found;
6481    GrouP        g;
6482    Int4         gi;
6483    Int4         i;
6484    Int4         len;
6485    Int4         numsaps;
6486    SegmenT      picture;
6487    SeqAlignPtr  salp;
6488    SeqIdPtr     sip = NULL;
6489    Int4         start;
6490    Int4         start_r;
6491    Int4         stop;
6492    Int4         stop_r;
6493    Char         tmp[42];
6494    CharPtr      textid;
6495    Char         textid2[42];
6496    VieweR       v;
6497    WindoW       w;
6498 
6499    w = FixedWindow(-1, -1, -1, -1, "TPA display", StdCloseWindowProc);
6500    g = HiddenGroup(w, 1, 0, NULL);
6501    v = CreateViewer(g, 750, 300, TRUE, TRUE);
6502    picture = CreatePicture();
6503    salp = (SeqAlignPtr)(sap->segs);
6504    numsaps = 0;
6505    while (salp != NULL)
6506    {
6507       numsaps++;
6508       salp = salp->next;
6509    }
6510    salp = (SeqAlignPtr)(sap->segs);
6511    numsaps++;
6512    if (salp != NULL) {
6513      dsp = (DenseSegPtr)(salp->segs);
6514    }
6515    if (dsp != NULL) {
6516      sip = dsp->ids;
6517    }
6518    if (sip == NULL) return;
6519    SPI_GetAccessionFromSeqId(SqnSeqIdFindBestAccession(sip), &gi, &textid);
6520    if (textid == NULL)
6521    {
6522       sprintf(textid2, "%d", gi);
6523       textid = textid2;
6524    }
6525    bsp = BioseqLockById(sip);
6526    len = bsp->length;
6527    AddRectangle(picture, 0, numsaps*10, (bsp->length*680)/len, numsaps*10-7, 0, TRUE, 0);
6528    sprintf(tmp, "1");
6529    AddLabel(picture, 0-10, numsaps*10-3, tmp, 0, 0, MIDDLE_LEFT, 0);
6530    sprintf(tmp, "%d  %s", bsp->length, textid);
6531    AddLabel(picture, ((bsp->length+10)*680)/len, numsaps*10-3, tmp, 0, 0, MIDDLE_RIGHT, 0);
6532    BioseqUnlock(bsp);
6533    i = numsaps-1;
6534    while (salp != NULL)
6535    {
6536       acc = acc_head;
6537       found = FALSE;
6538       while (acc != NULL && !found)
6539       {
6540          if (acc->sap == salp)
6541             found = TRUE;
6542          else
6543             acc = acc->next;
6544       }
6545       AlnMgr2GetNthSeqRangeInSA(salp, 1, &start, &stop);
6546       start_r = (start*680)/len;
6547       stop_r = (stop*680)/len;
6548       AddRectangle(picture, start_r, i*10, stop_r, i*10-7, 0, TRUE, 0);
6549       dsp = (DenseSegPtr)(salp->segs);
6550       sprintf(tmp, "%d", start+1);
6551       AddLabel(picture, start_r-10, i*10-3, tmp, 0, 0, MIDDLE_LEFT, 0);
6552       if (acc != NULL && acc->accession != NULL) {
6553         sprintf(tmp, "%d  %s", stop+1, acc->accession);
6554         AddLabel(picture, stop_r+10, i*10-3, tmp, 0, 0, MIDDLE_RIGHT, 0);
6555       }
6556       salp = salp->next;
6557       i--;
6558    }
6559    AttachPicture(v, picture, 0, 0, UPPER_LEFT, 1, 1, FrameVwr);
6560    Show(w);
6561 }
6562 
6563 
PrintTPAHistErrors(LogInfoPtr lip,ValNodePtr errors)6564 static void PrintTPAHistErrors (LogInfoPtr lip, ValNodePtr errors)
6565 {
6566   ValNodePtr vnp;
6567 
6568   if (lip == NULL || lip->fp == NULL || errors == NULL) return;
6569 
6570   for (vnp = errors; vnp != NULL; vnp = vnp->next)
6571   {
6572     fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
6573     lip->data_in_log = TRUE;
6574   }
6575   fprintf (lip->fp, "\n\n");
6576 }
6577 
6578 
CKA_RunChecker(SeqEntryPtr sep,CKABlastOptsPtr opts)6579 static void CKA_RunChecker(SeqEntryPtr sep, CKABlastOptsPtr opts)
6580 {
6581    CKA_AccPtr   acc;
6582    CKA_AccPtr   acc_head;
6583    CKA_AccPtr   acc_head_next;
6584    CKA_AccPtr   acc_head_prev;
6585    CKA_AccPtr   acc_head_real;
6586    CKA_AccPtr   acc_head_tmp;
6587    BioseqPtr    bsp;
6588    Boolean      found;
6589    Int4         gi;
6590    SeqIdPtr     lastid;
6591    SeqAlignPtr  sap;
6592    SeqHistPtr   shp;
6593    CharPtr      textid;
6594    Char         textid2[42];
6595    LogInfoPtr   lip;
6596    ValNodePtr   err_list;
6597    CharPtr      err_msg;
6598    CharPtr      no_align_fmt = "Accession %s does not align to the bioseq %s.\n";
6599 
6600    if (sep == NULL)
6601    {
6602       Message(MSG_ERROR, "Null SeqEntry passed to CKA_RunChecker");
6603       return;
6604    }
6605    acc_head = NULL;
6606    SeqEntryExplore(sep, &acc_head, CKA_FindAllTpaDescr);
6607    lastid = NULL;
6608    if (acc_head == NULL)
6609    {
6610       Message(MSG_ERROR, "No Tpa features found in SeqEntry.");
6611       return;
6612    }
6613 
6614    lip = OpenLog ("TPA Alignment Assembly Problems");
6615 
6616    acc_head_real = acc_head;
6617    while (acc_head != NULL)
6618    {
6619       lastid = acc_head->sip_whole;
6620       acc_head_prev = acc_head;
6621       acc_head_tmp = acc_head->next;
6622       found = FALSE;
6623       while (!found && acc_head_tmp != NULL)
6624       {
6625          if (SeqIdComp(lastid, acc_head_tmp->sip_whole) != SIC_YES)
6626             found = TRUE;
6627          else
6628          {
6629             acc_head_prev = acc_head_tmp;
6630             acc_head_tmp = acc_head_tmp->next;
6631          }
6632       }
6633       acc_head_next = acc_head_prev->next;
6634       acc_head_prev->next = NULL;
6635       bsp = BioseqLockById(acc_head->sip_whole);
6636       if (ISA_na(bsp->mol))
6637       {
6638          sap = CKA_MakeAlign(bsp, acc_head, lip, opts);
6639          acc = acc_head;
6640          while (acc != NULL && acc->sap == NULL)
6641          {
6642             acc = acc->next;
6643          }
6644          SPI_GetAccessionFromSeqId(SqnSeqIdFindBestAccession(acc_head->sip_whole), &gi, &textid);
6645          if (textid == NULL)
6646          {
6647             sprintf(textid2, "%d", gi);
6648             textid = textid2;
6649          }
6650 
6651          err_list = NULL;
6652 
6653          /* report each accession that does not align to the bioseq */
6654          acc = acc_head;
6655          while (acc != NULL)
6656          {
6657            if (acc->sap == NULL)
6658            {
6659              err_msg = (CharPtr) MemNew (sizeof(Char) * (StringLen (no_align_fmt) + StringLen (acc->accession) + StringLen (textid)));
6660              sprintf (err_msg, no_align_fmt, acc->accession, textid);
6661              ValNodeAddPointer (&err_list, 0, err_msg);
6662            }
6663            acc = acc->next;
6664          }
6665 
6666          if (sap != NULL) {
6667             AlnMgr2IndexLite(sap);
6668             AlnMgr2SortAlnSetByNthRowPos(sap, 1);
6669 	          /* make seq-hist and add it to record */
6670 	          if (bsp->hist != NULL)
6671 	          {
6672 	              shp = bsp->hist;
6673 	              if (shp->assembly != NULL)
6674 	                SeqAlignSetFree(shp->assembly);
6675 	              shp->assembly = (SeqAlignPtr)(sap->segs);
6676 	          }
6677             else
6678 	          {
6679 	              shp = SeqHistNew();
6680 	              shp->assembly = (SeqAlignPtr)(sap->segs);
6681 	              bsp->hist = shp;
6682 	          }
6683          }
6684 
6685          if (ValidateTPAHistAlign(bsp, &err_list))
6686          {
6687             fprintf (lip->fp, "Alignments were successfully created and are being added to %s.\n", textid);
6688             lip->data_in_log = TRUE;
6689             PrintTPAHistErrors (lip, err_list);
6690             err_list = ValNodeFreeData (err_list);
6691          }
6692 	       else if (sap != NULL)
6693          {
6694             fprintf (lip->fp, "Alignments were created but are not valid. They are being added to %s for review.\n", textid);
6695             lip->data_in_log = TRUE;
6696             PrintTPAHistErrors (lip, err_list);
6697             err_list = ValNodeFreeData (err_list);
6698          }
6699          else if (sap == NULL)
6700          {
6701             fprintf (lip->fp, "No alignments could be created for %s.\n", textid);
6702             lip->data_in_log = TRUE;
6703             PrintTPAHistErrors (lip, err_list);
6704             err_list = ValNodeFreeData (err_list);
6705             acc_head = acc_head_next;
6706             BioseqUnlock (bsp);
6707             continue;
6708          } else {
6709             PrintTPAHistErrors (lip, err_list);
6710             err_list = ValNodeFreeData (err_list);
6711          }
6712 
6713          if (sap != NULL) {
6714             sap->segs = NULL;
6715             SeqAlignFree(sap);
6716          }
6717 	     }
6718      else
6719      {
6720         fprintf (lip->fp, "%s is annotated on a non-nucleotide bioseq.\n", acc_head->accession);
6721         lip->data_in_log = TRUE;
6722      }
6723      BioseqUnlock (bsp);
6724      acc_head = acc_head_next;
6725   }
6726   /*CKA_ShowAln(sap, acc_head_real);*/
6727   while (acc_head_real != NULL)
6728   {
6729      acc_head_tmp = acc_head_real->next;
6730      MemFree(acc_head_real->accession);
6731      SeqIdFree(acc_head_real->sip_whole);
6732      MemFree(acc_head_real);
6733      acc_head_real = acc_head_tmp;
6734   }
6735   CloseLog (lip);
6736   lip = FreeLog (lip);
6737 }
6738 
6739 
6740 typedef struct seqalignrow {
6741   Int4 start;
6742   Int4 stop;
6743   Uint1 strand;
6744 } SeqAlignRowData, PNTR SeqAlignRowPtr;
6745 
SeqAlignRowNew(Int4 start,Int4 stop,Uint1 strand)6746 static SeqAlignRowPtr SeqAlignRowNew (Int4 start, Int4 stop, Uint1 strand)
6747 {
6748   SeqAlignRowPtr r;
6749   Int4 tmp;
6750 
6751   r = (SeqAlignRowPtr) MemNew (sizeof (SeqAlignRowData));
6752   r->start = start;
6753   r->stop = stop;
6754 
6755   if (r->start > r->stop) {
6756     tmp = r->start;
6757     r->start = r->stop;
6758     r->stop = tmp;
6759   }
6760   r->strand = strand;
6761   return r;
6762 }
6763 
6764 
SeqAlignRowCopy(SeqAlignRowPtr orig)6765 static SeqAlignRowPtr SeqAlignRowCopy (SeqAlignRowPtr orig)
6766 {
6767   SeqAlignRowPtr r = NULL;
6768 
6769   if (orig != NULL) {
6770     r = SeqAlignRowNew (orig->start, orig->stop, orig->strand);
6771   }
6772   return r;
6773 }
6774 
6775 
SeqAlignRowFree(SeqAlignRowPtr r)6776 static SeqAlignRowPtr SeqAlignRowFree (SeqAlignRowPtr r)
6777 {
6778   r = MemFree (r);
6779   return r;
6780 }
6781 
6782 
RowDiff(SeqAlignRowPtr r1,SeqAlignRowPtr r2)6783 static Int4 RowDiff (SeqAlignRowPtr r1, SeqAlignRowPtr r2)
6784 {
6785   Int4 diff = 0;
6786 
6787   if (r1 == NULL || r2 == NULL) {
6788     return -1;
6789   }
6790 
6791   diff = ABS(r1->start - r2->start) + ABS (r1->stop - r2->stop);
6792   return diff;
6793 }
6794 
6795 
DoesRow1ContainRow2(SeqAlignRowPtr row1,SeqAlignRowPtr row2)6796 static Boolean DoesRow1ContainRow2 (SeqAlignRowPtr row1, SeqAlignRowPtr row2)
6797 {
6798   if (row1 == NULL || row2 == NULL) {
6799     return FALSE;
6800   }
6801 
6802   if (row1->start <= row2->start && row1->stop >= row2->stop) {
6803     return TRUE;
6804   } else {
6805     return FALSE;
6806   }
6807 }
6808 
6809 
DoesRowContainPoint(SeqAlignRowPtr row,Int4 point)6810 static Boolean DoesRowContainPoint (SeqAlignRowPtr row, Int4 point)
6811 {
6812   if (row == NULL) {
6813     return FALSE;
6814   }
6815 
6816   if (row->start <= point && row->stop >= point) {
6817     return TRUE;
6818   } else {
6819     return FALSE;
6820   }
6821 }
6822 
6823 
SeqAlignRowOverlap(SeqAlignRowPtr r1,SeqAlignRowPtr r2)6824 static Int4 SeqAlignRowOverlap (SeqAlignRowPtr r1, SeqAlignRowPtr r2)
6825 {
6826   Int4 overlap = 0;
6827 
6828   if (r1 == NULL || r2 == NULL) {
6829     return 0;
6830   }
6831   if (r1->start <= r2->start) {
6832     if (r1->stop < r2->stop) {
6833       /* completely before */
6834       overlap = 0;
6835     } else if (r1->stop >= r2->stop) {
6836       /* completely contains */
6837       overlap = r2->stop - r2->start + 1;
6838     } else {
6839       /* partial overlap */
6840       overlap = r1->stop - r2->start + 1;
6841     }
6842   } else {
6843     if (r1->start > r2->stop) {
6844       /* completely after */
6845       overlap = 0;
6846     } else if (r1->stop <= r2->stop) {
6847       /* completely contained */
6848       overlap = r1->stop - r1->start + 1;
6849     } else {
6850       /* partial overlap */
6851       overlap = r2->stop - r1->start + 1;
6852     }
6853   }
6854   return overlap;
6855 }
6856 
6857 
SeqAlignRowConflict(SeqAlignRowPtr r1,SeqAlignRowPtr r2,Int4 fuzz)6858 static Boolean SeqAlignRowConflict (SeqAlignRowPtr r1, SeqAlignRowPtr r2, Int4 fuzz)
6859 {
6860   if (r1 == NULL || r2 == NULL) {
6861     return FALSE;
6862   }
6863   if (DoesRow1ContainRow2(r1, r2)) {
6864     return TRUE;
6865   } else if (DoesRow1ContainRow2(r2, r1)) {
6866     return TRUE;
6867   } else if (SeqAlignRowOverlap (r1, r2) > fuzz) {
6868     return TRUE;
6869   } else {
6870     return FALSE;
6871   }
6872 }
6873 
6874 
SeqAlignRowLen(SeqAlignRowPtr r)6875 static Int4 SeqAlignRowLen (SeqAlignRowPtr r)
6876 {
6877   Int4 len = 0;
6878 
6879   if (r != NULL) {
6880     len = r->stop - r->start + 1;
6881   }
6882   return len;
6883 }
6884 
6885 
6886 
6887 typedef struct seqalignsort {
6888   SeqAlignRowPtr row1;
6889   SeqAlignRowPtr row2;
6890   SeqAlignPtr salp;
6891 } SeqAlignSortData, PNTR SeqAlignSortPtr;
6892 
6893 
SeqAlignSortNew(SeqAlignPtr salp)6894 static SeqAlignSortPtr SeqAlignSortNew (SeqAlignPtr salp)
6895 {
6896   SeqAlignSortPtr s;
6897 
6898   if (salp == NULL) {
6899     return NULL;
6900   }
6901 
6902   s = (SeqAlignSortPtr) MemNew (sizeof (SeqAlignSortData));
6903   s->salp = SeqAlignDup (salp);
6904 
6905   AlnMgr2IndexSingleChildSeqAlign(s->salp);
6906 
6907   s->row1 = SeqAlignRowNew (SeqAlignStart (s->salp, 0), SeqAlignStop (s->salp, 0), SeqAlignStrand (s->salp, 0));
6908   s->row2 = SeqAlignRowNew (SeqAlignStart (s->salp, 1), SeqAlignStop (s->salp, 1), SeqAlignStrand (s->salp, 1));
6909 
6910   return s;
6911 }
6912 
6913 
SeqAlignSortFree(SeqAlignSortPtr s)6914 static SeqAlignSortPtr SeqAlignSortFree (SeqAlignSortPtr s)
6915 {
6916   if (s != NULL) {
6917     s->row1 = SeqAlignRowFree (s->row1);
6918     s->row2 = SeqAlignRowFree (s->row2);
6919     s->salp = SeqAlignFree (s->salp);
6920     s = MemFree (s);
6921   }
6922   return s;
6923 }
6924 
6925 
SeqAlignSortCopy(SeqAlignSortPtr s)6926 static SeqAlignSortPtr SeqAlignSortCopy (SeqAlignSortPtr s)
6927 {
6928   SeqAlignSortPtr copy = NULL;
6929 
6930   if (s != NULL) {
6931     copy = (SeqAlignSortPtr) MemNew (sizeof (SeqAlignSortData));
6932     copy->salp = SeqAlignDup (s->salp);
6933     AlnMgr2IndexSingleChildSeqAlign(copy->salp);
6934     copy->row1 = SeqAlignRowCopy (s->row1);
6935     copy->row2 = SeqAlignRowCopy (s->row2);
6936   }
6937   return copy;
6938 }
6939 
6940 
SeqAlignSortListNew(SeqAlignPtr salp)6941 static ValNodePtr SeqAlignSortListNew (SeqAlignPtr salp)
6942 {
6943   ValNodePtr list = NULL;
6944   SeqAlignPtr salp_next;
6945 
6946   while (salp != NULL) {
6947     salp_next = salp->next;
6948     salp->next = NULL;
6949     ValNodeAddPointer (&list, 0, SeqAlignSortNew (salp));
6950     salp = salp_next;
6951   }
6952   return list;
6953 }
6954 
6955 
SeqAlignSortListFree(ValNodePtr vnp)6956 static ValNodePtr SeqAlignSortListFree (ValNodePtr vnp)
6957 {
6958   ValNodePtr vnp_next;
6959 
6960   while (vnp != NULL) {
6961     vnp_next = vnp->next;
6962     vnp->next = NULL;
6963     vnp->data.ptrvalue = SeqAlignSortFree (vnp->data.ptrvalue);
6964     vnp = ValNodeFree (vnp);
6965     vnp = vnp_next;
6966   }
6967   return vnp;
6968 }
6969 
6970 
SeqAlignSortConflict(SeqAlignSortPtr s1,SeqAlignSortPtr s2,Int4 fuzz)6971 static Boolean SeqAlignSortConflict (SeqAlignSortPtr s1, SeqAlignSortPtr s2, Int4 fuzz)
6972 {
6973   if (s1 == NULL || s2 == NULL) {
6974     return FALSE;
6975   } else if (SeqAlignRowConflict (s1->row1, s2->row1, fuzz)) {
6976     return TRUE;
6977   } else if (SeqAlignRowConflict (s1->row2, s2->row2, fuzz)) {
6978     return TRUE;
6979   } else {
6980     return FALSE;
6981   }
6982 }
6983 
6984 
SeqAlignSortListLongestInterval(ValNodePtr list)6985 static Int4 SeqAlignSortListLongestInterval (ValNodePtr list)
6986 {
6987   Int4 len, max = 0;
6988   ValNodePtr vnp;
6989   SeqAlignSortPtr s;
6990 
6991   for (vnp = list; vnp != NULL; vnp = vnp->next) {
6992     s = vnp->data.ptrvalue;
6993     if (s != NULL && s->row1 != NULL) {
6994       len = SeqAlignRowLen (s->row1);
6995       if (len > max) {
6996         max = len;
6997       }
6998     }
6999   }
7000   return max;
7001 }
7002 
7003 
SeqAlignRowFromSeqAlignSort(SeqAlignSortPtr s,Int4 row)7004 static SeqAlignRowPtr SeqAlignRowFromSeqAlignSort (SeqAlignSortPtr s, Int4 row)
7005 {
7006   if (s == NULL) {
7007     return NULL;
7008   } else if (row == 1) {
7009     return s->row1;
7010   } else {
7011     return s->row2;
7012   }
7013 }
7014 
7015 
SeqAlignSortRowStrand(SeqAlignSortPtr s,Int4 row)7016 static Uint1 SeqAlignSortRowStrand (SeqAlignSortPtr s, Int4 row)
7017 {
7018   Uint1 strand = Seq_strand_plus;
7019   SeqAlignRowPtr r;
7020 
7021   r = SeqAlignRowFromSeqAlignSort (s, row);
7022   if (r != NULL) {
7023     strand = r->strand;
7024   }
7025   return strand;
7026 }
7027 
7028 
DoesSeqAlignSort1ContainSeqAlignSort2(SeqAlignSortPtr s1,SeqAlignSortPtr s2)7029 static Boolean DoesSeqAlignSort1ContainSeqAlignSort2 (SeqAlignSortPtr s1, SeqAlignSortPtr s2)
7030 {
7031   if (s1 == NULL || s2 == NULL) {
7032     return FALSE;
7033   } else if (DoesRow1ContainRow2 (s1->row1, s2->row1) && DoesRow1ContainRow2(s1->row2, s2->row2)) {
7034     return TRUE;
7035   } else {
7036     return FALSE;
7037   }
7038 }
7039 
7040 
SeqAlignSortListFindBestStrand(ValNodePtr vnp,Int4 row)7041 static Uint1 SeqAlignSortListFindBestStrand (ValNodePtr vnp, Int4 row)
7042 {
7043   Int4 num_plus = 0, num_minus = 0, num_align, num = 0;
7044   Uint4 plus_len = 0, minus_len = 0;
7045   SeqAlignSortPtr s;
7046 
7047   if (vnp == NULL) {
7048     return Seq_strand_plus;
7049   } else if (vnp->next == NULL) {
7050     s = (SeqAlignSortPtr) vnp->data.ptrvalue;
7051     if (s == NULL) {
7052       return Seq_strand_plus;
7053     } else {
7054       return SeqAlignSortRowStrand(s, row);
7055     }
7056   }
7057 
7058   /* count the alignments */
7059   num_align = ValNodeLen (vnp);
7060 
7061   /* only look at strands from the first half of the alignments */
7062   num_align = num_align / 2;
7063 
7064   while (vnp != NULL && num < num_align) {
7065     s = (SeqAlignSortPtr) vnp->data.ptrvalue;
7066     if (s != NULL) {
7067       if (SeqAlignSortRowStrand(s, row) == Seq_strand_minus) {
7068         num_minus++;
7069         if (row == 1) {
7070           minus_len += SeqAlignRowLen (s->row1);
7071         } else {
7072           minus_len += SeqAlignRowLen (s->row2);
7073         }
7074       } else {
7075         num_plus++;
7076         if (row == 1) {
7077           plus_len += SeqAlignRowLen (s->row1);
7078         } else {
7079           plus_len += SeqAlignRowLen (s->row2);
7080         }
7081       }
7082     }
7083     vnp = vnp->next;
7084     num++;
7085   }
7086 
7087   if (num_minus == 0) {
7088     return Seq_strand_plus;
7089   } else if (num_plus == 0) {
7090     return Seq_strand_minus;
7091   } else if (minus_len / num_minus > plus_len / num_plus) {
7092     return Seq_strand_minus;
7093   } else {
7094     return Seq_strand_plus;
7095   }
7096 }
7097 
7098 
SeqAlignSortListMarkStrand(ValNodePtr vnp,Int4 row,Uint1 strand)7099 static void SeqAlignSortListMarkStrand (ValNodePtr vnp, Int4 row, Uint1 strand)
7100 {
7101   while (vnp != NULL) {
7102     if (SeqAlignSortRowStrand (vnp->data.ptrvalue, row) == strand) {
7103       vnp->choice = 1;
7104     }
7105     vnp = vnp->next;
7106   }
7107 }
7108 
7109 
SeqAlignSortListRemoveMarked(ValNodePtr PNTR list)7110 static void SeqAlignSortListRemoveMarked (ValNodePtr PNTR list)
7111 {
7112   ValNodePtr remove_list;
7113 
7114   if (list == NULL) {
7115     return;
7116   }
7117 
7118   remove_list = ValNodeExtractList (list, 1);
7119   remove_list = SeqAlignSortListFree (remove_list);
7120 }
7121 
7122 
SeqAlignSortListRemoveConflictingStrands(ValNodePtr PNTR list,Int4 row)7123 static Uint1 SeqAlignSortListRemoveConflictingStrands (ValNodePtr PNTR list, Int4 row)
7124 {
7125   Uint1 strand;
7126 
7127   if (list == NULL) {
7128     return Seq_strand_plus;
7129   }
7130 
7131   strand = SeqAlignSortListFindBestStrand (*list, row);
7132   if (strand == Seq_strand_plus) {
7133     SeqAlignSortListMarkStrand (*list, row, Seq_strand_minus);
7134   } else {
7135     SeqAlignSortListMarkStrand (*list, row, Seq_strand_plus);
7136   }
7137 
7138   SeqAlignSortListRemoveMarked (list);
7139   return strand;
7140 }
7141 
7142 
SeqAlignFromSeqAlignSortList(ValNodePtr vnp)7143 static SeqAlignPtr SeqAlignFromSeqAlignSortList (ValNodePtr vnp)
7144 {
7145   SeqAlignPtr salp_list = NULL, salp_prev = NULL;
7146   SeqAlignSortPtr s;
7147 
7148   while (vnp != NULL) {
7149     s = (SeqAlignSortPtr) vnp->data.ptrvalue;
7150     if (s != NULL && s->salp != NULL) {
7151       s->salp->next = NULL;
7152       if (salp_prev == NULL) {
7153         salp_list = s->salp;
7154       } else {
7155         salp_prev->next = s->salp;
7156       }
7157       salp_prev = s->salp;
7158       s->salp->next = NULL;
7159       /* NULL out entry in SeqAlignSort so that it will not be freed later */
7160       s->salp = NULL;
7161     }
7162     vnp = vnp->next;
7163   }
7164   return salp_list;
7165 }
7166 
7167 
CompareSeqAlignRow(SeqAlignRowPtr r1,SeqAlignRowPtr r2)7168 static int CompareSeqAlignRow (SeqAlignRowPtr r1, SeqAlignRowPtr r2)
7169 {
7170   int rval = 0;
7171 
7172   if (r1 == NULL && r2 == NULL) {
7173     rval = 0;
7174   } else if (r1 == NULL) {
7175     rval = -1;
7176   } else if (r2 == NULL) {
7177     rval = 1;
7178   } else if (r1->start < r2->start) {
7179     rval = -1;
7180   } else if (r1->start > r2->start) {
7181     rval = 1;
7182   } else if (r1->stop < r2->stop) {
7183     rval = -1;
7184   } else if (r1->stop > r2->stop) {
7185     rval = 1;
7186   } else if (r1->strand < r2->strand) {
7187     rval = -1;
7188   } else if (r1->strand > r2->strand) {
7189     rval = 1;
7190   }
7191   return rval;
7192 }
7193 
7194 
CompareSeqAlignSortPreferRow1(SeqAlignSortPtr s1,SeqAlignSortPtr s2)7195 static int CompareSeqAlignSortPreferRow1 (SeqAlignSortPtr s1, SeqAlignSortPtr s2)
7196 {
7197   int rval = 0;
7198   if (s1 == NULL && s2 == NULL) {
7199     rval = 0;
7200   } else if (s1 == NULL) {
7201     rval = -1;
7202   } else if (s2 == NULL) {
7203     rval = 1;
7204   } else if ((rval = CompareSeqAlignRow (s1->row1,s2->row1)) == 0) {
7205     rval = CompareSeqAlignRow (s1->row2, s2->row2);
7206   }
7207   return rval;
7208 }
7209 
7210 
CompareSeqAlignSortPreferRow2(SeqAlignSortPtr s1,SeqAlignSortPtr s2)7211 static int CompareSeqAlignSortPreferRow2 (SeqAlignSortPtr s1, SeqAlignSortPtr s2)
7212 {
7213   int rval = 0;
7214   if (s1 == NULL && s2 == NULL) {
7215     rval = 0;
7216   } else if (s1 == NULL) {
7217     rval = -1;
7218   } else if (s2 == NULL) {
7219     rval = 1;
7220   } else if ((rval = CompareSeqAlignRow (s1->row2,s2->row2)) == 0) {
7221     rval = CompareSeqAlignRow (s1->row1, s2->row1);
7222   }
7223   return rval;
7224 }
7225 
7226 
7227 
SortVnpBySeqAlignSortRow1(VoidPtr ptr1,VoidPtr ptr2)7228 static int LIBCALLBACK SortVnpBySeqAlignSortRow1 (VoidPtr ptr1, VoidPtr ptr2)
7229 
7230 {
7231   ValNodePtr  vnp1;
7232   ValNodePtr  vnp2;
7233 
7234   if (ptr1 != NULL && ptr2 != NULL) {
7235     vnp1 = *((ValNodePtr PNTR) ptr1);
7236     vnp2 = *((ValNodePtr PNTR) ptr2);
7237     if (vnp1 != NULL && vnp2 != NULL) {
7238       return CompareSeqAlignSortPreferRow1 (vnp1->data.ptrvalue, vnp2->data.ptrvalue);
7239     }
7240   }
7241   return 0;
7242 }
7243 
7244 
SortVnpBySeqAlignSortRow2(VoidPtr ptr1,VoidPtr ptr2)7245 static int LIBCALLBACK SortVnpBySeqAlignSortRow2 (VoidPtr ptr1, VoidPtr ptr2)
7246 
7247 {
7248   ValNodePtr  vnp1;
7249   ValNodePtr  vnp2;
7250 
7251   if (ptr1 != NULL && ptr2 != NULL) {
7252     vnp1 = *((ValNodePtr PNTR) ptr1);
7253     vnp2 = *((ValNodePtr PNTR) ptr2);
7254     if (vnp1 != NULL && vnp2 != NULL) {
7255       return CompareSeqAlignSortPreferRow2 (vnp1->data.ptrvalue, vnp2->data.ptrvalue);
7256     }
7257   }
7258   return 0;
7259 }
7260 
7261 
DoesFirstRepeatContainAllOtherRepeats(ValNodePtr start,ValNodePtr stop)7262 static Boolean DoesFirstRepeatContainAllOtherRepeats (ValNodePtr start, ValNodePtr stop)
7263 {
7264   SeqAlignSortPtr s1, s2;
7265   ValNodePtr vnp;
7266 
7267   if (start == NULL || stop == NULL || stop == start->next) {
7268     return FALSE;
7269   }
7270   s1 = (SeqAlignSortPtr) start->data.ptrvalue;
7271   for (vnp = start->next; vnp != stop; vnp = vnp->next) {
7272     s2 = (SeqAlignSortPtr) vnp->data.ptrvalue;
7273     if (!DoesSeqAlignSort1ContainSeqAlignSort2 (s1, s2)) {
7274       return FALSE;
7275     }
7276   }
7277   return TRUE;
7278 }
7279 
7280 
MarkSubAlignments(ValNodePtr PNTR list)7281 static void MarkSubAlignments (ValNodePtr PNTR list)
7282 {
7283   ValNodePtr vnp1, vnp2;
7284 
7285   if (list == NULL) {
7286     return;
7287   }
7288 
7289   *list = ValNodeSort (*list, SortVnpBySeqAlignSortRow1);
7290 
7291   for (vnp1 = *list; vnp1 != NULL; vnp1 = vnp1->next) {
7292     if (vnp1->choice != 1) {
7293       for (vnp2 = vnp1->next; vnp2 != NULL; vnp2 = vnp2->next) {
7294         if (DoesSeqAlignSort1ContainSeqAlignSort2 (vnp1->data.ptrvalue, vnp2->data.ptrvalue)) {
7295           vnp2->choice = 1;
7296         }
7297       }
7298     }
7299   }
7300 }
7301 
7302 
SeqAlignSortListMarkRepeats(ValNodePtr PNTR list,Int4 row,Int4 fuzz)7303 static ValNodePtr SeqAlignSortListMarkRepeats (ValNodePtr PNTR list, Int4 row, Int4 fuzz)
7304 {
7305   ValNodePtr repeat_start, vnp, vnp_mark;
7306   ValNodePtr repeat_list = NULL, tmp_list;
7307   SeqAlignSortPtr s1, s2;
7308   SeqAlignRowPtr  interval, r2;
7309   Int4            diff;
7310   Boolean         is_repeat;
7311 
7312   if (list == NULL || *list == NULL || (*list)->next == NULL) {
7313     return NULL;
7314   }
7315 
7316   if (row == 1) {
7317     *list = ValNodeSort (*list, SortVnpBySeqAlignSortRow1);
7318   } else {
7319     *list = ValNodeSort (*list, SortVnpBySeqAlignSortRow2);
7320   }
7321 
7322   repeat_start = *list;
7323   s1 = repeat_start->data.ptrvalue;
7324   interval = SeqAlignRowCopy (SeqAlignRowFromSeqAlignSort(s1, row));
7325   for (vnp = (*list)->next; vnp != NULL; vnp = vnp->next) {
7326     s2 = vnp->data.ptrvalue;
7327     is_repeat = FALSE;
7328     r2 = SeqAlignRowFromSeqAlignSort (s2, row);
7329 
7330     if (interval->start <= r2->start && interval->stop >= r2->stop) {
7331       /* contained */
7332       is_repeat = TRUE;
7333     } else if (r2->start <= interval->start && r2->stop >= interval->stop) {
7334       /* contained */
7335       is_repeat = TRUE;
7336     } else if ((diff = RowDiff (interval, r2)) > -1 && diff < fuzz) {
7337       is_repeat = TRUE;
7338     }
7339     if (is_repeat) {
7340       if (interval->start > r2->start) {
7341         interval->start = r2->start;
7342       }
7343       if (interval->stop < r2->stop) {
7344         interval->stop = r2->stop;
7345       }
7346     } else {
7347       if (repeat_start->next != vnp) {
7348         tmp_list = NULL;
7349         for (vnp_mark = repeat_start; vnp_mark != vnp; vnp_mark = vnp_mark->next) {
7350           /* add copy to list of repeats */
7351           ValNodeAddPointer (&tmp_list, 0, SeqAlignSortCopy (vnp_mark->data.ptrvalue));
7352           /* mark as repeat for this row */
7353           vnp_mark->choice = row;
7354           s2 = vnp_mark->data.ptrvalue;
7355           if (SeqAlignRowLen(s2->row1) == 2300) {
7356             vnp_mark->choice = row;
7357           }
7358         }
7359         ValNodeAddPointer (&repeat_list, 0, tmp_list);
7360       }
7361       repeat_start = vnp;
7362       s1 = vnp->data.ptrvalue;
7363       interval = SeqAlignRowFree (interval);
7364       interval = SeqAlignRowCopy (SeqAlignRowFromSeqAlignSort(s1, row));
7365     }
7366   }
7367 
7368   if (repeat_start->next != NULL) {
7369     tmp_list = NULL;
7370     for (vnp_mark = repeat_start; vnp_mark != vnp; vnp_mark = vnp_mark->next) {
7371       /* add copy to list of repeats */
7372       ValNodeAddPointer (&tmp_list, 0, SeqAlignSortCopy (vnp_mark->data.ptrvalue));
7373       /* mark as repeat for this row */
7374       vnp_mark->choice = row;
7375       s2 = vnp_mark->data.ptrvalue;
7376     }
7377     ValNodeAddPointer (&repeat_list, 0, tmp_list);
7378   }
7379 
7380   interval = SeqAlignRowFree (interval);
7381   return repeat_list;
7382 }
7383 
7384 
SeqAlignRowFuzzyCompare(SeqAlignRowPtr r1,SeqAlignRowPtr r2,Int4 fuzz)7385 static int SeqAlignRowFuzzyCompare (SeqAlignRowPtr r1, SeqAlignRowPtr r2, Int4 fuzz)
7386 {
7387   if (r1 == NULL && r2 == NULL) {
7388     return 0;
7389   } else if (r1 == NULL) {
7390     return -1;
7391   } else if (r2 == NULL) {
7392     return 1;
7393   }
7394 
7395   if (r1->stop < r2->start || r1->stop - r2->start < fuzz) {
7396     return -1;
7397   } else if (r2->stop < r1->start || r2->stop - r1->start < fuzz) {
7398     return 1;
7399   } else {
7400     return 0;
7401   }
7402 }
7403 
7404 
SeqAlignSortFuzzyCompare(SeqAlignSortPtr s1,SeqAlignSortPtr s2,Int4 row,Int4 fuzz)7405 static int SeqAlignSortFuzzyCompare (SeqAlignSortPtr s1, SeqAlignSortPtr s2, Int4 row, Int4 fuzz)
7406 {
7407   if (s1 == NULL && s2 == NULL) {
7408     return 0;
7409   } else if (s1 == NULL) {
7410     return -1;
7411   } else if (s2 == NULL) {
7412     return 1;
7413   } else if (row == 1) {
7414     return SeqAlignRowFuzzyCompare (s1->row1, s2->row1, fuzz);
7415   } else {
7416     return SeqAlignRowFuzzyCompare (s1->row2, s2->row2, fuzz);
7417   }
7418 }
7419 
7420 
SeqAlignSortListRemoveIntervalsOutOfOrder(ValNodePtr PNTR list,Int4 row,Int4 fuzz)7421 static void SeqAlignSortListRemoveIntervalsOutOfOrder (ValNodePtr PNTR list, Int4 row, Int4 fuzz)
7422 {
7423   ValNodePtr vnp, vnp_prev = NULL;
7424 
7425   if (list == NULL) {
7426     return;
7427   }
7428 
7429   for (vnp = *list; vnp != NULL; vnp = vnp->next) {
7430     if (vnp_prev != NULL && SeqAlignSortFuzzyCompare (vnp_prev->data.ptrvalue, vnp->data.ptrvalue, row, fuzz) != -1) {
7431       vnp->choice = 1;
7432     } else if (vnp->next != NULL && SeqAlignSortFuzzyCompare (vnp->data.ptrvalue, vnp->next->data.ptrvalue, row, fuzz) != -1) {
7433       if (vnp->next->next != NULL
7434           && SeqAlignSortFuzzyCompare (vnp->data.ptrvalue, vnp->next->next->data.ptrvalue, row, fuzz) == -1
7435           && SeqAlignSortFuzzyCompare (vnp->next->data.ptrvalue, vnp->next->next->data.ptrvalue, row, fuzz) != -1) {
7436         /* ok to keep this one, we'll toss the next one */
7437       } else {
7438         vnp->choice = 1;
7439       }
7440     }
7441     if (vnp->choice == 0) {
7442       vnp_prev = vnp;
7443     }
7444   }
7445 
7446   SeqAlignSortListRemoveMarked (list);
7447 }
7448 
7449 
GetRepeatIntervalFuzz(SeqAlignSortPtr s_repeat,SeqAlignSortPtr s_before,SeqAlignSortPtr s_after,Int4 row)7450 static Int4 GetRepeatIntervalFuzz (SeqAlignSortPtr s_repeat, SeqAlignSortPtr s_before, SeqAlignSortPtr s_after, Int4 row)
7451 {
7452   Int4 start_fuzz = 0, end_fuzz = 0;
7453 
7454   if (s_repeat == NULL) {
7455     return -1;
7456   }
7457 
7458   if (s_before != NULL) {
7459     if (row == 1) {
7460       start_fuzz = ABS (s_repeat->row1->start - s_before->row1->stop);
7461     } else {
7462       start_fuzz = ABS (s_repeat->row2->start - s_before->row2->stop);
7463     }
7464   }
7465   if (s_after != NULL) {
7466     if (row == 1) {
7467       end_fuzz = ABS (s_after->row1->start - s_repeat->row1->stop);
7468     } else {
7469       end_fuzz = ABS (s_after->row2->start - s_repeat->row2->stop);
7470     }
7471   }
7472 
7473   return start_fuzz + end_fuzz;
7474 }
7475 
7476 
StrandedSeqAlignSortRowCompare(SeqAlignSortPtr s1,SeqAlignSortPtr s2,Int4 row,Int4 fuzz)7477 static int StrandedSeqAlignSortRowCompare (SeqAlignSortPtr s1, SeqAlignSortPtr s2, Int4 row, Int4 fuzz)
7478 {
7479   SeqAlignRowPtr r1 = NULL, r2 = NULL;
7480   int rval = 0;
7481   Uint1 strand = Seq_strand_plus;
7482 
7483   if (s1 == NULL || s2 == NULL) {
7484     return 0;
7485   }
7486 
7487   r1 = SeqAlignRowFromSeqAlignSort (s1, row);
7488   r2 = SeqAlignRowFromSeqAlignSort (s2, row);
7489   strand = r1->strand;
7490 
7491   if (strand == Seq_strand_minus) {
7492     if (r1->start < r2->start - fuzz) {
7493       rval = 1;
7494     } else if (r1->start >r2->start + fuzz) {
7495       rval = -1;
7496     }
7497   } else {
7498     if (r1->start > r2->start + fuzz) {
7499       rval = 1;
7500     } else if (r1->stop < r2->stop - fuzz) {
7501       rval = -1;
7502     }
7503   }
7504 
7505   return rval;
7506 }
7507 
7508 
FindSeqAlignSortWithPoint(ValNodePtr list,Int4 point,Int4 row)7509 static Boolean FindSeqAlignSortWithPoint (ValNodePtr list, Int4 point, Int4 row)
7510 {
7511   ValNodePtr vnp;
7512   SeqAlignRowPtr r;
7513   SeqAlignSortPtr s;
7514   Boolean found = FALSE;
7515 
7516   for (vnp = list; vnp != NULL; vnp = vnp->next) {
7517     s = vnp->data.ptrvalue;
7518     r = SeqAlignRowFromSeqAlignSort (s, row);
7519     if (point >= r->start && point <= r->stop) {
7520       found = TRUE;
7521     }
7522   }
7523   return found;
7524 }
7525 
7526 
LengthOfLongestInterval(ValNodePtr list,Int4 row)7527 static Int4 LengthOfLongestInterval (ValNodePtr list, Int4 row)
7528 {
7529   Int4 max = 0, len;
7530   ValNodePtr vnp;
7531   SeqAlignRowPtr r;
7532   SeqAlignSortPtr s;
7533 
7534   for (vnp = list; vnp != NULL; vnp = vnp->next) {
7535     s = vnp->data.ptrvalue;
7536     r = SeqAlignRowFromSeqAlignSort (s, row);
7537     len = r->stop - r->start + 1;
7538     if (len > max) {
7539       max = len;
7540     }
7541   }
7542   return max;
7543 }
7544 
7545 
FindBestRepeat(ValNodePtr PNTR repeat_list,SeqAlignSortPtr s_before,SeqAlignSortPtr s_after,Int4 row,Int4 fuzz)7546 static ValNodePtr FindBestRepeat (ValNodePtr PNTR repeat_list, SeqAlignSortPtr s_before, SeqAlignSortPtr s_after, Int4 row, Int4 fuzz)
7547 {
7548   Int4       best_diff = -1, diff;
7549   ValNodePtr vnp, vnp_best = NULL, vnp_best_prev = NULL, vnp_prev = NULL;
7550   SeqAlignSortPtr s_this;
7551 
7552   if (repeat_list == NULL || *repeat_list == NULL) {
7553     return NULL;
7554   }
7555 
7556   for (vnp = *repeat_list; vnp != NULL; vnp = vnp->next) {
7557     s_this = vnp->data.ptrvalue;
7558 
7559     if (StrandedSeqAlignSortRowCompare (s_this, s_before, row, fuzz) < 0
7560       || StrandedSeqAlignSortRowCompare (s_this, s_after, row, fuzz) > 0) {
7561       /* skip - already out of order */
7562     } else {
7563       diff = GetRepeatIntervalFuzz (vnp->data.ptrvalue, s_before, s_after, row);
7564       if (diff > -1 && (best_diff < 0 || best_diff > diff)) {
7565         vnp_best = vnp;
7566         vnp_best_prev = vnp_prev;
7567         best_diff = diff;
7568       }
7569     }
7570     vnp_prev = vnp;
7571   }
7572 
7573   if (vnp_best != NULL) {
7574     if (vnp_best_prev == NULL) {
7575       *repeat_list = vnp_best->next;
7576     } else {
7577       vnp_best_prev->next = vnp_best->next;
7578     }
7579     vnp_best->next = NULL;
7580   }
7581 
7582   return vnp_best;
7583 }
7584 
7585 
RemoveRepeatsCoincidingWithBest(ValNodePtr PNTR repeat_list,ValNodePtr best,Int4 row,Int4 fuzz)7586 static void RemoveRepeatsCoincidingWithBest (ValNodePtr PNTR repeat_list, ValNodePtr best, Int4 row, Int4 fuzz)
7587 {
7588   ValNodePtr vnp;
7589   SeqAlignSortPtr s_best, s;
7590   SeqAlignRowPtr r_best, r2;
7591   Boolean        is_repeat;
7592   Int4           diff;
7593 
7594   if (repeat_list == NULL || *repeat_list == NULL || best == NULL) {
7595     return;
7596   }
7597 
7598   s_best = best->data.ptrvalue;
7599   r_best = SeqAlignRowFromSeqAlignSort (s_best, row);
7600 
7601   for (vnp = *repeat_list; vnp != NULL; vnp = vnp->next) {
7602     s = vnp->data.ptrvalue;
7603     r2 = SeqAlignRowFromSeqAlignSort (s, row);
7604 
7605     is_repeat = FALSE;
7606     if (r_best->start <= r2->start && r_best->stop >= r2->stop) {
7607       /* contained */
7608       is_repeat = TRUE;
7609     } else if (r2->start <= r_best->start && r2->stop >= r_best->stop) {
7610       /* contained */
7611       is_repeat = TRUE;
7612     } else if (r2->stop < r_best->stop || r2->stop - r_best->stop < fuzz) {
7613       is_repeat = TRUE;
7614     } else if ((diff = RowDiff (r_best, r2)) > -1 && diff < fuzz) {
7615       is_repeat = TRUE;
7616     }
7617 
7618     if (is_repeat) {
7619       vnp->choice = 1;
7620     }
7621   }
7622   SeqAlignSortListRemoveMarked (repeat_list);
7623 }
7624 
7625 
ExtractLongestSeqAlignRow(ValNodePtr PNTR list,Int4 row)7626 static ValNodePtr ExtractLongestSeqAlignRow (ValNodePtr PNTR list, Int4 row)
7627 {
7628   ValNodePtr vnp, vnp_prev = NULL, rval = NULL;
7629   Int4       longest = 0, len;
7630   Boolean    found = FALSE;
7631 
7632   if (list == NULL || *list == NULL) {
7633     return NULL;
7634   }
7635 
7636   for (vnp = *list; vnp != NULL; vnp = vnp->next) {
7637     len = SeqAlignRowLen (SeqAlignRowFromSeqAlignSort (vnp->data.ptrvalue, row));
7638     if (longest < len) {
7639       longest = len;
7640     }
7641   }
7642 
7643   for (vnp = *list; vnp != NULL && !found; vnp = vnp->next) {
7644     len = SeqAlignRowLen (SeqAlignRowFromSeqAlignSort (vnp->data.ptrvalue, row));
7645     if (len == longest) {
7646       if (vnp_prev == NULL) {
7647         *list = vnp->next;
7648       } else {
7649         vnp_prev->next = vnp->next;
7650       }
7651       vnp->next = NULL;
7652       rval = vnp;
7653       found = TRUE;
7654     }
7655     vnp_prev = vnp;
7656   }
7657   return rval;
7658 }
7659 
7660 
InsertBestRepeat(ValNodePtr repeat_list,ValNodePtr PNTR sorted_list,Int4 row,Int4 fuzz)7661 static void InsertBestRepeat (ValNodePtr repeat_list, ValNodePtr PNTR sorted_list, Int4 row, Int4 fuzz)
7662 {
7663   ValNodePtr vnp, vnp_prev = NULL, vnp_new;
7664   SeqAlignSortPtr s_repeat, s, s_before = NULL;
7665   Boolean         found = TRUE;
7666   SeqAlignRowPtr  r1, r2;
7667   Int4 other_row;
7668 
7669   if (repeat_list == NULL || sorted_list == NULL) {
7670     return;
7671   }
7672 
7673   if (row == 1) {
7674     other_row = 2;
7675   } else {
7676     other_row = 1;
7677   }
7678   if (sorted_list == NULL || *sorted_list == NULL) {
7679     /* keep longest, mark others for removal */
7680     vnp = ExtractLongestSeqAlignRow (&repeat_list, row);
7681     ValNodeLink (sorted_list,vnp);
7682     repeat_list = SeqAlignSortListFree (repeat_list);
7683   } else {
7684     s_repeat = repeat_list->data.ptrvalue;
7685     found = FALSE;
7686     vnp = *sorted_list;
7687 
7688     /* find first entry that is after this repeat, and insert before that */
7689     while (vnp != NULL && !found) {
7690       if (SeqAlignSortConflict (s_repeat, vnp->data.ptrvalue, fuzz)) {
7691         found = TRUE;
7692         break;
7693       }
7694 
7695       s = vnp->data.ptrvalue;
7696       r1 = SeqAlignRowFromSeqAlignSort (s, row);
7697       r2 = SeqAlignRowFromSeqAlignSort (s_repeat, row);
7698 
7699       if (r1->start == r2->start && r1->stop == r2->stop) {
7700         /* this is a duplicate.  throw it away. */
7701         found = TRUE;
7702         break;
7703       }
7704 
7705       if (r1->start > r2->start || r2->start - r1->start < fuzz) {
7706         while (repeat_list != NULL) {
7707           /* extract best repeat */
7708           vnp_new = FindBestRepeat (&repeat_list, s_before, vnp->data.ptrvalue, other_row, fuzz);
7709           if (vnp_new == NULL) {
7710             repeat_list = SeqAlignSortListFree (repeat_list);
7711           } else {
7712             RemoveRepeatsCoincidingWithBest (&repeat_list, vnp_new, row, fuzz);
7713             vnp_new->next = vnp;
7714             if (vnp_prev == NULL) {
7715               *sorted_list = vnp_new;
7716             } else {
7717               vnp_prev->next = vnp_new;
7718             }
7719             vnp_prev = vnp_new;
7720             s_before = vnp_new->data.ptrvalue;
7721           }
7722         }
7723         found = TRUE;
7724       }
7725       if (!found) {
7726         s_before = vnp->data.ptrvalue;
7727         vnp_prev = vnp;
7728         vnp = vnp->next;
7729       }
7730     }
7731     if (!found) {
7732       while (repeat_list != NULL) {
7733         /* extract best repeat */
7734         vnp_new = FindBestRepeat (&repeat_list, s_before, NULL, other_row, fuzz);
7735         if (vnp_new == NULL) {
7736           repeat_list = SeqAlignSortListFree (repeat_list);
7737         } else {
7738           RemoveRepeatsCoincidingWithBest (&repeat_list, vnp_new, row, fuzz);
7739           vnp_new->next = NULL;
7740           if (vnp_prev == NULL) {
7741             *sorted_list = vnp_new;
7742           } else {
7743             vnp_prev->next = vnp_new;
7744           }
7745           vnp_prev = vnp_new;
7746           s_before = vnp_new->data.ptrvalue;
7747         }
7748       }
7749     }
7750   }
7751 
7752   SeqAlignSortListRemoveMarked (&repeat_list);
7753   repeat_list = ValNodeFree (repeat_list);
7754 }
7755 
7756 
FindLongestRepeatInterval(ValNodePtr repeat_list)7757 static Int4 FindLongestRepeatInterval (ValNodePtr repeat_list)
7758 {
7759   Int4 len, max = 0;
7760   ValNodePtr vnp_r, vnp;
7761   SeqAlignSortPtr s;
7762 
7763   for (vnp_r = repeat_list; vnp_r != NULL; vnp_r = vnp_r->next) {
7764     for (vnp = vnp_r->data.ptrvalue; vnp != NULL; vnp = vnp->next) {
7765       s = vnp->data.ptrvalue;
7766       if (s != NULL && s->row1 != NULL) {
7767         len = SeqAlignRowLen (s->row1);
7768         if (len > max) {
7769           max = len;
7770         }
7771       }
7772     }
7773   }
7774   return max;
7775 }
7776 
7777 
7778 /* note - we want to sort from highest to lowest */
SortVnpByRepeatList(VoidPtr ptr1,VoidPtr ptr2)7779 static int LIBCALLBACK SortVnpByRepeatList (VoidPtr ptr1, VoidPtr ptr2)
7780 
7781 {
7782   ValNodePtr  vnp1;
7783   ValNodePtr  vnp2;
7784   Int4        len1, len2;
7785   int         rval = 0;
7786 
7787   if (ptr1 != NULL && ptr2 != NULL) {
7788     vnp1 = *((ValNodePtr PNTR) ptr1);
7789     vnp2 = *((ValNodePtr PNTR) ptr2);
7790     if (vnp1 != NULL && vnp2 != NULL) {
7791       len1 = SeqAlignSortListLongestInterval (vnp1->data.ptrvalue);
7792       len2 = SeqAlignSortListLongestInterval (vnp2->data.ptrvalue);
7793       if (len1 < len2) {
7794         rval = 1;
7795       } else if (len2 < len1) {
7796         rval = -1;
7797       }
7798     }
7799   }
7800   return rval;
7801 }
7802 
7803 
FindCompleteCoverageAlign(ValNodePtr PNTR list,Int4 row)7804 static void FindCompleteCoverageAlign (ValNodePtr PNTR list, Int4 row)
7805 {
7806   SeqAlignSortPtr s;
7807   ValNodePtr      vnp, prev = NULL;
7808   Boolean         found = FALSE;
7809   SeqIdPtr        sip;
7810   BioseqPtr       bsp;
7811   Int4            length;
7812 
7813   if (list == NULL || *list == NULL) {
7814     return;
7815   }
7816 
7817   vnp = *list;
7818   s = (SeqAlignSortPtr) vnp->data.ptrvalue;
7819   sip = AlnMgr2GetNthSeqIdPtr (s->salp, row);
7820   bsp = BioseqLockById (sip);
7821   if (bsp == NULL) {
7822     return;
7823   }
7824 
7825   length = bsp->length;
7826   BioseqUnlock(bsp);
7827 
7828   while (vnp != NULL && !found) {
7829     s = (SeqAlignSortPtr) vnp->data.ptrvalue;
7830     if (s != NULL) {
7831       if (row == 1) {
7832         if (SeqAlignRowLen (s->row1) == length) {
7833           found = TRUE;
7834         }
7835       } else {
7836         if (SeqAlignRowLen (s->row2) == length) {
7837           found = TRUE;
7838         }
7839       }
7840     }
7841     if (!found) {
7842       prev = vnp;
7843       vnp = vnp->next;
7844     }
7845   }
7846 
7847   if (found) {
7848     vnp->next = SeqAlignSortListFree (vnp->next);
7849     if (prev != NULL) {
7850       prev->next = NULL;
7851       *list = SeqAlignSortListFree (*list);
7852       *list = vnp;
7853     }
7854   }
7855 }
7856 
7857 
SelectBestRepeatsFromList(SeqAlignPtr PNTR salp)7858 static void SelectBestRepeatsFromList (SeqAlignPtr PNTR salp)
7859 {
7860   ValNodePtr list, vnp;
7861   ValNodePtr row1_repeats, row2_repeats;
7862   Uint1 strand1, strand2;
7863   SeqAlignPtr    tmp_salp;
7864   Int4           fuzz = 15;
7865   Int4           missing = 600;
7866   Int4           len1, len2;
7867   Int4           best_len;
7868 
7869   if (salp == NULL || *salp == NULL || (*salp)->next == NULL) {
7870     return;
7871   }
7872 
7873   list = SeqAlignSortListNew (*salp);
7874 
7875   FindSeqAlignSortWithPoint (list, missing, 1);
7876 
7877   FindCompleteCoverageAlign (&list, 2);
7878   FindCompleteCoverageAlign (&list, 1);
7879 
7880   /* remove conflicting strands for row 1 */
7881   strand1 = SeqAlignSortListRemoveConflictingStrands (&list, 1);
7882   best_len = LengthOfLongestInterval (list, 1);
7883 
7884   /* remove conflicting strands for row 1 */
7885   strand2 = SeqAlignSortListRemoveConflictingStrands (&list, 2);
7886   best_len = LengthOfLongestInterval (list, 1);
7887 
7888   FindSeqAlignSortWithPoint (list, missing, 1);
7889 
7890   if (list != NULL && list->next != NULL) {
7891     /* remove alignments that are completely contained in another alignment */
7892     MarkSubAlignments (&list);
7893     SeqAlignSortListRemoveMarked (&list);
7894   }
7895 
7896   if (list != NULL && list->next != NULL) {
7897     row1_repeats = SeqAlignSortListMarkRepeats (&list, 1, fuzz);
7898     row1_repeats = ValNodeSort (row1_repeats, SortVnpByRepeatList);
7899     row2_repeats = SeqAlignSortListMarkRepeats (&list, 2, fuzz);
7900     row2_repeats = ValNodeSort (row2_repeats, SortVnpByRepeatList);
7901     vnp = ValNodeExtractList (&list, 1);
7902     best_len = LengthOfLongestInterval (vnp, 1);
7903     vnp = SeqAlignSortListFree (vnp);
7904     best_len = LengthOfLongestInterval (list, 1);
7905     vnp = ValNodeExtractList (&list, 2);
7906     best_len = LengthOfLongestInterval (vnp, 1);
7907     vnp = SeqAlignSortListFree (vnp);
7908     best_len = LengthOfLongestInterval (list, 1);
7909 
7910     FindSeqAlignSortWithPoint (list, missing, 1);
7911 
7912     /* remove scaffold intervals that are out of order */
7913     list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
7914     SeqAlignSortListRemoveIntervalsOutOfOrder (&list, 1, fuzz);
7915     best_len = LengthOfLongestInterval (list, 1);
7916     list = ValNodeSort (list, SortVnpBySeqAlignSortRow2);
7917     SeqAlignSortListRemoveIntervalsOutOfOrder (&list, 2, fuzz);
7918     best_len = LengthOfLongestInterval (list, 1);
7919 
7920     FindSeqAlignSortWithPoint (list, missing, 1);
7921 
7922     /* Remove overlaps.*/
7923     list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
7924     tmp_salp = SeqAlignFromSeqAlignSortList (list);
7925     list = SeqAlignSortListFree (list);
7926     ACT_RemoveInconsistentAlnsFromSet (tmp_salp, 1, 1);
7927     list = SeqAlignSortListNew (tmp_salp);
7928 
7929     FindSeqAlignSortWithPoint (list, missing, 1);
7930 
7931     len1 = FindLongestRepeatInterval (row1_repeats);
7932     len2 = FindLongestRepeatInterval (row2_repeats);
7933 
7934     if (len1 >= len2) {
7935       /* for each repeat on row 1, we want to pick the most consistent interval for row 2 */
7936       list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
7937       for (vnp = row1_repeats; vnp != NULL; vnp = vnp->next) {
7938         InsertBestRepeat (vnp->data.ptrvalue, &list, 1, fuzz);
7939       }
7940       row1_repeats = ValNodeFree (row1_repeats);
7941 
7942       /* for each repeat on row 2, we want to pick the most consistent interval for row 1 */
7943       list = ValNodeSort (list, SortVnpBySeqAlignSortRow2);
7944       for (vnp = row2_repeats; vnp != NULL; vnp = vnp->next) {
7945         InsertBestRepeat (vnp->data.ptrvalue, &list, 2, fuzz);
7946       }
7947       row2_repeats = ValNodeFree (row2_repeats);
7948     } else {
7949       /* for each repeat on row 2, we want to pick the most consistent interval for row 1 */
7950       list = ValNodeSort (list, SortVnpBySeqAlignSortRow2);
7951       for (vnp = row2_repeats; vnp != NULL; vnp = vnp->next) {
7952         InsertBestRepeat (vnp->data.ptrvalue, &list, 2, fuzz);
7953       }
7954       row2_repeats = ValNodeFree (row2_repeats);
7955 
7956       /* for each repeat on row 1, we want to pick the most consistent interval for row 2 */
7957       list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
7958       for (vnp = row1_repeats; vnp != NULL; vnp = vnp->next) {
7959         InsertBestRepeat (vnp->data.ptrvalue, &list, 1, fuzz);
7960       }
7961       row1_repeats = ValNodeFree (row1_repeats);
7962     }
7963   }
7964 
7965   list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
7966   *salp = SeqAlignFromSeqAlignSortList (list);
7967 
7968   list = SeqAlignSortListFree (list);
7969 }
7970 
7971 
amconssetfree(AMConsSetPtr acp)7972 static void amconssetfree(AMConsSetPtr acp)
7973 {
7974    AMConsSetPtr  acp_next;
7975 
7976    while (acp != NULL)
7977    {
7978       acp_next = acp->next;
7979       MemFree(acp->starts);
7980       MemFree(acp->stops);
7981       MemFree(acp->strands);
7982       MemFree(acp);
7983       acp = acp_next;
7984    }
7985 }
7986 
CKA_SortForConsistent(VoidPtr ptr1,VoidPtr ptr2)7987 static int LIBCALLBACK CKA_SortForConsistent(VoidPtr ptr1, VoidPtr ptr2)
7988 {
7989    AMConsSetPtr  acp1;
7990    AMConsSetPtr  acp2;
7991    FloatHi       bitscore;
7992    FloatHi       evalue;
7993    Int4          number;
7994    SAIndex2Ptr   saip1;
7995    SAIndex2Ptr   saip2;
7996 
7997    acp1 = *((AMConsSetPtr PNTR)ptr1);
7998    acp2 = *((AMConsSetPtr PNTR)ptr2);
7999    saip1 = (SAIndex2Ptr)(acp1->sap->saip);
8000    saip2 = (SAIndex2Ptr)(acp2->sap->saip);
8001    if (saip1->score == 0)
8002       GetScoreAndEvalue(acp1->sap, &saip1->score, &bitscore, &evalue, &number);
8003    if (saip2->score == 0)
8004       GetScoreAndEvalue(acp2->sap, &saip2->score, &bitscore, &evalue, &number);
8005    if (saip1->score > saip2->score)
8006       return -1;
8007    else if (saip1->score < saip2->score)
8008       return 1;
8009    else
8010       return 0;
8011 }
8012 
8013 
CKA_RemoveInconsistentAlnsFromSet(SeqAlignPtr sap_head,Int4 fuzz,CKABlastOptsPtr opts)8014 static void CKA_RemoveInconsistentAlnsFromSet(SeqAlignPtr sap_head, Int4 fuzz, CKABlastOptsPtr opts)
8015 {
8016    AMConsSetPtr  acp;
8017    AMConsSetPtr  acp_head;
8018    AMConsSetPtr  acp_prev;
8019    AMConsSetPtr  PNTR acparray;
8020    DenseSegPtr   dsp;
8021    Int4          i;
8022    Int4          j;
8023    Int4          k;
8024    Int4          lfuzz;
8025    SeqAlignPtr   newsap;
8026    Int4          numrows;
8027    Int4          numsaps;
8028    Int4          orientation;
8029    Int4          row;
8030    SAIndex2Ptr   saip;
8031    SeqAlignPtr   salp_head;
8032    SeqAlignPtr   salp_prev;
8033    SeqAlignPtr   sap;
8034    SeqAlignPtr   sapnext;
8035    Int4          score;
8036    SeqIdPtr      sip;
8037    SeqIdPtr      sip_head;
8038    Uint1         strand;
8039 
8040    if (sap_head == NULL || opts == NULL) {
8041      return;
8042    }
8043    lfuzz = fuzz;
8044    if (fuzz < 0)
8045       fuzz = 1;
8046    sap = (SeqAlignPtr)(sap_head->segs);
8047    if (sap->next == NULL)
8048       return;
8049    dsp = (DenseSegPtr)(sap->segs);
8050    sip_head = dsp->ids;
8051    numrows = AlnMgr2GetNumRows(sap);
8052    acp_head = NULL;
8053    strand = AlnMgr2GetNthStrand(sap, 1);
8054    numsaps = 0;
8055    while (sap != NULL)
8056    {
8057       if (AlnMgr2GetNumRows(sap) != numrows)
8058       {
8059          amconssetfree(acp_head);
8060          return;
8061       }
8062       numsaps++;
8063       acp = (AMConsSetPtr)MemNew(sizeof(AMConsSet));
8064       acp->starts = (Int4Ptr)MemNew(numrows*sizeof(Int4));
8065       acp->stops = (Int4Ptr)MemNew(numrows*sizeof(Int4));
8066       acp->strands = (Uint1Ptr)MemNew(numrows*sizeof(Uint1));
8067       acp->which = (Int4Ptr)MemNew(numrows*sizeof(Int4));
8068       acp->sap = sap;
8069       if (acp_head != NULL)
8070       {
8071          acp_prev->next = acp;
8072          acp_prev = acp;
8073       } else
8074          acp_head = acp_prev = acp;
8075       sip = sip_head;
8076       row = AlnMgr2GetFirstNForSip(sap, sip);
8077       if (row <= 0)
8078       {
8079          amconssetfree(acp_head);
8080          return;
8081       }
8082       if (acp->strands[row] != strand)
8083       {
8084          sapnext = acp->sap->next;
8085          acp->sap->next = NULL;
8086          score = ((SAIndex2Ptr)(acp->sap->saip))->score;
8087          SeqAlignListReverseStrand(acp->sap);
8088          AMAlignIndexFreeEitherIndex(acp->sap);
8089          AlnMgr2IndexSingleChildSeqAlign(acp->sap);
8090          saip = (SAIndex2Ptr)(acp->sap->saip);
8091          saip->score = score;
8092          acp->strands[row] = strand;
8093          acp->sap->next = sapnext;
8094       }
8095       for (i=0; i<numrows; i++)
8096       {
8097          acp->which[i] = row;
8098          AlnMgr2GetNthSeqRangeInSA(sap, i+1, &acp->starts[i], &acp->stops[i]);
8099          acp->strands[i] = AlnMgr2GetNthStrand(sap, i+1);
8100       }
8101       sap = sap->next;
8102    }
8103    acparray = (AMConsSetPtr PNTR)MemNew(numsaps*sizeof(AMConsSetPtr));
8104    acp = acp_head;
8105    i = 0;
8106    while (acp != NULL)
8107    {
8108       acparray[i] = acp;
8109       acp = acp->next;
8110       i++;
8111    }
8112    HeapSort(acparray, numsaps, sizeof(AMConsSetPtr), CKA_SortForConsistent);
8113    /* orientation -1 means that ith is before jth in ALL rows, 1 means ith is after jth in ALL rows */
8114    for (i=0; i<numsaps; i++)
8115    {
8116       if (acparray[i]->used != -1)
8117       {
8118          for (j=i+1; j<numsaps; j++)
8119          {
8120             orientation = 0;
8121             for (k=0; acparray[j]->used != -1 && k<numrows; k++)
8122             {
8123                if (acparray[i]->starts[k] - fuzz < acparray[j]->starts[k])
8124                {
8125                   if (acparray[i]->stops[k] - fuzz < acparray[j]->starts[k])
8126                   {
8127                      if (orientation == 0)
8128                      {
8129                         if (acparray[i]->strands[k] == Seq_strand_minus)
8130                            orientation = 1;
8131                         else
8132                            orientation = -1;
8133                      }
8134                   } else
8135                   {
8136                      if (lfuzz >= 0) /* just mark it for deletion */
8137                         acparray[j]->used = -1;
8138                      else /* truncate it */
8139                      {
8140                         if (acparray[j]->stops[k] >
8141                             acparray[i]->stops[k] + opts->wordsize)
8142                         {
8143                            newsap = AlnMgr2GetSubAlign(acparray[j]->sap, acparray[i]->stops[k]+1,
8144  acparray[j]->stops[k], k+1, TRUE);
8145                            AlnMgr2IndexSingleChildSeqAlign(newsap);
8146                            SeqAlignFree(acparray[j]->sap);
8147                            acparray[j]->sap = newsap;
8148                            acparray[j]->starts[k] = acparray[i]->stops[k]+1;
8149                         } else
8150                            acparray[j]->used = -1;
8151                      }
8152                   }
8153                } else if (acparray[i]->starts[k] - fuzz > acparray[j]->starts[k])
8154                {
8155                  if (acparray[i]->starts[k] + fuzz > acparray[j]->stops[k])
8156                   {
8157                      if (orientation == 0)
8158                      {
8159                         if (acparray[i]->strands[k] == Seq_strand_minus)
8160                            orientation = -1;
8161                         else
8162                            orientation = 1;
8163                      }
8164                   } else
8165                   {
8166                      if (lfuzz >= 0) /* mark for deletion */
8167                         acparray[j]->used = -1;
8168                      else /* truncate */
8169                      {
8170                         if (acparray[j]->starts[k] <
8171                             acparray[i]->starts[k] - opts->wordsize)
8172                         {
8173                            newsap = AlnMgr2GetSubAlign(acparray[j]->sap, acparray[j]->starts[k], acparray[i]->starts[k]-1, k+1, TRUE);
8174                            AlnMgr2IndexSingleChildSeqAlign(newsap);
8175                            SeqAlignFree(acparray[j]->sap);
8176                            acparray[j]->sap = newsap;
8177                            acparray[j]->stops[k] = acparray[i]->starts[k]-1;
8178                         } else
8179                            acparray[j]->used = -1;
8180                      }
8181                   }
8182                } else
8183                   acparray[j]->used = -1;
8184             }
8185          }
8186       }
8187    }
8188    /* now free all the unused ones, stick the rest back together, reindex, and return */
8189    salp_head = salp_prev = NULL;
8190    for (i=0; i<numsaps; i++)
8191    {
8192       if (acparray[i]->used == -1)
8193       {
8194          SeqAlignFree(acparray[i]->sap);
8195          acparray[i]->sap = NULL;
8196       } else
8197       {
8198          if (salp_head != NULL)
8199          {
8200             salp_prev->next = acparray[i]->sap;
8201             salp_prev = acparray[i]->sap;
8202             salp_prev->next = NULL;
8203          } else
8204          {
8205             salp_head = salp_prev = acparray[i]->sap;
8206             salp_prev->next = NULL;
8207          }
8208       }
8209    }
8210    amconssetfree(acp_head);
8211    MemFree(acparray);
8212    sap_head->segs = (Pointer)(salp_head);
8213    AMAlignIndex2Free2(sap_head->saip);
8214    AlnMgr2IndexLite(sap_head);
8215 }
8216 
8217 
ReadFromTraceDb(CharPtr number)8218 static BioseqPtr ReadFromTraceDb (CharPtr number)
8219 
8220 {
8221   BioseqPtr    bsp = NULL;
8222   CONN         conn;
8223   time_t       currtime, starttime;
8224   FILE         *fp;
8225   time_t       max = 0;
8226   size_t       n_written;
8227   Char         path [PATH_MAX];
8228   Char         query [64];
8229   SeqEntryPtr  sep = NULL;
8230   EIO_Status   status;
8231   STimeout     timeout;
8232   unsigned long int     val;
8233 
8234   if (StringHasNoText (number)) return NULL;
8235   if (sscanf (number, "%lu", &val) != 1) return NULL;
8236   sprintf (query, "cmd=raw&query=retrieve+fasta+%lu", (long) val);
8237   conn = QUERY_OpenUrlQuery ("www.ncbi.nlm.nih.gov", 0, "/Traces/trace.cgi",
8238                              query, "Sequin", 30, eMIME_T_NcbiData,
8239                              eMIME_Fasta, eENCOD_None, 0);
8240   if (conn == NULL) return NULL;
8241   status = CONN_Write (conn, (const void *) query, StringLen (query),
8242                        &n_written, eIO_WritePersist);
8243   if (status != eIO_Success) return NULL;
8244   QUERY_SendQuery (conn);
8245 
8246 #ifdef OS_MAC
8247   timeout.sec = 0;
8248   timeout.usec = 0;
8249 #else
8250   timeout.sec = 100;
8251   timeout.usec = 0;
8252 #endif
8253 
8254   starttime = GetSecs ();
8255   while ((status = CONN_Wait (conn, eIO_Read, &timeout)) == eIO_Timeout && max < 300) {
8256     currtime = GetSecs ();
8257     max = currtime - starttime;
8258   }
8259 
8260   if (status == eIO_Success) {
8261     TmpNam (path);
8262     fp = FileOpen (path, "w");
8263     QUERY_CopyResultsToFile (conn, fp);
8264     FileClose (fp);
8265     /*
8266     LaunchGeneralTextViewer (path, "QueueFastaQueryToURL results");
8267     */
8268     fp = FileOpen (path, "r");
8269     sep = FastaToSeqEntry (fp, TRUE);
8270     FileClose (fp);
8271     FileRemove (path);
8272     if (sep != NULL) {
8273       bsp = FindNucBioseq (sep);
8274     }
8275   }
8276   CONN_Close (conn);
8277 
8278   return bsp;
8279 }
8280 
8281 
IsHUPIDAccession(BioseqPtr bsp)8282 static Boolean IsHUPIDAccession (BioseqPtr bsp)
8283 {
8284   Int4 j, num;
8285   ObjMgrDataPtr omdp;
8286   OMUserDataPtr omudp;
8287   ObjMgrProcPtr ompp = NULL;
8288   ObjMgrPtr omp;
8289   ObjMgrDataPtr PNTR omdpp;
8290   Boolean           rval = FALSE;
8291 
8292   ompp = NULL;
8293   omp = ObjMgrReadLock();
8294 
8295   omdpp = omp->datalist;
8296   if (omdpp != NULL) {
8297     num = omp->currobj;
8298     for (j = 0; j < num && ompp == NULL; j++) {
8299       if (omdpp[j] != NULL && omdpp[j]->datatype == OBJ_BIOSEQ
8300           && omdpp[j]->dataptr == bsp) {
8301 
8302         omdp = ObjMgrFindTop (omp, omdpp[j]);
8303         if (omdp != NULL) {
8304           for (omudp = omdp->userdata; omudp != NULL && ompp == NULL; omudp = omudp->next)
8305           {
8306             if (omudp->proctype == OMPROC_FETCH)  /* caching function */
8307             {
8308               ompp = ObjMgrProcFind(omp, omudp->procid, NULL, 0);
8309             }
8310           }
8311         }
8312       }
8313     }
8314   }
8315 
8316   if (ompp != NULL && StringCmp (ompp->procname, "HUPBioseqFetch") == 0)
8317   {
8318     rval = TRUE;
8319   }
8320 
8321   ObjMgrUnlock();
8322   return rval;
8323 }
8324 
8325 
ExamineAln(SeqAlignPtr sap)8326 static void ExamineAln (SeqAlignPtr sap)
8327 {
8328   Int4 len, num_aln = 0;
8329 
8330   while (sap != NULL) {
8331     len = SeqAlignLength (sap);
8332     num_aln++;
8333     sap = sap->next;
8334   }
8335 
8336 }
8337 
8338 
RemoveShortAlignments(SeqAlignPtr PNTR p_salp,Int4 min_len)8339 static void RemoveShortAlignments (SeqAlignPtr PNTR p_salp, Int4 min_len)
8340 {
8341   SeqAlignPtr this_aln, prev = NULL, next_aln;
8342   Int4        len;
8343 
8344   if (p_salp == NULL || (this_aln = *p_salp) == NULL) {
8345     return;
8346   }
8347 
8348   len = SeqAlignLength (this_aln);
8349   if (len < min_len) {
8350     /* free after the first */
8351     next_aln = this_aln->next;
8352     this_aln->next = NULL;
8353     this_aln = next_aln;
8354     while (this_aln != NULL) {
8355       next_aln = this_aln->next;
8356       this_aln = SeqAlignFree (this_aln);
8357       this_aln = next_aln;
8358     }
8359   } else {
8360     /* free only if shorter than min_len */
8361     while (this_aln != NULL) {
8362       next_aln = this_aln->next;
8363       if ((len = SeqAlignLength (this_aln)) < min_len) {
8364         if (prev == NULL) {
8365           *p_salp = next_aln;
8366         } else {
8367           prev->next = next_aln;
8368         }
8369         this_aln->next = NULL;
8370         this_aln = SeqAlignFree (this_aln);
8371       } else {
8372         prev = this_aln;
8373       }
8374       this_aln = next_aln;
8375     }
8376   }
8377 }
8378 
8379 
CKA_MakeAlign(BioseqPtr bsp,CKA_AccPtr acc_head,LogInfoPtr lip,CKABlastOptsPtr opts)8380 static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr lip, CKABlastOptsPtr opts)
8381 {
8382    CKA_AccPtr           acc;
8383    CKA_AccPtr           acc_new;
8384    CKA_AccPtr           acc_new_head_head;
8385    CKA_AccPtr           acc_new_head;
8386    CKA_AccPtr           acc_new_prev;
8387    SeqAlignPtr          allsap;
8388    SeqAlignPtr          allsap_prev;
8389    AMAlignIndex2Ptr     amaip;
8390    BioseqPtr            bsp_tmp = NULL;
8391    Int4                 i;
8392    BLAST_SummaryOptions *options = NULL;
8393    SBlastSeqalignArray * seqalign_arr=NULL;
8394    SeqAlignPtr          sap_new;
8395    SeqAlignPtr          sap_tmp;
8396    SeqAlignPtr          sap_tmp_next;
8397    SeqIdPtr             sip;
8398    Uint1                strand;
8399    Boolean              need_to_unlock = FALSE;
8400 
8401    if (bsp == NULL || acc_head == NULL || opts == NULL)
8402       return NULL;
8403    acc = acc_head;
8404    allsap = NULL;
8405    allsap_prev = NULL;
8406    acc_new_head_head = acc_new_prev = NULL;
8407    BLAST_SummaryOptionsInit(&options);
8408    options->program = eBlastn;
8409    options->use_megablast = TRUE;
8410    options->word_size = opts->wordsize;
8411    options->cutoff_evalue = opts->expect_value;
8412    options->hint = eBlastHint_None;
8413    options->gap_open = -1;
8414    options->gap_extend = -1;
8415    options->filter_string = StringSave ("F");
8416    while (acc != NULL)
8417    {
8418 
8419       if (need_to_unlock)
8420       {
8421         BioseqUnlock (bsp_tmp);
8422         need_to_unlock = FALSE;
8423       }
8424 
8425       bsp_tmp = NULL;
8426       if (StringNICmp (acc->accession, "ti", 2) == 0) {
8427         bsp_tmp = ReadFromTraceDb (acc->accession + 2);
8428       } else {
8429         sip = SeqIdFromAccessionDotVersion(acc->accession);
8430         bsp_tmp = BioseqLockById(sip);
8431         sip = SeqIdFree (sip);
8432         if (bsp_tmp != NULL) {
8433           need_to_unlock = TRUE;
8434           if (lip != NULL && lip->fp != NULL && IsHUPIDAccession (bsp_tmp)) {
8435             fprintf (lip->fp, "%s is unreleased accession in TPA Seq-Hist.\n", acc->accession);
8436             lip->data_in_log = TRUE;
8437           }
8438         }
8439       }
8440       if (bsp_tmp == NULL) {
8441         if (lip != NULL) {
8442           fprintf (lip->fp, "Unable to load %s", acc->accession);
8443           lip->data_in_log = TRUE;
8444         }
8445         acc = acc->next;
8446         continue;
8447       }
8448       if (bsp_tmp->id->next) {
8449         /* find the best accession */
8450         SeqIdPtr sip = SeqIdDup(SqnSeqIdFindBestAccession(bsp_tmp->id));
8451         bsp_tmp->id = SeqIdSetFree(bsp_tmp->id);
8452         bsp_tmp->id = sip;
8453       }
8454       if (!ISA_na(bsp_tmp->mol))
8455       {
8456          if (need_to_unlock)
8457          {
8458            BioseqUnlock(bsp_tmp);
8459            need_to_unlock = FALSE;
8460          }
8461          Message(MSG_ERROR, "%s is not a nucleotide bioseq.", acc->accession);
8462          break;
8463       }
8464       WatchCursor();
8465       if (acc->start_acc >= 0 && acc->stop_acc >= 0 &&
8466           acc->start_acc < bsp->length &&
8467           acc->start_acc < bsp->length) {
8468         SeqLocPtr slp1, slp2;
8469         if (acc->start_acc <= acc->stop_acc) {
8470           slp2 = SeqLocIntNew
8471             (acc->start_acc, acc->stop_acc, Seq_strand_plus, bsp->id);
8472         } else {
8473           slp2 = SeqLocIntNew
8474             (acc->stop_acc, acc->start_acc, Seq_strand_minus, bsp->id);
8475         }
8476         slp1 = SeqLocIntNew(0, bsp_tmp->length-1, Seq_strand_plus, bsp_tmp->id);
8477         acc->sap = NULL;
8478         seqalign_arr = NULL;
8479         BLAST_TwoSeqLocSets (options, slp1, slp2, NULL, &seqalign_arr, NULL, NULL, NULL);
8480         if (seqalign_arr != NULL)
8481         {
8482           acc->sap = seqalign_arr->array[0];
8483           seqalign_arr->array[0] = NULL;
8484           seqalign_arr = SBlastSeqalignArrayFree(seqalign_arr);
8485         }
8486         SeqLocFree(slp1);
8487         SeqLocFree(slp2);
8488       } else {
8489         acc->sap = NULL;
8490         BLAST_TwoSequencesSearch(options, bsp_tmp, bsp, &(acc->sap));
8491       }
8492       ArrowCursor();
8493       acc->start_acc = acc->stop_acc = 0; /* reset, for later usage */
8494       if (acc->sap != NULL)
8495          SPI_flip_sa_list(acc->sap);
8496       acc_new_head = NULL;
8497       if (StringStr (acc->accession, "1742833740") != NULL) {
8498         acc_new_head = NULL;
8499       }
8500       if (acc->sap != NULL && acc->sap->next != NULL && opts->allow_repeats) {
8501         RemoveShortAlignments (&(acc->sap), .8 * bsp_tmp->length);
8502       }
8503       if (acc->sap != NULL && acc->sap->next != NULL)
8504       {
8505          if (!opts->allow_repeats) {
8506            SelectBestRepeatsFromList (&(acc->sap));
8507          }
8508          AlnMgr2IndexLite(acc->sap);
8509          if (!opts->allow_repeats) {
8510            CKA_RemoveInconsistentAlnsFromSet(acc->sap, -1, opts);
8511          }
8512 
8513          sap_tmp = acc->sap;
8514          acc->sap = (SeqAlignPtr)(acc->sap->segs);
8515          sap_tmp->segs = NULL;
8516          SeqAlignFree(sap_tmp);
8517          sap_tmp = acc->sap->next;
8518          acc->sap->next = NULL;
8519          while (sap_tmp != NULL)
8520          {
8521             AlnMgr2IndexSingleChildSeqAlign(sap_tmp);
8522             sap_tmp_next = sap_tmp->next;
8523             sap_tmp->next = NULL;
8524             acc_new = (CKA_AccPtr)MemNew(sizeof(CKA_Acc));
8525             acc_new->accession = StringSave(acc->accession);
8526             acc_new->sip_whole = SeqIdDup(acc->sip_whole);
8527             acc_new->sap = sap_tmp;
8528             sap_tmp = sap_tmp_next;
8529             if (!acc_new_head) {
8530               acc_new_head = acc_new;
8531             }
8532             if (acc_new_prev) {
8533               acc_new_prev->next = acc_new;
8534             }
8535             acc_new_prev = acc_new;
8536          }
8537       } else if (acc->sap != NULL)
8538          AlnMgr2IndexSingleChildSeqAlign(acc->sap);
8539       if (acc->sap != NULL)
8540       {
8541          strand = AlnMgr2GetNthStrand(acc->sap, 1);
8542          if (strand == Seq_strand_minus)
8543          {
8544             SeqAlignListReverseStrand(acc->sap);
8545             SAIndex2Free2(acc->sap->saip);
8546             acc->sap->saip = NULL;
8547          }
8548       }
8549       if (allsap != NULL && acc->sap != NULL)
8550       {
8551          allsap_prev->next = acc->sap;
8552          allsap_prev = allsap_prev->next;;
8553       } else if (acc->sap != NULL)
8554          allsap_prev = allsap = (acc->sap);
8555       acc_new = acc_new_head;
8556       while (acc_new != NULL)
8557       {
8558          strand = AlnMgr2GetNthStrand(acc_new->sap, 1);
8559          if (strand == Seq_strand_minus)
8560          {
8561             SeqAlignListReverseStrand(acc_new->sap);
8562             SAIndex2Free2(acc_new->sap->saip);
8563             acc_new->sap->saip = NULL;
8564          }
8565          if (allsap != NULL)
8566          {
8567             allsap_prev->next = acc_new->sap;
8568             allsap_prev = allsap_prev->next;;
8569          } else
8570             allsap_prev = allsap = acc_new->sap;
8571          acc_new = acc_new->next;
8572       }
8573       if (allsap_prev != NULL)
8574       {
8575          while (allsap_prev->next != NULL)
8576          {
8577             allsap_prev = allsap_prev->next;
8578          }
8579       }
8580       if (need_to_unlock)
8581       {
8582          BioseqUnlock(bsp_tmp);
8583          need_to_unlock = FALSE;
8584       }
8585       acc = acc->next;
8586       if (!acc_new_head_head) {
8587         acc_new_head_head = acc_new_head;
8588       }
8589    }
8590 
8591    BLAST_SummaryOptionsFree(options);
8592    if (need_to_unlock)
8593    {
8594       BioseqUnlock (bsp_tmp);
8595       need_to_unlock = FALSE;
8596    }
8597 
8598    acc = acc_head;
8599    while (acc->next != NULL)
8600    {
8601       acc = acc->next;
8602    }
8603    acc->next = acc_new_head_head;
8604    if (allsap == NULL)
8605       return NULL;
8606    sap_new = SeqAlignNew();
8607    sap_new->segtype = SAS_DISC;
8608    sap_new->segs = (Pointer)(allsap);
8609    allsap = sap_new;
8610    AlnMgr2IndexLite(allsap);
8611    AlnMgr2SortAlnSetByNthRowPos(allsap, 1);
8612    amaip = (AMAlignIndex2Ptr)(allsap->saip);
8613    for (i=0; i<amaip->numsaps-1; i++)
8614    {
8615       amaip->saps[i]->next = amaip->saps[i+1];
8616    }
8617    amaip->saps[amaip->numsaps-1]->next = NULL;
8618    allsap->segs = (Pointer)(amaip->saps[0]);
8619    return allsap;
8620 }
8621 
8622 
SetDefaultCKAOptions(CKABlastOptsPtr opts)8623 static void SetDefaultCKAOptions (CKABlastOptsPtr opts)
8624 {
8625   if (opts == NULL) {
8626     return;
8627   }
8628   opts->allow_repeats = FALSE;
8629   opts->expect_value = 0.000001;
8630   opts->wordsize = 28;
8631 }
8632 
8633 
CreateSeqHistTPA(IteM i)8634 NLM_EXTERN void CreateSeqHistTPA (IteM i)
8635 {
8636   BaseFormPtr        bfp;
8637   SeqEntryPtr        sep;
8638   CKABlastOptsData   opts;
8639 
8640 #ifdef WIN_MAC
8641   bfp = currentFormDataPtr;
8642 #else
8643   bfp = GetObjectExtra (i);
8644 #endif
8645   if (bfp == NULL) return;
8646   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8647   if (sep == NULL) return;
8648 
8649   SetDefaultCKAOptions (&opts);
8650 
8651   CKA_RunChecker(sep, &opts);
8652 
8653   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8654   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8655 }
8656 
8657 
8658 typedef struct tpahistform {
8659   FORM_MESSAGE_BLOCK
8660   TexT blast_wordsize_text;
8661   TexT blast_expect_value_text;
8662   ButtoN blast_allow_repeats_button;
8663 } TPAHistFormData, PNTR TPAHistFormPtr;
8664 
DoAcceptBlastOptions(ButtoN b)8665 static void DoAcceptBlastOptions (ButtoN b)
8666 
8667 {
8668    TPAHistFormPtr frm;
8669    SeqEntryPtr    sep;
8670    CharPtr tmp;
8671    long    val1;
8672    FloatHi val2;
8673    CKABlastOptsData opts;
8674 
8675    frm = (TPAHistFormPtr) GetObjectExtra (b);
8676    if (frm == NULL) {
8677      return;
8678    }
8679    sep = GetTopSeqEntryForEntityID (frm->input_entityID);
8680    if (sep == NULL) return;
8681 
8682    SetDefaultCKAOptions (&opts);
8683 
8684    tmp = SaveStringFromText (frm->blast_wordsize_text);
8685    if (sscanf (tmp, "%ld", &val1) == 1) {
8686      opts.wordsize = (Int4) val1;
8687    }
8688    tmp = MemFree (tmp);
8689    tmp = SaveStringFromText (frm->blast_expect_value_text);
8690    if (sscanf (tmp, "%lf", &val2) == 1) {
8691      opts.expect_value = (FloatHi) val2;
8692    }
8693    tmp = MemFree (tmp);
8694    opts.allow_repeats =
8695      (Boolean) GetStatus (frm->blast_allow_repeats_button);
8696 
8697 
8698   CKA_RunChecker(sep, &opts);
8699 
8700   ObjMgrSetDirtyFlag (frm->input_entityID, TRUE);
8701   ObjMgrSendMsg (OM_MSG_UPDATE, frm->input_entityID, 0, 0);
8702   Remove (frm->form);
8703 
8704 }
8705 
8706 
CreateSeqHistTPADetailed(IteM i)8707 NLM_EXTERN void CreateSeqHistTPADetailed (IteM i)
8708 {
8709    BaseFormPtr        bfp;
8710    TPAHistFormPtr frm;
8711    GrouP   c;
8712    GrouP   g;
8713    GrouP   h;
8714    WindoW  w;
8715    ButtoN  b;
8716    Char    buf[64];
8717    CKABlastOptsData opts;
8718 
8719 #ifdef WIN_MAC
8720   bfp = currentFormDataPtr;
8721 #else
8722   bfp = GetObjectExtra (i);
8723 #endif
8724   if (bfp == NULL) return;
8725 
8726    frm = MemNew (sizeof (TPAHistFormData));
8727    frm->input_entityID = bfp->input_entityID;
8728    w = FixedWindow (-50, -33, -10, -10, "Blast Options", NULL);
8729    SetObjectExtra (w, frm, StdCleanupFormProc);
8730    frm->form = (ForM) w;
8731 
8732    h = HiddenGroup (w, -1, 0, NULL);
8733    SetGroupSpacing (h, 3, 2);
8734    g = HiddenGroup (h, 2, 0, NULL);
8735 
8736    SetDefaultCKAOptions (&opts);
8737    StaticPrompt (g, "Word Size", 0, dialogTextHeight, programFont, 'l');
8738    sprintf(buf, "%d", opts.wordsize);
8739    frm->blast_wordsize_text = DialogText (g, buf, 10, NULL);
8740 
8741    StaticPrompt (g, "Expect Value", 0, dialogTextHeight, programFont, 'l');
8742    sprintf(buf, "%f", opts.expect_value);
8743    frm->blast_expect_value_text = DialogText (g, buf, 10, NULL);
8744 
8745    frm->blast_allow_repeats_button = CheckBox (g, "Allow Repeats", NULL);
8746    SetStatus(frm->blast_allow_repeats_button, opts.allow_repeats);
8747 
8748    c = HiddenGroup (w, 2, 0, NULL);
8749    SetGroupSpacing (c, 5, 5);
8750    b = DefaultButton (c, "Accept", DoAcceptBlastOptions);
8751    SetObjectExtra (b, frm, NULL);
8752    PushButton (c, "Cancel", StdCancelButtonProc);
8753    AlignObjects (ALIGN_CENTER, (HANDLE) h, (HANDLE) c, NULL);
8754    RealizeWindow (w);
8755    Show (w);
8756    Select (w);
8757    Select (frm->blast_wordsize_text);
8758 }
8759 
8760 extern Int2 LIBCALLBACK AssemblyUserGenFunc (Pointer data);
8761 
8762 typedef struct assemblyuserdialog {
8763   DIALOG_MESSAGE_BLOCK
8764   DialoG        accns;
8765 } AssemblyUserDialog, PNTR AssemblyUserDialogPtr;
8766 
8767 typedef struct assemblyuserform {
8768   FEATURE_FORM_BLOCK
8769   SeqEntryPtr   sep;
8770   SeqDescrPtr   orig_sdp;
8771 } AssemblyUserForm, PNTR AssemblyUserFormPtr;
8772 
UserObjectPtrToAssemblyDialog(DialoG d,Pointer data)8773 static void UserObjectPtrToAssemblyDialog (DialoG d, Pointer data)
8774 
8775 {
8776   AssemblyUserDialogPtr  adp;
8777   Char                   buf [16];
8778   UserFieldPtr           curr;
8779   Int4                   from;
8780   ValNodePtr             head = NULL;
8781   ObjectIdPtr            oip;
8782   CharPtr                str;
8783   CharPtr                tmp;
8784   Int4                   to;
8785   UserFieldPtr           ufp;
8786   UserObjectPtr          uop;
8787 
8788   adp = (AssemblyUserDialogPtr) GetObjectExtra (d);
8789   if (adp == NULL) return;
8790 
8791   uop = (UserObjectPtr) data;
8792   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "TpaAssembly") != 0) {
8793     PointerToDialog (adp->accns, NULL);
8794     return;
8795   }
8796 
8797   for (curr = uop->data; curr != NULL; curr = curr->next) {
8798     if (curr->choice != 11) continue;
8799     str = NULL;
8800     from = 0;
8801     to = 0;
8802     for (ufp = curr->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
8803       oip = ufp->label;
8804       if (oip == NULL) continue;
8805       if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
8806         str = (CharPtr) ufp->data.ptrvalue;
8807       } else if (StringICmp (oip->str, "from") == 0 && ufp->choice == 2) {
8808         from = (Int4) ufp->data.intvalue;
8809       } else if (StringICmp (oip->str, "to") == 0 && ufp->choice == 2) {
8810         to = (Int4) ufp->data.intvalue;
8811       }
8812     }
8813     if (StringHasNoText (str)) continue;
8814     tmp = MemNew (StringLen (str) + 32);
8815     StringCpy (tmp, str);
8816     StringCat (tmp, "\t");
8817     if (from > 0 || to > 0) {
8818       sprintf (buf, "%ld", (long) (from + 1));
8819       StringCat (tmp, buf);
8820       StringCat (tmp, "\t");
8821       sprintf (buf, "%ld", (long) (to + 1));
8822       StringCat (tmp, buf);
8823       StringCat (tmp, "\t");
8824     } else {
8825       StringCat (tmp, "\t\t");
8826     }
8827     ValNodeAddStr (&head, 0, (Pointer) tmp);
8828   }
8829 
8830   PointerToDialog (adp->accns, (Pointer) head);
8831   ValNodeFreeData (head);
8832 }
8833 
DoAddAccessionToTpa(UserObjectPtr uop,CharPtr last)8834 static void DoAddAccessionToTpa (UserObjectPtr uop, CharPtr last)
8835 
8836 {
8837   Int4      from = 0;
8838   CharPtr   ptr1, ptr2, ptr3;
8839   Int4      to = 0;
8840   long int  val;
8841 
8842   ptr1 = StringChr (last, '\t');
8843   if (ptr1 != NULL) {
8844     *ptr1 = '\0';
8845     ptr1++;
8846     ptr2 = StringChr (ptr1, '\t');
8847     if (ptr2 != NULL) {
8848       *ptr2 = '\0';
8849       ptr2++;
8850       ptr3 = StringChr (ptr2, '\t');
8851       if (ptr3 != NULL) {
8852         *ptr3 = '\0';
8853       }
8854     }
8855     if (sscanf (ptr1, "%ld", &val) == 1 && val > 0) {
8856       from = val - 1;
8857       if (sscanf (ptr2, "%ld", &val) == 1 && val > 0) {
8858         to = val - 1;
8859       } else {
8860         from = 0;
8861         to = 0;
8862       }
8863     }
8864   }
8865   AddAccessionToTpaAssemblyUserObject (uop, last, from, to);
8866 }
8867 
AssemblyDialogToUserObjectPtr(DialoG d)8868 static Pointer AssemblyDialogToUserObjectPtr (DialoG d)
8869 
8870 {
8871   AssemblyUserDialogPtr  adp;
8872   Char                   ch;
8873   ValNodePtr             head;
8874   CharPtr                last;
8875   UserObjectPtr          uop;
8876   CharPtr                ptr;
8877   CharPtr                str;
8878   CharPtr                tmp;
8879   ValNodePtr             vnp;
8880 
8881   adp = (AssemblyUserDialogPtr) GetObjectExtra (d);
8882   if (adp == NULL) return NULL;
8883 
8884   uop = CreateTpaAssemblyUserObject ();
8885   if (uop == NULL) return NULL;
8886 
8887   head = (ValNodePtr) DialogToPointer (adp->accns);
8888   if (head == NULL) return NULL;
8889 
8890   for (vnp = head; vnp != NULL; vnp = vnp->next) {
8891     str = (CharPtr) vnp->data.ptrvalue;
8892     if (StringHasNoText (str)) continue;
8893     tmp = StringSave (str);
8894     last = tmp;
8895     ptr = last;
8896     ch = *ptr;
8897     while (ch != '\0') {
8898       if (ch == ',' || ch == ' ') {
8899         *ptr = '\0';
8900         TrimSpacesAroundString (last);
8901         DoAddAccessionToTpa (uop, last);
8902         ptr++;
8903         last = ptr;
8904         ch = *ptr;
8905       } else {
8906         ptr++;
8907         ch = *ptr;
8908       }
8909     }
8910     if (! StringHasNoText (last)) {
8911       TrimSpacesAroundString (last);
8912       DoAddAccessionToTpa (uop, last);
8913     }
8914     MemFree (tmp);
8915   }
8916 
8917   ValNodeFreeData (head);
8918 
8919   return uop;
8920 }
8921 
ValNodePtrToAssemblyDialog(DialoG d,Pointer data)8922 static void ValNodePtrToAssemblyDialog (DialoG d, Pointer data)
8923 
8924 {
8925   ValNodePtr   head;
8926   Int2         j;
8927   ValNodePtr   list;
8928   CharPtr      str;
8929   TagListPtr   tlp;
8930   ValNodePtr   vnp;
8931 
8932   tlp = (TagListPtr) GetObjectExtra (d);
8933   list = (ValNodePtr) data;
8934   if (tlp != NULL) {
8935     head = NULL;
8936     while (list != NULL) {
8937       vnp = ValNodeNew (head);
8938       if (head == NULL) {
8939         head = vnp;
8940       }
8941       if (vnp != NULL) {
8942         str = MemNew (StringLen ((CharPtr) list->data.ptrvalue) + 3);
8943         if (str != NULL) {
8944           StringCpy (str, (CharPtr) list->data.ptrvalue);
8945           StringCat (str, "\n");
8946         }
8947         vnp->data.ptrvalue = str;
8948       }
8949       list = list->next;
8950     }
8951     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
8952     tlp->vnp = head;
8953     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
8954     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
8955     }
8956     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
8957     CorrectBarMax (tlp->bar, tlp->max);
8958     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
8959   }
8960 }
8961 
AssemblyDialogToValNodePtr(DialoG d)8962 static Pointer AssemblyDialogToValNodePtr (DialoG d)
8963 
8964 {
8965   Char         ch;
8966   ValNodePtr   head;
8967   Int2         j;
8968   Int2         len;
8969   ValNodePtr   list;
8970   Boolean      okay;
8971   CharPtr      str;
8972   TagListPtr   tlp;
8973   ValNodePtr   vnp;
8974 
8975   head = NULL;
8976   tlp = (TagListPtr) GetObjectExtra (d);
8977   if (tlp != NULL && tlp->vnp != NULL) {
8978     list = NULL;
8979     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
8980       str = (CharPtr) vnp->data.ptrvalue;
8981       okay = FALSE;
8982       len = StringLen (str);
8983       for (j = 0; j < len; j++) {
8984         ch = str [j];
8985         if (ch != ' ' && ch != '\t' && ch != '\n') {
8986           okay = TRUE;
8987         }
8988       }
8989       if (okay) {
8990         list = ValNodeNew (list);
8991         if (head == NULL) {
8992           head = list;
8993         }
8994         if (list != NULL) {
8995           list->choice = 0;
8996           list->data.ptrvalue = StringSave ((CharPtr) vnp->data.ptrvalue);
8997         }
8998       }
8999     }
9000   }
9001   return (Pointer) head;
9002 }
9003 
9004 Uint2 assmbly_types [] = {
9005   TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_TEXT
9006 };
9007 
9008 Uint2 assmbly_widths [] = {
9009   16, 8, 8, 0
9010 };
9011 
CreateAssemblyDialog(GrouP g)9012 static DialoG CreateAssemblyDialog (GrouP g)
9013 
9014 {
9015   AssemblyUserDialogPtr  adp;
9016   GrouP                  p;
9017   GrouP                  x;
9018   GrouP                  y;
9019 
9020   p = HiddenGroup (g, -1, 0, NULL);
9021   SetGroupSpacing (p, 10, 10);
9022 
9023   adp = (AssemblyUserDialogPtr) MemNew (sizeof (AssemblyUserDialog));
9024   if (adp == NULL) return NULL;
9025 
9026   SetObjectExtra (p, adp, NULL);
9027   adp->dialog = (DialoG) p;
9028   adp->todialog = UserObjectPtrToAssemblyDialog;
9029   adp->fromdialog = AssemblyDialogToUserObjectPtr;
9030 
9031   x = HiddenGroup (p, 0, 2, NULL);
9032   y = HiddenGroup (x, 3, 0, NULL);
9033   StaticPrompt (y, "Accessions", 16 * stdCharWidth, 0, programFont, 'c');
9034   StaticPrompt (y, "From", 8 * stdCharWidth, 0, programFont, 'c');
9035   StaticPrompt (y, "To", 8 * stdCharWidth, 0, programFont, 'c');
9036   adp->accns = CreateTagListDialog (x, 3, 3, -1,
9037                                     assmbly_types, assmbly_widths, NULL,
9038                                     ValNodePtrToAssemblyDialog,
9039                                     AssemblyDialogToValNodePtr);
9040 
9041   return (DialoG) p;
9042 }
9043 
AssemblyUserFormMessage(ForM f,Int2 mssg)9044 static void AssemblyUserFormMessage (ForM f, Int2 mssg)
9045 
9046 {
9047   AssemblyUserFormPtr  afp;
9048 
9049   afp = (AssemblyUserFormPtr) GetObjectExtra (f);
9050   if (afp != NULL) {
9051     switch (mssg) {
9052       case VIB_MSG_CLOSE :
9053         Remove (f);
9054         break;
9055       case VIB_MSG_CUT :
9056         StdCutTextProc (NULL);
9057         break;
9058       case VIB_MSG_COPY :
9059         StdCopyTextProc (NULL);
9060         break;
9061       case VIB_MSG_PASTE :
9062         StdPasteTextProc (NULL);
9063         break;
9064       case VIB_MSG_DELETE :
9065         StdDeleteTextProc (NULL);
9066         break;
9067       default :
9068         if (afp->appmessage != NULL) {
9069           afp->appmessage (f, mssg);
9070         }
9071         break;
9072     }
9073   }
9074 }
9075 
9076 
CountNumberSequence(CharPtr str)9077 static Int4 CountNumberSequence (CharPtr str)
9078 {
9079   if (StringHasNoText (str)) return 0;
9080   else return StringSpn (str, "0123456789");
9081 }
9082 
CountCapitalLetterSequence(CharPtr str)9083 static Int4 CountCapitalLetterSequence (CharPtr str)
9084 {
9085   if (StringHasNoText (str)) return 0;
9086   else return StringSpn (str, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
9087 }
9088 
LooksLikeTPAAccession(CharPtr str)9089 static Boolean LooksLikeTPAAccession (CharPtr str)
9090 {
9091   Int4 len, num_len, letter_len;
9092 
9093   if (StringHasNoText (str)) return TRUE;
9094 
9095   len = StringLen (str);
9096 
9097   if (StringNICmp (str, "ti", 2) == 0 && CountNumberSequence (str + 2) == len - 2)
9098   {
9099     return TRUE;
9100   }
9101   else if (StringChr (str, '_') != NULL)
9102   {
9103     return FALSE;
9104   }
9105   letter_len = CountCapitalLetterSequence (str);
9106   num_len = CountNumberSequence(str + letter_len);
9107 
9108   if ((letter_len == 1 && num_len == 5)
9109       || (letter_len == 2 && num_len == 6)
9110       || (letter_len == 4 && num_len == 8))
9111   {
9112     if (str[letter_len + num_len] == 0
9113         || (str[letter_len + num_len] == '.' && letter_len + num_len + 1 + CountNumberSequence (str + letter_len + num_len + 1) == len))
9114     {
9115       return TRUE;
9116     }
9117   }
9118   return FALSE;
9119 }
9120 
9121 
TPAAssemblyFormAccept(ButtoN b)9122 static void TPAAssemblyFormAccept (ButtoN b)
9123 
9124 {
9125   AssemblyUserFormPtr afp;
9126   UserObjectPtr     uop;
9127   UserFieldPtr      curr, ufp;
9128   LogInfoPtr        lip;
9129   CharPtr           str;
9130   Boolean           some_bad = FALSE;
9131   ObjectIdPtr       oip;
9132 
9133   afp = (AssemblyUserFormPtr) GetObjectExtra (b);
9134 
9135   uop = (UserObjectPtr) DialogToPointer (afp->data);
9136   if (uop == NULL)
9137   {
9138     StdAcceptFormButtonProc (b);
9139     return;
9140   }
9141 
9142   lip = OpenLog ("Possible Problem Accessions");
9143 
9144   /* put explanatory text here, but do not set data_in_log flag until
9145    * suspect accession is actually found
9146    */
9147   fprintf (lip->fp, "The information you have input does not appear to be a GenBank accession number.\n");
9148   fprintf (lip->fp, "Please confirm that you have identified the primary sequences used to assemble \n"
9149                     "or derive your TPA sequences with GenBank accession numbers in the correct format.\n");
9150 
9151   for (curr = uop->data; curr != NULL; curr = curr->next) {
9152     if (curr->choice != 11) continue;
9153     str = NULL;
9154     for (ufp = curr->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
9155       oip = ufp->label;
9156       if (oip == NULL) continue;
9157       if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
9158         str = (CharPtr) ufp->data.ptrvalue;
9159         if (!LooksLikeTPAAccession (str))
9160         {
9161           fprintf (lip->fp, "%s\n", str);
9162           lip->data_in_log = TRUE;
9163           some_bad = TRUE;
9164         }
9165       }
9166     }
9167   }
9168 
9169   CloseLog (lip);
9170   lip = FreeLog (lip);
9171   uop = UserObjectFree (uop);
9172 
9173   if (some_bad && ANS_NO == Message (MSG_YN, "Some of your accession numbers may not be in the correct format - continue anyway?"))
9174   {
9175     Select (afp->form);
9176     return;
9177   }
9178 
9179   StdAcceptFormButtonProc (b);
9180 }
9181 
9182 
PopulateAssemblyIntervals(ButtoN b)9183 static void PopulateAssemblyIntervals (ButtoN b)
9184 {
9185   AssemblyUserFormPtr  afp;
9186   BioseqPtr            bsp;
9187   UserObjectPtr        uop;
9188   SeqAlignPtr          salp;
9189   Char                 id_txt[355];
9190   SeqIdPtr             sip;
9191   Int4                 primary_start, primary_stop;
9192 
9193   afp = (AssemblyUserFormPtr) GetObjectExtra (b);
9194   if (afp == NULL) {
9195     return;
9196   }
9197 
9198   bsp = GetSequenceForObject (OBJ_SEQDESC, afp->orig_sdp);
9199   if (bsp != NULL && bsp->hist != NULL && bsp->hist->assembly != NULL) {
9200     uop = CreateTpaAssemblyUserObject  ();
9201     /* populate user object with intervals */
9202     for (salp = bsp->hist->assembly; salp != NULL; salp = salp->next) {
9203       AlnMgr2IndexSingleChildSeqAlign (salp);
9204       sip = AlnMgr2GetNthSeqIdPtr (salp, 2);
9205       SeqIdWrite (sip, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
9206       AlnMgr2GetNthSeqRangeInSA (salp, 1, &primary_start, &primary_stop);
9207       if (AlnMgr2GetNthStrand (salp, 2) == Seq_strand_minus) {
9208         AddAccessionToTpaAssemblyUserObject (uop, id_txt, primary_stop, primary_start);
9209       } else {
9210         AddAccessionToTpaAssemblyUserObject (uop, id_txt, primary_start, primary_stop);
9211       }
9212       sip = SeqIdFree (sip);
9213     }
9214 
9215     PointerToDialog (afp->data, uop);
9216     uop = UserObjectFree (uop);
9217   }
9218 }
9219 
ExportTpaAccessionList(ButtoN b)9220 static void ExportTpaAccessionList (ButtoN b)
9221 {
9222   AssemblyUserFormPtr  afp;
9223   UserObjectPtr        uop;
9224   Char                 path[PATH_MAX];
9225   Boolean              first = TRUE;
9226   UserFieldPtr         curr, ufp;
9227   CharPtr              str;
9228   ObjectIdPtr          oip;
9229   FILE *fp;
9230 
9231   afp = (AssemblyUserFormPtr) GetObjectExtra (b);
9232   if (afp == NULL) {
9233     return;
9234   }
9235 
9236   uop = (UserObjectPtr) DialogToPointer (afp->data);
9237   if (uop == NULL)
9238   {
9239     return;
9240   }
9241 
9242   path[0] = 0;
9243   if (GetOutputFileName (path, sizeof (path), NULL)) {
9244 #ifdef WIN_MAC
9245     fp = FileOpen (path, "r");
9246     if (fp != NULL) {
9247       FileClose (fp);
9248     } else {
9249       FileCreate (path, "TEXT", "ttxt");
9250     }
9251 #endif
9252     fp = FileOpen (path, "w");
9253     if (fp == NULL) {
9254       Message (MSG_ERROR, "Unable to open %s", path);
9255     } else {
9256       for (curr = uop->data; curr != NULL; curr = curr->next) {
9257         if (curr->choice != 11) continue;
9258         str = NULL;
9259         for (ufp = curr->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
9260           oip = ufp->label;
9261           if (oip == NULL) continue;
9262           if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
9263             str = (CharPtr) ufp->data.ptrvalue;
9264             fprintf (fp, "%s%s", first ? "" : ", ", str);
9265             first = FALSE;
9266           }
9267         }
9268       }
9269       fprintf (fp, "\n");
9270       FileClose (fp);
9271     }
9272   }
9273 }
9274 
9275 
ExportTpaAccessionTable(ButtoN b)9276 static void ExportTpaAccessionTable (ButtoN b)
9277 {
9278   AssemblyUserFormPtr  afp;
9279   UserObjectPtr        uop;
9280   Char                 path[PATH_MAX];
9281   Boolean              first = TRUE;
9282   UserFieldPtr         curr, ufp;
9283   CharPtr              str;
9284   Int4                 from, to;
9285   ObjectIdPtr          oip;
9286   FILE *fp;
9287 
9288   afp = (AssemblyUserFormPtr) GetObjectExtra (b);
9289   if (afp == NULL) {
9290     return;
9291   }
9292 
9293   uop = (UserObjectPtr) DialogToPointer (afp->data);
9294   if (uop == NULL)
9295   {
9296     return;
9297   }
9298 
9299   path[0] = 0;
9300   if (GetOutputFileName (path, sizeof (path), NULL)) {
9301 #ifdef WIN_MAC
9302     fp = FileOpen (path, "r");
9303     if (fp != NULL) {
9304       FileClose (fp);
9305     } else {
9306       FileCreate (path, "TEXT", "ttxt");
9307     }
9308 #endif
9309     fp = FileOpen (path, "w");
9310     if (fp == NULL) {
9311       Message (MSG_ERROR, "Unable to open %s", path);
9312     } else {
9313       str = NULL;
9314       from = -1;
9315       to = -1;
9316       for (curr = uop->data; curr != NULL; curr = curr->next) {
9317         if (curr->choice != 11) continue;
9318         for (ufp = curr->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
9319           oip = ufp->label;
9320           if (oip == NULL) continue;
9321           if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
9322             if (!first) {
9323               fprintf (fp, "%s", str);
9324               if (from > -1 && to > -1) {
9325                 fprintf (fp, "\t%d\t%d", from + 1, to + 1);
9326               }
9327               fprintf (fp, "\n");
9328             }
9329             str = (CharPtr) ufp->data.ptrvalue;
9330             from = -1;
9331             to = -1;
9332             first = FALSE;
9333           } else if (StringICmp (oip->str, "from") == 0) {
9334             from = ufp->data.intvalue;
9335           } else if (StringICmp (oip->str, "to") == 0) {
9336             to = ufp->data.intvalue;
9337           }
9338         }
9339       }
9340       if (str != NULL) {
9341         fprintf (fp, "%s", str);
9342         if (from > -1 && to > -1) {
9343           fprintf (fp, "\t%d\t%d", from + 1, to + 1);
9344         }
9345         fprintf (fp, "\n");
9346       }
9347 
9348       FileClose (fp);
9349     }
9350   }
9351 }
9352 
9353 
ImportTPATable(ButtoN b)9354 static void ImportTPATable (ButtoN b)
9355 {
9356   AssemblyUserFormPtr  afp;
9357   FILE *fp;
9358   UserObjectPtr        uop;
9359   Char                 path[PATH_MAX];
9360   ReadBufferData rbd;
9361   CharPtr        line;
9362   ValNodePtr     column_list;
9363   UserFieldPtr   last = NULL, row, ufp;
9364 
9365   afp = (AssemblyUserFormPtr) GetObjectExtra (b);
9366   if (afp == NULL) {
9367     return;
9368   }
9369 
9370   path[0] = 0;
9371   if (!GetInputFileName (path, sizeof (path), "", "TEXT")) {
9372     return;
9373   }
9374   fp = FileOpen (path, "r");
9375   if (fp == NULL) {
9376     Message (MSG_ERROR, "Unable to open %s", path);
9377     return;
9378   }
9379 
9380   uop = CreateTpaAssemblyUserObject  ();
9381 
9382   rbd.fp = fp;
9383   rbd.current_data = NULL;
9384 
9385   line = AbstractReadFunction (&rbd);
9386   while (line != NULL)
9387   {
9388     column_list = ReadOneColumnList(line);
9389     if (column_list != NULL) {
9390       row = UserFieldNew ();
9391       row->choice = 11;
9392       row->label = ObjectIdNew();
9393       ufp = CreateTPAAssemblyAccessionField (column_list->data.ptrvalue);
9394       row->data.ptrvalue = ufp;
9395       if (column_list->next != NULL && column_list->next->next != NULL) {
9396         ufp->next = CreateTPAAssemblyFromField (atoi (column_list->next->data.ptrvalue) - 1);
9397         ufp->next->next = CreateTPAAssemblyToField (atoi (column_list->next->next->data.ptrvalue) - 1);
9398       }
9399       column_list = ValNodeFreeData (column_list);
9400       if (last == NULL) {
9401         uop->data = row;
9402       } else {
9403         last->next = row;
9404       }
9405       last = row;
9406     }
9407     line = AbstractReadFunction (&rbd);
9408   }
9409   FileClose (rbd.fp);
9410 
9411   PointerToDialog (afp->data, uop);
9412   uop = UserObjectFree (uop);
9413 }
9414 
9415 
CreateAssemblyDescForm(Int2 left,Int2 top,Int2 width,Int2 height,CharPtr title,ValNodePtr sdp,SeqEntryPtr sep,FormActnFunc actproc)9416 static ForM CreateAssemblyDescForm (Int2 left, Int2 top, Int2 width,
9417                                    Int2 height, CharPtr title, ValNodePtr sdp,
9418                                    SeqEntryPtr sep, FormActnFunc actproc)
9419 
9420 {
9421   AssemblyUserFormPtr  afp;
9422   ButtoN               b, pop_btn = NULL;
9423   GrouP                c;
9424   GrouP                g, g2;
9425   StdEditorProcsPtr    sepp;
9426   WindoW               w;
9427   BioseqPtr            bsp;
9428 
9429   w = NULL;
9430   afp = (AssemblyUserFormPtr) MemNew (sizeof (AssemblyUserForm));
9431   if (afp != NULL) {
9432     w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
9433     SetObjectExtra (w, afp, StdDescFormCleanupProc);
9434     afp->form = (ForM) w;
9435     afp->actproc = actproc;
9436     afp->formmessage = AssemblyUserFormMessage;
9437 
9438     afp->sep = sep;
9439 
9440 #ifndef WIN_MAC
9441     CreateStdEditorFormMenus (w);
9442 #endif
9443     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
9444     if (sepp != NULL) {
9445       SetActivate (w, sepp->activateForm);
9446       afp->appmessage = sepp->handleMessages;
9447     }
9448 
9449     g = HiddenGroup (w, -1, 0, NULL);
9450     afp->data = CreateAssemblyDialog (g);
9451 
9452     g2 = HiddenGroup (g, 2, 0, NULL);
9453     if (sdp != NULL) {
9454       bsp = GetSequenceForObject (OBJ_SEQDESC, sdp);
9455       if (bsp != NULL && bsp->hist != NULL && bsp->hist->assembly != NULL) {
9456         pop_btn = PushButton (g2, "Populate Intervals from Assembly Alignment", PopulateAssemblyIntervals);
9457         SetObjectExtra (pop_btn, afp, NULL);
9458       }
9459     }
9460     b = PushButton (g2, "Export TPA Accession List", ExportTpaAccessionList);
9461     SetObjectExtra (b, afp, NULL);
9462     b = PushButton (g2, "Export Interval Table", ExportTpaAccessionTable);
9463     SetObjectExtra (b, afp, NULL);
9464     b = PushButton (g2, "Import Interval Table", ImportTPATable);
9465     SetObjectExtra (b, afp, NULL);
9466 
9467     c = HiddenGroup (w, 2, 0, NULL);
9468     b = DefaultButton (c, "Accept", TPAAssemblyFormAccept);
9469     SetObjectExtra (b, afp, NULL);
9470     PushButton (c, "Cancel", StdCancelButtonProc);
9471     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) g2, NULL);
9472     RealizeWindow (w);
9473   }
9474   return (ForM) w;
9475 }
9476 
9477 
AssemblyUserGenFunc(Pointer data)9478 extern Int2 LIBCALLBACK AssemblyUserGenFunc (Pointer data)
9479 
9480 {
9481   AssemblyUserFormPtr  afp;
9482   ObjectIdPtr          oip;
9483   OMProcControlPtr     ompcp;
9484   OMUserDataPtr        omudp;
9485   ObjMgrProcPtr        proc;
9486   ValNodePtr           sdp;
9487   SeqEntryPtr          sep;
9488   UserObjectPtr        uop;
9489   WindoW               w;
9490 
9491   ompcp = (OMProcControlPtr) data;
9492   w = NULL;
9493   sdp = NULL;
9494   sep = NULL;
9495   uop = NULL;
9496   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
9497   proc = ompcp->proc;
9498   switch (ompcp->input_itemtype) {
9499     case OBJ_SEQDESC :
9500       sdp = (ValNodePtr) ompcp->input_data;
9501       if (sdp != NULL && sdp->choice != Seq_descr_user) {
9502         return OM_MSG_RET_ERROR;
9503       }
9504       if (sdp != NULL) {
9505         uop = (UserObjectPtr) sdp->data.ptrvalue;
9506       }
9507       break;
9508     case OBJ_BIOSEQ :
9509       break;
9510     case OBJ_BIOSEQSET :
9511       break;
9512     case 0 :
9513       break;
9514     default :
9515       return OM_MSG_RET_ERROR;
9516   }
9517   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
9518                                 ompcp->input_itemtype, ompcp->proc->procid);
9519   if (omudp != NULL) {
9520     if (StringCmp (proc->procname, "Edit Assembly User Desc") == 0) {
9521       afp = (AssemblyUserFormPtr) omudp->userdata.ptrvalue;
9522       if (afp != NULL) {
9523         Select (afp->form);
9524       }
9525       return OM_MSG_RET_DONE;
9526     } else {
9527       return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
9528     }
9529   }
9530   if (uop != NULL) {
9531     oip = uop->type;
9532     if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
9533     if (StringCmp (oip->str, "TpaAssembly") != 0) return OM_MSG_RET_OK;
9534   }
9535   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
9536   w = (WindoW) CreateAssemblyDescForm (-50, -33, -10, -10,
9537                                        "Assembly Tracking", sdp, sep,
9538                                        StdDescFormActnProc);
9539   afp = (AssemblyUserFormPtr) GetObjectExtra (w);
9540   if (afp != NULL) {
9541     afp->input_entityID = ompcp->input_entityID;
9542     afp->input_itemID = ompcp->input_itemID;
9543     afp->input_itemtype = ompcp->input_itemtype;
9544     afp->this_itemtype = OBJ_SEQDESC;
9545     afp->this_subtype = Seq_descr_user;
9546     afp->procid = ompcp->proc->procid;
9547     afp->proctype = ompcp->proc->proctype;
9548     afp->userkey = OMGetNextUserKey ();
9549     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
9550 	                           OMPROC_EDIT, afp->userkey);
9551     if (omudp != NULL) {
9552       omudp->userdata.ptrvalue = (Pointer) afp;
9553       omudp->messagefunc = StdVibrantEditorMsgFunc;
9554     }
9555     SendMessageToForm (afp->form, VIB_MSG_INIT);
9556     if (sdp != NULL) {
9557       PointerToDialog (afp->data, (Pointer) sdp->data.ptrvalue);
9558       SetClosestParentIfDuplicating ((BaseFormPtr) afp);
9559       afp->orig_sdp = sdp;
9560     }
9561   }
9562   Show (w);
9563   Select (w);
9564   return OM_MSG_RET_DONE;
9565 }
9566 
9567 
9568 /* advanced editor for Seq-hist assembly alignment */
9569 typedef struct assemblyalignmentdlg {
9570   DIALOG_MESSAGE_BLOCK
9571   DialoG intervals_dialog;
9572 
9573 
9574 } AssemblyAlignmentDlgData, PNTR AssemblyAlignmentDlgPtr;
9575 
9576 Uint2 assmbly_aln_types [] = {
9577   TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_PROMPT, TAGLIST_POPUP
9578 };
9579 
9580 Uint2 assmbly_aln_widths [] = {
9581   16, 8, 8, 8, 8, 8, 0
9582 };
9583 
ENUM_ALIST(assmbly_aln_strand_alist)9584 ENUM_ALIST(assmbly_aln_strand_alist)
9585   {"Plus",  0},
9586   {"Minus",    1},
9587 END_ENUM_ALIST
9588 
9589 
9590 
9591 static EnumFieldAssocPtr assmbly_aln_alists[] = {
9592   NULL, NULL, NULL, NULL, NULL, assmbly_aln_strand_alist
9593 };
9594 
9595 
9596 typedef struct assemblyalignmentinterval {
9597   CharPtr prim_accession;
9598   Int4    tpa_from;
9599   Int4    tpa_to;
9600   Int4    prim_from;
9601   Uint1   prim_strand;
9602   Uint2   percent_identity;
9603 } AssemblyAlignmentIntervalData, PNTR AssemblyAlignmentIntervalPtr;
9604 
9605 
AssemblyAlignmentIntervalFree(AssemblyAlignmentIntervalPtr interval)9606 static AssemblyAlignmentIntervalPtr AssemblyAlignmentIntervalFree (AssemblyAlignmentIntervalPtr interval)
9607 {
9608   if (interval != NULL) {
9609     interval->prim_accession = MemFree (interval->prim_accession);
9610     interval = MemFree (interval);
9611   }
9612   return interval;
9613 }
9614 
9615 
AssemblyAlignmentIntervalFromTagListString(CharPtr str)9616 static AssemblyAlignmentIntervalPtr AssemblyAlignmentIntervalFromTagListString (CharPtr str)
9617 {
9618   AssemblyAlignmentIntervalPtr interval;
9619   CharPtr cp;
9620   Int4    len, val;
9621 
9622   if (StringHasNoText (str)) {
9623     return NULL;
9624   }
9625 
9626   interval = (AssemblyAlignmentIntervalPtr) MemNew (sizeof (AssemblyAlignmentIntervalData));
9627   MemSet (interval, 0, sizeof (AssemblyAlignmentIntervalData));
9628 
9629   cp = StringChr (str, '\t');
9630   if (cp == NULL) {
9631     interval->prim_accession = StringSave (str);
9632   } else {
9633     len = cp - str + 1;
9634     interval->prim_accession = (CharPtr) MemNew (sizeof (Char) * len);
9635     StringNCpy (interval->prim_accession, str, len - 1);
9636     interval->prim_accession[len - 1] = 0;
9637     str = cp + 1;
9638     cp = StringChr (str, '\t');
9639     interval->tpa_from = atoi (str);
9640     if (cp != NULL) {
9641       str = cp + 1;
9642       cp = StringChr (str, '\t');
9643       interval->tpa_to = atoi (str);
9644       if (cp != NULL) {
9645         str = cp + 1;
9646         cp = StringChr (str, '\t');
9647         interval->prim_from = atoi (str);
9648         if (cp != NULL) {
9649           cp = StringChr (cp + 1, '\t');
9650           if (cp != NULL) {
9651             val = atoi (cp + 1);
9652             if (val == 1) {
9653               interval->prim_strand = Seq_strand_minus;
9654             } else {
9655               interval->prim_strand = Seq_strand_plus;
9656             }
9657           }
9658         }
9659       }
9660     }
9661   }
9662   return interval;
9663 }
9664 
9665 
TagListStringFromAssemblyAlignmentInterval(AssemblyAlignmentIntervalPtr interval)9666 static CharPtr TagListStringFromAssemblyAlignmentInterval (AssemblyAlignmentIntervalPtr interval)
9667 {
9668   CharPtr str, str_fmt = "%s\t%d\t%d\t%d\t%d (%d)\t%d\n";
9669 
9670   if (interval == NULL) {
9671     return NULL;
9672   }
9673 
9674   str = (CharPtr) MemNew (sizeof (Char) * (StringLen (str_fmt) + StringLen (interval->prim_accession) + 61));
9675   sprintf (str, str_fmt, interval->prim_accession == NULL ? "" : interval->prim_accession,
9676                          interval->tpa_from,
9677                          interval->tpa_to,
9678                          interval->prim_from,
9679                          interval->prim_from + interval->tpa_to - interval->tpa_from,
9680                          interval->percent_identity,
9681                          interval->prim_strand == Seq_strand_minus ? 1 : 0);
9682   return str;
9683 }
9684 
9685 
AssemblyAlignmentIntervalFromSeqAlign(SeqAlignPtr salp)9686 static AssemblyAlignmentIntervalPtr AssemblyAlignmentIntervalFromSeqAlign (SeqAlignPtr salp)
9687 {
9688   AssemblyAlignmentIntervalPtr interval;
9689   DenseSegPtr dsp;
9690   Char     id_txt[200];
9691 
9692   if (salp == NULL || salp->dim != 2 || salp->segtype != SAS_DENSEG) {
9693     return NULL;
9694   }
9695 
9696   dsp = (DenseSegPtr) salp->segs;
9697   if (dsp == NULL || dsp->numseg != 1) {
9698     return NULL;
9699   }
9700 
9701   interval = (AssemblyAlignmentIntervalPtr) MemNew (sizeof (AssemblyAlignmentIntervalData));
9702   MemSet (interval, 0, sizeof (AssemblyAlignmentIntervalData));
9703 
9704   /* first row is TPA, second row is primary */
9705   SeqIdWrite (dsp->ids->next, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
9706   interval->prim_accession = StringSave (id_txt);
9707 
9708   interval->tpa_from = dsp->starts[0] + 1;
9709   interval->tpa_to = dsp->starts[0] + dsp->lens[0];
9710   interval->prim_from = dsp->starts[1] + 1;
9711   if (dsp->strands == NULL) {
9712     interval->prim_strand = Seq_strand_plus;
9713   } else {
9714     interval->prim_strand = dsp->strands[1];
9715   }
9716 
9717   interval->percent_identity = AlignmentPercentIdentity (salp, FALSE);
9718 
9719   return interval;
9720 }
9721 
9722 
SeqAlignFromAssemblyAlignmentInterval(AssemblyAlignmentIntervalPtr interval)9723 static SeqAlignPtr SeqAlignFromAssemblyAlignmentInterval (AssemblyAlignmentIntervalPtr interval)
9724 {
9725   SeqAlignPtr salp;
9726   DenseSegPtr dsp;
9727 
9728   if (interval == NULL) {
9729     return NULL;
9730   }
9731   dsp = DenseSegNew ();
9732   dsp->dim = 2;
9733   dsp->numseg = 1;
9734   dsp->starts = (Int4Ptr) MemNew (sizeof (Int4) * dsp->dim * dsp->numseg);
9735   dsp->lens = (Int4Ptr) MemNew (sizeof (Int4) * dsp->numseg);
9736   dsp->strands = (Uint1Ptr) MemNew (sizeof (Uint1) * dsp->dim * dsp->numseg);
9737 
9738   dsp->ids = ValNodeNew (NULL);
9739   dsp->ids->next = SeqIdFromAccessionDotVersion(interval->prim_accession);
9740 
9741   dsp->starts[0] = interval->tpa_from - 1;
9742   dsp->starts[1] = interval->prim_from - 1;
9743   dsp->lens[0] = interval->tpa_to - interval->tpa_from + 1;
9744   dsp->strands[0] = Seq_strand_plus;
9745   dsp->strands[1] = interval->prim_strand;
9746 
9747   salp = SeqAlignNew ();
9748   salp->dim = 2;
9749   salp->segtype = SAS_DENSEG;
9750   salp->segs = dsp;
9751   salp->type = SAT_PARTIAL;
9752   return salp;
9753 }
9754 
9755 
SeqAlignToAssemblyAlignmentDialog(DialoG d,Pointer data)9756 static void SeqAlignToAssemblyAlignmentDialog (DialoG d, Pointer data)
9757 {
9758   AssemblyAlignmentDlgPtr dlg;
9759 
9760   dlg = (AssemblyAlignmentDlgPtr) GetObjectExtra (d);
9761   if (dlg == NULL) {
9762     return;
9763   }
9764 
9765   PointerToDialog (dlg->intervals_dialog, data);
9766 }
9767 
9768 
AssemblyAlignmentDialogToSeqAlign(DialoG d)9769 static Pointer AssemblyAlignmentDialogToSeqAlign (DialoG d)
9770 {
9771   AssemblyAlignmentDlgPtr dlg;
9772   SeqAlignPtr salp = NULL;
9773 
9774   dlg = (AssemblyAlignmentDlgPtr) GetObjectExtra (d);
9775   if (dlg == NULL) {
9776     return NULL;
9777   }
9778 
9779   salp = DialogToPointer (dlg->intervals_dialog);
9780 
9781   return salp;
9782 }
9783 
9784 
SeqAlignToTagDlg(DialoG d,Pointer data)9785 static void SeqAlignToTagDlg (DialoG d, Pointer data)
9786 {
9787   TagListPtr tlp;
9788   SeqAlignPtr salp;
9789   AssemblyAlignmentIntervalPtr interval;
9790 
9791   tlp =(TagListPtr) GetObjectExtra (d);
9792   if (tlp == NULL) {
9793     return;
9794   }
9795 
9796   tlp->vnp = ValNodeFreeData (tlp->vnp);
9797   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
9798   salp = (SeqAlignPtr) data;
9799 
9800   while (salp != NULL) {
9801     interval = AssemblyAlignmentIntervalFromSeqAlign (salp);
9802     if (interval != NULL) {
9803       ValNodeAddPointer (&(tlp->vnp), 0, TagListStringFromAssemblyAlignmentInterval (interval));
9804       interval = AssemblyAlignmentIntervalFree (interval);
9805     }
9806     salp = salp->next;
9807   }
9808   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
9809 }
9810 
9811 
SeqAlignFromTagDlg(DialoG d)9812 static Pointer SeqAlignFromTagDlg (DialoG d)
9813 {
9814   TagListPtr tlp;
9815   SeqAlignPtr salp = NULL, salp_last = NULL, salp_tmp;
9816   ValNodePtr vnp;
9817   AssemblyAlignmentIntervalPtr interval;
9818 
9819   tlp =(TagListPtr) GetObjectExtra (d);
9820   if (tlp == NULL) {
9821     return NULL;
9822   }
9823 
9824   for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
9825     interval = AssemblyAlignmentIntervalFromTagListString (vnp->data.ptrvalue);
9826     if (interval != NULL) {
9827       salp_tmp = SeqAlignFromAssemblyAlignmentInterval (interval);
9828       if (salp_tmp != NULL) {
9829         if (salp_last == NULL) {
9830           salp = salp_tmp;
9831         } else {
9832           salp_last->next = salp_tmp;
9833         }
9834         salp_last = salp_tmp;
9835       }
9836       interval = AssemblyAlignmentIntervalFree (interval);
9837     }
9838   }
9839   return salp;
9840 }
9841 
9842 
CreateAssemblyAlignmentDialog(GrouP g)9843 static DialoG CreateAssemblyAlignmentDialog (GrouP g)
9844 
9845 {
9846   AssemblyAlignmentDlgPtr dlg;
9847   GrouP                   p;
9848   GrouP                   x;
9849   GrouP                   y;
9850 
9851   p = HiddenGroup (g, -1, 0, NULL);
9852   SetGroupSpacing (p, 10, 10);
9853 
9854   dlg = (AssemblyAlignmentDlgPtr) MemNew (sizeof (AssemblyAlignmentDlgData));
9855   if (dlg == NULL) return NULL;
9856 
9857   SetObjectExtra (p, dlg, NULL);
9858   dlg->dialog = (DialoG) p;
9859   dlg->todialog = SeqAlignToAssemblyAlignmentDialog;
9860   dlg->fromdialog = AssemblyAlignmentDialogToSeqAlign;
9861 
9862   x = HiddenGroup (p, 0, 2, NULL);
9863   y = HiddenGroup (x, 6, 0, NULL);
9864   StaticPrompt (y, "", 16 * stdCharWidth, 0, programFont, 'c');
9865   StaticPrompt (y, "", 8 * stdCharWidth, 0, programFont, 'c');
9866   StaticPrompt (y, "", 8 * stdCharWidth, 0, programFont, 'c');
9867   StaticPrompt (y, "", 8 * stdCharWidth, 0, programFont, 'c');
9868   StaticPrompt (y, "Primary To", 8 * stdCharWidth, 0, programFont, 'c');
9869   StaticPrompt (y, "", 8 * stdCharWidth, 0, programFont, 'c');
9870   StaticPrompt (y, "Accessions", 16 * stdCharWidth, 0, programFont, 'c');
9871   StaticPrompt (y, "TPA From", 8 * stdCharWidth, 0, programFont, 'c');
9872   StaticPrompt (y, "TPA To", 8 * stdCharWidth, 0, programFont, 'c');
9873   StaticPrompt (y, "Primary From", 8 * stdCharWidth, 0, programFont, 'c');
9874   StaticPrompt (y, "(Percent Identity)", 8 * stdCharWidth, 0, programFont, 'c');
9875   StaticPrompt (y, "Primary Strand", 8 * stdCharWidth, 0, programFont, 'c');
9876   dlg->intervals_dialog = CreateTagListDialogExEx (x, 6, 6, -1, assmbly_aln_types, assmbly_aln_widths, assmbly_aln_alists,
9877                                                    TRUE, FALSE, SeqAlignToTagDlg, SeqAlignFromTagDlg,
9878                                                    NULL, NULL, FALSE);
9879 
9880 
9881   return (DialoG) p;
9882 }
9883 
9884 
AddTPAIdToAlignment(SeqAlignPtr salp,BioseqPtr bsp)9885 static void AddTPAIdToAlignment (SeqAlignPtr salp, BioseqPtr bsp)
9886 {
9887   DenseSegPtr dsp;
9888   SeqIdPtr    sip;
9889 
9890   if (salp == NULL || salp->dim != 2 || salp->segtype != SAS_DENSEG || bsp == NULL) {
9891     return;
9892   }
9893 
9894   dsp = salp->segs;
9895   if (dsp == NULL) {
9896     return;
9897   }
9898 
9899   sip = SeqIdFindWorst (bsp->id);
9900   sip = SeqIdDup (sip);
9901 
9902   sip->next = dsp->ids->next;
9903   dsp->ids->next = NULL;
9904   dsp->ids = SeqIdFree (dsp->ids);
9905   dsp->ids = sip;
9906 }
9907 
9908 
AddTPAIdToAlignmentList(SeqAlignPtr salp,BioseqPtr bsp)9909 static void AddTPAIdToAlignmentList (SeqAlignPtr salp, BioseqPtr bsp)
9910 {
9911   while (salp != NULL) {
9912     AddTPAIdToAlignment (salp, bsp);
9913     salp = salp->next;
9914   }
9915 }
9916 
9917 typedef struct assemblyalignmentform {
9918   FORM_MESSAGE_BLOCK
9919   DialoG dlg;
9920   BioseqPtr bsp;
9921 } AssemblyAlignmentFormData, PNTR AssemblyAlignmentFormPtr;
9922 
9923 
CheckCoverageWithAddedIntervals(LogInfoPtr lip,BioseqPtr bsp,SeqAlignPtr salp)9924 static void CheckCoverageWithAddedIntervals (LogInfoPtr lip, BioseqPtr bsp, SeqAlignPtr salp)
9925 {
9926   ValNodePtr err_list = NULL;
9927   SeqAlignPtr salp_orig, salp_prev = NULL;
9928 
9929   if (bsp == NULL) {
9930     return;
9931   }
9932 
9933   if (bsp->hist == NULL) {
9934     bsp->hist = SeqHistNew ();
9935   }
9936 
9937   salp_orig = bsp->hist->assembly;
9938   while (salp_orig != NULL) {
9939     salp_prev = salp_orig;
9940     salp_orig = salp_orig->next;
9941   }
9942 
9943   if (salp_prev == NULL) {
9944     bsp->hist->assembly = salp;
9945   } else {
9946     salp_prev->next = salp;
9947   }
9948 
9949   ValidateTPAHistAlign (bsp, &err_list);
9950   if (err_list != NULL) {
9951     fprintf (lip->fp, "Projected Coverage Problems\n");
9952     PrintTPAHistErrors (lip, err_list);
9953     lip->data_in_log = TRUE;
9954     err_list = ValNodeFreeData (err_list);
9955   }
9956 
9957   if (salp_prev == NULL) {
9958     bsp->hist->assembly = NULL;
9959   } else {
9960     salp_prev->next = NULL;
9961   }
9962 }
9963 
9964 
ReportAssemblyIntervalProblems(BioseqPtr bsp,SeqAlignPtr salp)9965 static Boolean ReportAssemblyIntervalProblems (BioseqPtr bsp, SeqAlignPtr salp)
9966 {
9967   LogInfoPtr lip;
9968   AssemblyAlignmentIntervalPtr interval;
9969   Boolean    has_errors = FALSE;
9970   SeqAlignPtr salp_tmp;
9971 
9972   lip = OpenLog ("Assembly Alignment Interval Problems");
9973   fprintf (lip->fp, "Primary Accession\tTPA From\tTPA To\tPrimary From\tPrimary To\tStrand\tPercent Identity\n");
9974   for (salp_tmp = salp; salp_tmp != NULL; salp_tmp = salp_tmp->next) {
9975     interval = AssemblyAlignmentIntervalFromSeqAlign (salp_tmp);
9976     fprintf (lip->fp, "%s\t%d\t%d\t%d\t%d\t%s\t%d%s\n",
9977              interval->prim_accession,
9978              interval->tpa_from,
9979              interval->tpa_to,
9980              interval->prim_from,
9981              interval->prim_from + interval->tpa_to - interval->tpa_from,
9982              interval->prim_strand == Seq_strand_minus ? "c" : "",
9983              interval->percent_identity,
9984              interval->percent_identity < 75 ? "(Suspiciously low percent identity!)" : "");
9985     if (interval->percent_identity < 75) {
9986       lip->data_in_log = TRUE;
9987     }
9988     interval = AssemblyAlignmentIntervalFree (interval);
9989   }
9990   fprintf (lip->fp, "\n");
9991   CheckCoverageWithAddedIntervals (lip, bsp, salp);
9992   CloseLog (lip);
9993   has_errors = lip->data_in_log;
9994   return has_errors;
9995 }
9996 
9997 
AcceptAssemblyAlignment(ButtoN b)9998 static void AcceptAssemblyAlignment (ButtoN b)
9999 {
10000   AssemblyAlignmentFormPtr frm;
10001   SeqAlignPtr              salp, salp_next;
10002   ValNodePtr               list;
10003   MsgAnswer                ans = ANS_OK;
10004 
10005   frm = (AssemblyAlignmentFormPtr) GetObjectExtra (b);
10006   if (frm == NULL) {
10007     return;
10008   }
10009   salp = DialogToPointer (frm->dlg);
10010   if (salp == NULL) {
10011     Message (MSG_ERROR, "No intervals specified");
10012     return;
10013   }
10014   AddTPAIdToAlignmentList (salp, frm->bsp);
10015   if (ReportAssemblyIntervalProblems (frm->bsp, salp)) {
10016     ans = Message (MSG_OKC, "Continue with errors?");
10017   }
10018 
10019   if (ans == ANS_OK) {
10020     if (frm->bsp->hist == NULL) {
10021       frm->bsp->hist = SeqHistNew ();
10022     }
10023 
10024     /* something is wrong here, alignment is not being sorted */
10025     salp_next = salp;
10026     while (salp_next->next != NULL) {
10027       salp_next = salp_next->next;
10028     }
10029     salp_next->next = frm->bsp->hist->assembly;
10030 
10031     list = SeqAlignSortListNew (salp);
10032     list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
10033     salp = SeqAlignFromSeqAlignSortList (list);
10034     list = SeqAlignSortListFree (list);
10035     frm->bsp->hist->assembly = salp;
10036     ObjMgrSetDirtyFlag (frm->bsp->idx.entityID, TRUE);
10037     ObjMgrSendMsg (OM_MSG_UPDATE, frm->bsp->idx.entityID, 0, 0);
10038     Remove (frm->form);
10039   } else {
10040     while (salp != NULL) {
10041       salp_next = salp->next;
10042       salp->next = NULL;
10043       salp = SeqAlignFree (salp);
10044       salp = salp_next;
10045     }
10046   }
10047 }
10048 
10049 
CheckAssemblyAlignment(ButtoN b)10050 static void CheckAssemblyAlignment (ButtoN b)
10051 {
10052   AssemblyAlignmentFormPtr frm;
10053   SeqAlignPtr              salp, salp_next;
10054 
10055   frm = (AssemblyAlignmentFormPtr) GetObjectExtra (b);
10056   if (frm == NULL) {
10057     return;
10058   }
10059 
10060   salp = DialogToPointer (frm->dlg);
10061   if (salp == NULL) {
10062     Message (MSG_ERROR, "No intervals specified");
10063     return;
10064   }
10065   AddTPAIdToAlignmentList (salp, frm->bsp);
10066   PointerToDialog (frm->dlg, salp);
10067   ReportAssemblyIntervalProblems (frm->bsp, salp);
10068 
10069   while (salp != NULL) {
10070     salp_next = salp->next;
10071     salp->next = NULL;
10072     salp = SeqAlignFree (salp);
10073     salp = salp_next;
10074   }
10075 }
10076 
10077 
AdvancedAssemblyAlignmentEditor(IteM i)10078 extern void AdvancedAssemblyAlignmentEditor (IteM i)
10079 {
10080   BaseFormPtr        bfp;
10081   BioseqPtr   bsp;
10082   WindoW      w;
10083   GrouP       h, c;
10084   AssemblyAlignmentFormPtr frm;
10085   ButtoN                   b;
10086 
10087 #ifdef WIN_MAC
10088   bfp = currentFormDataPtr;
10089 #else
10090   bfp = GetObjectExtra (i);
10091 #endif
10092   if (bfp == NULL) return;
10093 
10094   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
10095   if (bsp == NULL) {
10096     Message (MSG_ERROR, "Must select single Bioseq!");
10097     return;
10098   }
10099 
10100   frm = (AssemblyAlignmentFormPtr) MemNew (sizeof (AssemblyAlignmentFormData));
10101   frm->bsp = bsp;
10102 
10103   w = FixedWindow (-50, -33, -10, -10, "Add Intervals to Assembly Alignment", StdCloseWindowProc);
10104   SetObjectExtra (w, frm, StdCleanupExtraProc);
10105   frm->form = (ForM) w;
10106 
10107   h = HiddenGroup (w, -1, 0, NULL);
10108   SetGroupSpacing (h, 10, 10);
10109 
10110   frm->dlg = CreateAssemblyAlignmentDialog(h);
10111 
10112   c = HiddenGroup (h, 3, 0, NULL);
10113   b = PushButton (c, "Accept", AcceptAssemblyAlignment);
10114   SetObjectExtra (b, frm, NULL);
10115   b = PushButton (c, "Check", CheckAssemblyAlignment);
10116   SetObjectExtra (b, frm, NULL);
10117   b = PushButton (c, "Cancel", StdCancelButtonProc);
10118 
10119   AlignObjects (ALIGN_CENTER, (HANDLE) frm->dlg, (HANDLE) c, NULL);
10120 
10121   Show (w);
10122   Update ();
10123 }
10124 
10125 typedef enum {
10126   eAssemblyIntervalInfo_NoAction = 0,
10127   eAssemblyIntervalInfo_Remove,
10128   eAssemblyIntervalInfo_Truncate_Left,
10129   eAssemblyIntervalInfo_Truncate_Right,
10130   eAssemblyIntervalInfo_Truncate_Both
10131 } EAssemblyIntervalInfoAction;
10132 
10133 
10134 typedef struct assemblyintervalinfo {
10135   SeqAlignPtr salp;
10136   Int4        prim_left;
10137   Int4        prim_right;
10138   Uint1       prim_strand;
10139   Int4        tpa_left;
10140   Int4        tpa_right;
10141   CharPtr     prim_id;
10142   ValNodePtr  conflict_list;
10143   EAssemblyIntervalInfoAction action;
10144 } AssemblyIntervalInfoData, PNTR AssemblyIntervalInfoPtr;
10145 
10146 typedef enum {
10147   eIntervalConflict_none,
10148   eIntervalConflict_a_contains_b,
10149   eIntervalConflict_a_contained_in_b,
10150   eIntervalConflict_a_overlaps_b_on_5,
10151   eIntervalConflict_a_overlaps_b_on_3
10152 } EIntervalConflict;
10153 
10154 
FindIntervalConflict(Int4 left1,Int4 right1,Int4 left2,Int4 right2,Int4 overlap)10155 static Int4 FindIntervalConflict (Int4 left1, Int4 right1, Int4 left2, Int4 right2, Int4 overlap)
10156 {
10157   if (right1 < left2 + overlap || left1 > right2 - overlap) {
10158     return eIntervalConflict_none;
10159   } else if (left1 <= left2 && right1 < right2 && right1 - left2  + 1> overlap) {
10160     return eIntervalConflict_a_overlaps_b_on_5;
10161   } else if (left1 > left2 && right1 >= right2 && right2 - left1  + 1> overlap) {
10162     return eIntervalConflict_a_overlaps_b_on_3;
10163   } else if (left1 <= left2 && right1 >= right2) {
10164     return eIntervalConflict_a_contains_b;
10165   } else if (left2 <= left1 && right2 >= right2) {
10166     return eIntervalConflict_a_contained_in_b;
10167   } else {
10168     Message (MSG_ERROR, "Conflict calculation failed");
10169     return eIntervalConflict_none;
10170   }
10171 }
10172 
10173 
10174 
10175 typedef struct intervalconflictinfo {
10176   AssemblyIntervalInfoPtr conflict_interval;
10177   EIntervalConflict prim_conflict;
10178   EIntervalConflict tpa_conflict;
10179 } IntervalConflictInfoData, PNTR IntervalConflictInfoPtr;
10180 
10181 
IntervalConflictInfoNew(AssemblyIntervalInfoPtr conflict_interval,EIntervalConflict prim_conflict,EIntervalConflict tpa_conflict)10182 static IntervalConflictInfoPtr IntervalConflictInfoNew (AssemblyIntervalInfoPtr conflict_interval, EIntervalConflict prim_conflict, EIntervalConflict tpa_conflict)
10183 {
10184   IntervalConflictInfoPtr ip;
10185 
10186   ip = (IntervalConflictInfoPtr) MemNew (sizeof (IntervalConflictInfoData));
10187   ip->conflict_interval = conflict_interval;
10188   ip->prim_conflict = prim_conflict;
10189   ip->tpa_conflict = tpa_conflict;
10190   return ip;
10191 }
10192 
10193 
IntervalConflictInfoFree(IntervalConflictInfoPtr ip)10194 static IntervalConflictInfoPtr IntervalConflictInfoFree (IntervalConflictInfoPtr ip)
10195 {
10196   if (ip != NULL) {
10197     ip = MemFree (ip);
10198   }
10199   return ip;
10200 }
10201 
10202 
IntervalConflictInfoListFree(ValNodePtr vnp)10203 static ValNodePtr IntervalConflictInfoListFree (ValNodePtr vnp)
10204 {
10205   ValNodePtr vnp_next;
10206 
10207   while (vnp != NULL) {
10208     vnp_next = vnp->next;
10209     vnp->data.ptrvalue = IntervalConflictInfoFree (vnp->data.ptrvalue);
10210     vnp->next = NULL;
10211     vnp = ValNodeFree (vnp);
10212     vnp = vnp_next;
10213   }
10214   return vnp;
10215 }
10216 
10217 
AssemblyIntervalInfoFree(AssemblyIntervalInfoPtr ip)10218 static AssemblyIntervalInfoPtr AssemblyIntervalInfoFree (AssemblyIntervalInfoPtr ip)
10219 {
10220   if (ip != NULL) {
10221     ip->prim_id = MemFree (ip->prim_id);
10222     ip->conflict_list = IntervalConflictInfoListFree (ip->conflict_list);
10223     ip = MemFree (ip);
10224   }
10225   return ip;
10226 }
10227 
10228 
AssemblyIntervalInfoListFree(ValNodePtr vnp)10229 static ValNodePtr AssemblyIntervalInfoListFree (ValNodePtr vnp)
10230 {
10231   ValNodePtr vnp_next;
10232 
10233   while (vnp != NULL) {
10234     vnp_next = vnp->next;
10235     vnp->data.ptrvalue = AssemblyIntervalInfoFree (vnp->data.ptrvalue);
10236     vnp->next = NULL;
10237     vnp = ValNodeFree (vnp);
10238     vnp = vnp_next;
10239   }
10240   return vnp;
10241 }
10242 
10243 
TruncateForConflictsOnLeft(AssemblyIntervalInfoPtr ai)10244 static void TruncateForConflictsOnLeft (AssemblyIntervalInfoPtr ai)
10245 {
10246   IntervalConflictInfoPtr ip;
10247   ValNodePtr vnp;
10248   Int4       prim_change, tpa_change;
10249 
10250   if (ai == NULL || ai->conflict_list == NULL) {
10251     return;
10252   }
10253 
10254   for (vnp = ai->conflict_list; vnp != NULL; vnp = vnp->next) {
10255     if (vnp->choice == 1) {
10256       ip = (IntervalConflictInfoPtr) vnp->data.ptrvalue;
10257       prim_change = 0;
10258       tpa_change = 0;
10259       if (ip->tpa_conflict == eIntervalConflict_a_overlaps_b_on_5) {
10260         tpa_change = ip->conflict_interval->tpa_right - ai->tpa_left;
10261         if (tpa_change > 0) {
10262           ai->tpa_left += tpa_change;
10263           if (ai->prim_strand == Seq_strand_minus) {
10264             ai->prim_right -= tpa_change;
10265           } else {
10266             ai->prim_left += tpa_change;
10267           }
10268         }
10269       }
10270       if (ip->prim_conflict == eIntervalConflict_a_overlaps_b_on_5) {
10271         prim_change = ip->conflict_interval->prim_right - ai->prim_left;
10272         if (prim_change > 0) {
10273           ai->prim_left += prim_change;
10274           if (ai->prim_strand == Seq_strand_minus) {
10275             ai->tpa_right -= prim_change;
10276           } else {
10277             ai->tpa_left += prim_change;
10278           }
10279         }
10280       }
10281       vnp->choice = 0;
10282     }
10283   }
10284 }
10285 
10286 
TruncateForConflictsOnRight(AssemblyIntervalInfoPtr ai)10287 static void TruncateForConflictsOnRight (AssemblyIntervalInfoPtr ai)
10288 {
10289   IntervalConflictInfoPtr ip;
10290   ValNodePtr vnp;
10291   Int4       prim_change, tpa_change;
10292 
10293   if (ai == NULL || ai->conflict_list == NULL) {
10294     return;
10295   }
10296 
10297   for (vnp = ai->conflict_list; vnp != NULL; vnp = vnp->next) {
10298     if (vnp->choice == 1) {
10299       ip = (IntervalConflictInfoPtr) vnp->data.ptrvalue;
10300       prim_change = 0;
10301       tpa_change = 0;
10302       if (ip->tpa_conflict == eIntervalConflict_a_overlaps_b_on_3) {
10303         tpa_change = ai->tpa_right - ip->conflict_interval->tpa_left;
10304         if (tpa_change > 0) {
10305           ai->tpa_right -= tpa_change;
10306           if (ai->prim_strand == Seq_strand_minus) {
10307             ai->prim_left += tpa_change;
10308           } else {
10309             ai->prim_right -= tpa_change;
10310           }
10311         }
10312       }
10313       if (ip->prim_conflict == eIntervalConflict_a_overlaps_b_on_3) {
10314         prim_change = ai->prim_right - ip->conflict_interval->prim_left;
10315         if (prim_change > 0) {
10316           ai->prim_right -= prim_change;
10317           if (ai->prim_strand == Seq_strand_minus) {
10318             ai->tpa_left += prim_change;
10319           } else {
10320             ai->tpa_right -= prim_change;
10321           }
10322         }
10323       }
10324       vnp->choice = 0;
10325     }
10326   }
10327 }
10328 
10329 
ReevaluateConflicts(AssemblyIntervalInfoPtr ip,Int4 overlap)10330 static void ReevaluateConflicts (AssemblyIntervalInfoPtr ip, Int4 overlap)
10331 {
10332   ValNodePtr vnp;
10333   IntervalConflictInfoPtr cp;
10334 
10335   if (ip == NULL) {
10336     return;
10337   }
10338 
10339   for (vnp = ip->conflict_list; vnp != NULL; vnp = vnp->next) {
10340     cp = vnp->data.ptrvalue;
10341     if (cp->conflict_interval->action == eAssemblyIntervalInfo_Remove) {
10342       vnp->choice = 0;
10343     } else if (FindIntervalConflict (ip->tpa_left, ip->tpa_right,
10344                                      cp->conflict_interval->tpa_left, cp->conflict_interval->tpa_right, overlap) == eIntervalConflict_none
10345                && FindIntervalConflict (ip->prim_left, ip->prim_right,
10346                                         cp->conflict_interval->tpa_left, cp->conflict_interval->tpa_right, overlap) == eIntervalConflict_none) {
10347       vnp->choice = 0;
10348     } else {
10349       vnp->choice = 1;
10350     }
10351   }
10352 }
10353 
10354 
RecalculateAssemblyIntervalInfoEndpoints(AssemblyIntervalInfoPtr ip,Int4 overlap)10355 static void RecalculateAssemblyIntervalInfoEndpoints (AssemblyIntervalInfoPtr ip, Int4 overlap)
10356 {
10357   IntervalConflictInfoPtr cp;
10358   ValNodePtr vnp;
10359 
10360   if (ip == NULL) {
10361     return;
10362   }
10363 
10364   /* calculate endpoints */
10365   AlnMgr2IndexSingleChildSeqAlign (ip->salp);
10366   ip->prim_strand = SeqAlignStrand (ip->salp, 2);
10367   AlnMgr2GetNthSeqRangeInSA (ip->salp, 1, &(ip->tpa_left), &(ip->tpa_right));
10368   AlnMgr2GetNthSeqRangeInSA (ip->salp, 2, &(ip->prim_left), &(ip->prim_right));
10369 
10370   /* apply changes for conflicts and actions */
10371   if (ip->action == eAssemblyIntervalInfo_Truncate_Left) {
10372     TruncateForConflictsOnLeft (ip);
10373   } else if (ip->action == eAssemblyIntervalInfo_Truncate_Right) {
10374     TruncateForConflictsOnRight (ip);
10375   } else if (ip->action == eAssemblyIntervalInfo_Truncate_Both) {
10376     TruncateForConflictsOnLeft (ip);
10377     TruncateForConflictsOnRight (ip);
10378   }
10379 
10380   ReevaluateConflicts (ip, overlap);
10381   for (vnp = ip->conflict_list; vnp != NULL; vnp = vnp->next) {
10382     cp = vnp->data.ptrvalue;
10383     ReevaluateConflicts (cp->conflict_interval, overlap);
10384   }
10385 }
10386 
10387 
AssemblyIntervalInfoNew(SeqAlignPtr salp,Int4 overlap)10388 static AssemblyIntervalInfoPtr AssemblyIntervalInfoNew (SeqAlignPtr salp, Int4 overlap)
10389 {
10390   AssemblyIntervalInfoPtr ip;
10391   Char        id_txt[255];
10392   SeqIdPtr    sip;
10393   BioseqPtr   bsp;
10394 
10395   if (salp == NULL) {
10396     return NULL;
10397   }
10398 
10399   ip = (AssemblyIntervalInfoPtr) MemNew (sizeof (AssemblyIntervalInfoData));
10400   ip->salp = salp;
10401   AlnMgr2IndexSingleChildSeqAlign (ip->salp);
10402 
10403   sip = AlnMgr2GetNthSeqIdPtr (salp, 2);
10404   bsp = BioseqLockById (sip);
10405   if (bsp != NULL) {
10406     sip = SeqIdFree (sip);
10407     sip = SeqIdDup (SeqIdFindBest (bsp->id, SEQID_GENBANK));
10408     BioseqUnlock (bsp);
10409   }
10410 
10411   SeqIdWrite (sip, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
10412   sip = SeqIdFree (sip);
10413 
10414   ip->prim_id = StringSave (id_txt);
10415   RecalculateAssemblyIntervalInfoEndpoints (ip, overlap);
10416   return ip;
10417 }
10418 
10419 
SummarizeAssemblyInterval(AssemblyIntervalInfoPtr ip)10420 static CharPtr SummarizeAssemblyInterval (AssemblyIntervalInfoPtr ip)
10421 {
10422   CharPtr summary = NULL;
10423   CharPtr fmt = "%d-%d %s %d-%d%s";
10424   Int4    len;
10425 
10426   if (ip == NULL) {
10427     return NULL;
10428   }
10429 
10430   len = StringLen (fmt) + StringLen (ip->prim_id) + 60;
10431   if (ip->prim_strand == Seq_strand_minus) {
10432     len += 3;
10433   }
10434   summary = (CharPtr) MemNew (sizeof (Char) + len);
10435   sprintf (summary, fmt, ip->tpa_left + 1, ip->tpa_right + 1,
10436                          ip->prim_id,
10437                          ip->prim_left + 1, ip->prim_right + 1,
10438                          ip->prim_strand == Seq_strand_minus ? "(c)" : "");
10439   return summary;
10440 }
10441 
10442 
SummarizeConflictList(ValNodePtr list)10443 static CharPtr SummarizeConflictList (ValNodePtr list)
10444 {
10445   CharPtr summary = NULL, str, conflict = "Conflict with ";
10446   ValNodePtr vnp, strings = NULL;
10447   IntervalConflictInfoPtr ip;
10448   Int4 len = 0;
10449 
10450   for (vnp = list; vnp != NULL; vnp = vnp->next) {
10451     if (vnp->choice == 1 && vnp->data.ptrvalue != NULL) {
10452       ip = (IntervalConflictInfoPtr) vnp->data.ptrvalue;
10453       str = SummarizeAssemblyInterval (ip->conflict_interval);
10454       ValNodeAddPointer (&strings, 0, str);
10455       len += StringLen (str) + 3;
10456     }
10457   }
10458   if (strings == NULL) {
10459     summary = StringSave ("No conflicts");
10460   } else {
10461     summary = (CharPtr) MemNew (sizeof (Char) * (StringLen (conflict) + len));
10462     StringCpy (summary, conflict);
10463     for (vnp = strings; vnp != NULL; vnp = vnp->next) {
10464       StringCat (summary, vnp->data.ptrvalue);
10465       if (vnp->next != NULL) {
10466         StringCat (summary, ", ");
10467       }
10468     }
10469     strings = ValNodeFreeData (strings);
10470   }
10471   return summary;
10472 }
10473 
10474 
RemoveConflictLists(ValNodePtr list)10475 static void RemoveConflictLists (ValNodePtr list)
10476 {
10477   AssemblyIntervalInfoPtr ip;
10478 
10479   while (list != NULL) {
10480     ip = (AssemblyIntervalInfoPtr) list->data.ptrvalue;
10481     ip->conflict_list = IntervalConflictInfoListFree (ip->conflict_list);
10482     list = list->next;
10483   }
10484 }
10485 
10486 
BuildConflictLists(ValNodePtr list,Int4 overlap)10487 static void BuildConflictLists (ValNodePtr list, Int4 overlap)
10488 {
10489   ValNodePtr vnp1, vnp2;
10490   AssemblyIntervalInfoPtr ip1, ip2;
10491   EIntervalConflict prim_conflict, tpa_conflict;
10492   IntervalConflictInfoPtr conflict;
10493 
10494   if (list == NULL || list->next == NULL) {
10495     return;
10496   }
10497 
10498   RemoveConflictLists (list);
10499 
10500   for (vnp1 = list; vnp1->next != NULL; vnp1 = vnp1->next) {
10501     ip1 = (AssemblyIntervalInfoPtr) vnp1->data.ptrvalue;
10502     for (vnp2 = vnp1->next; vnp2 != NULL; vnp2 = vnp2->next) {
10503       ip2 = (AssemblyIntervalInfoPtr) vnp2->data.ptrvalue;
10504       if (StringCmp (ip1->prim_id, ip2->prim_id) == 0) {
10505         tpa_conflict = FindIntervalConflict (ip1->tpa_left, ip1->tpa_right, ip2->tpa_left, ip2->tpa_right, overlap);
10506         prim_conflict = FindIntervalConflict (ip1->prim_left, ip1->prim_right, ip2->prim_left, ip2->prim_right, overlap);
10507         if (tpa_conflict != eIntervalConflict_none || prim_conflict != prim_conflict) {
10508           conflict = IntervalConflictInfoNew (ip2, prim_conflict, tpa_conflict);
10509           ValNodeAddPointer (&(ip1->conflict_list), 1, conflict);
10510         }
10511         tpa_conflict = FindIntervalConflict (ip2->tpa_left, ip2->tpa_right, ip1->tpa_left, ip1->tpa_right, overlap);
10512         prim_conflict = FindIntervalConflict (ip2->prim_left, ip2->prim_right, ip1->prim_left, ip1->prim_right, overlap);
10513         if (tpa_conflict != eIntervalConflict_none || prim_conflict != prim_conflict) {
10514           conflict = IntervalConflictInfoNew (ip1, prim_conflict, tpa_conflict);
10515           ValNodeAddPointer (&(ip2->conflict_list), 1, conflict);
10516         }
10517       }
10518     }
10519   }
10520 }
10521 
10522 
AssemblyIntervalInfoListFromSeqAlign(SeqAlignPtr salp,Int4 overlap)10523 static ValNodePtr AssemblyIntervalInfoListFromSeqAlign (SeqAlignPtr salp, Int4 overlap)
10524 {
10525   ValNodePtr list = NULL;
10526 
10527   while (salp != NULL) {
10528     ValNodeAddPointer (&list, 0, AssemblyIntervalInfoNew (salp, overlap));
10529     salp = salp->next;
10530   }
10531 
10532   BuildConflictLists (list, overlap);
10533   return list;
10534 }
10535 
10536 
10537 typedef struct assemblyalignmentintervalresolutiondlg {
10538   DIALOG_MESSAGE_BLOCK
10539   DialoG intervals_dialog;
10540   TexT   overlap;
10541   ValNodePtr list;
10542 } AssemblyAlignmentIntervalResolutionDlgData, PNTR AssemblyAlignmentIntervalResolutionDlgPtr;
10543 
10544 CharPtr assmbly_aln_int_res_labels [] = {
10545   "Action",
10546   "Alignment",
10547   "Conflicts With" };
10548 
10549 Uint2 assmbly_aln_int_res_types [] = {
10550   TAGLIST_POPUP, TAGLIST_PROMPT, TAGLIST_PROMPT
10551 };
10552 
10553 Uint2 assmbly_aln_int_res_widths [] = {
10554   10, 15, 30, 0
10555 };
10556 
ENUM_ALIST(assmbly_aln_int_res_action_alist)10557 ENUM_ALIST(assmbly_aln_int_res_action_alist)
10558   {"No change",  eAssemblyIntervalInfo_NoAction},
10559   {"Remove",     eAssemblyIntervalInfo_Remove},
10560   {"Truncate Left", eAssemblyIntervalInfo_Truncate_Left},
10561   {"Truncate Right", eAssemblyIntervalInfo_Truncate_Right},
10562   {"Truncate Both", eAssemblyIntervalInfo_Truncate_Both},
10563 END_ENUM_ALIST
10564 
10565 
10566 static EnumFieldAssocPtr assmbly_aln_int_res_alists[] = {
10567   assmbly_aln_int_res_action_alist, NULL, NULL
10568 };
10569 
10570 
SummarizeOneIntervalResolutionRow(AssemblyIntervalInfoPtr ip)10571 static CharPtr SummarizeOneIntervalResolutionRow (AssemblyIntervalInfoPtr ip)
10572 {
10573   CharPtr str, int_str, conf_str, fmt = "%d\t%s\t%s\n";
10574 
10575   if (ip == NULL) {
10576     return NULL;
10577   }
10578 
10579   int_str = SummarizeAssemblyInterval (ip);
10580   conf_str = SummarizeConflictList (ip->conflict_list);
10581   str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + 15 + StringLen (int_str) + StringLen (conf_str)));
10582   sprintf (str, fmt, ip->action, int_str, conf_str);
10583   int_str = MemFree (int_str);
10584   conf_str = MemFree (conf_str);
10585 
10586   return str;
10587 }
10588 
UpdateConflicts(Pointer userdata)10589 static void UpdateConflicts (Pointer userdata)
10590 {
10591   AssemblyAlignmentIntervalResolutionDlgPtr dlg;
10592   AssemblyIntervalInfoPtr ip;
10593   TagListPtr tlp;
10594   ValNodePtr vnp, vnp_t;
10595   Int4 action;
10596   Boolean any_change = FALSE;
10597   CharPtr str;
10598   Int4    overlap = 0;
10599 
10600   dlg = (AssemblyAlignmentIntervalResolutionDlgPtr) userdata;
10601 
10602   if (dlg == NULL) {
10603     return;
10604   }
10605 
10606   tlp = (TagListPtr) GetObjectExtra (dlg->intervals_dialog);
10607   if (tlp == NULL) {
10608     return;
10609   }
10610 
10611   if (!TextHasNoText (dlg->overlap)) {
10612     str = SaveStringFromText (dlg->overlap);
10613     overlap = atoi (str);
10614     str = MemFree (str);
10615     if (overlap < 0) {
10616       overlap = 0;
10617     }
10618   }
10619 
10620   /* now update conflict lists */
10621   for (vnp = dlg->list, vnp_t = tlp->vnp; vnp != NULL && tlp->vnp != NULL; vnp = vnp->next, vnp_t = vnp_t->next) {
10622     ip = (AssemblyIntervalInfoPtr) vnp->data.ptrvalue;
10623     str = ExtractTagListColumn ((CharPtr) vnp_t->data.ptrvalue, 0);
10624     action = atoi (str);
10625     str = MemFree (str);
10626     if (action != ip->action) {
10627       ip->action = (EAssemblyIntervalInfoAction) action;
10628       RecalculateAssemblyIntervalInfoEndpoints (ip, overlap);
10629       any_change = TRUE;
10630     }
10631   }
10632 
10633   if (any_change) {
10634     for (vnp = dlg->list, vnp_t = tlp->vnp; vnp != NULL && tlp->vnp != NULL; vnp = vnp->next, vnp_t = vnp_t->next) {
10635       ip = (AssemblyIntervalInfoPtr) vnp->data.ptrvalue;
10636       vnp_t->data.ptrvalue = MemFree (vnp_t->data.ptrvalue);
10637       vnp_t->data.ptrvalue = SummarizeOneIntervalResolutionRow (ip);
10638     }
10639 
10640     /* update dialog */
10641     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
10642     SendMessageToDialog (tlp->dialog, VIB_MSG_ENTER);
10643   }
10644 }
10645 
10646 static TaglistCallback assmbly_int_res_callback_list[3] =
10647  { UpdateConflicts, UpdateConflicts, UpdateConflicts };
10648 
SeqAlignToAssemblyAlignmentIntervalResolutionDialog(DialoG d,Pointer data)10649 static void SeqAlignToAssemblyAlignmentIntervalResolutionDialog (DialoG d, Pointer data)
10650 {
10651   AssemblyAlignmentIntervalResolutionDlgPtr dlg;
10652   SeqAlignPtr salp;
10653   ValNodePtr  vnp;
10654   CharPtr     str;
10655   Int4        overlap = 0;
10656   TagListPtr  tlp;
10657 
10658   dlg = (AssemblyAlignmentIntervalResolutionDlgPtr) GetObjectExtra (d);
10659   salp = (SeqAlignPtr) data;
10660   if (dlg == NULL) {
10661     return;
10662   }
10663   tlp = (TagListPtr) GetObjectExtra (dlg->intervals_dialog);
10664   if (tlp == NULL) {
10665     return;
10666   }
10667   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
10668   tlp->vnp = ValNodeFreeData (tlp->vnp);
10669 
10670   if (!TextHasNoText (dlg->overlap)) {
10671     str = SaveStringFromText (dlg->overlap);
10672     overlap = atoi (str);
10673     str = MemFree (str);
10674     if (overlap < 0) {
10675       overlap = 0;
10676     }
10677   }
10678 
10679   dlg->list = AssemblyIntervalInfoListFree (dlg->list);
10680   dlg->list = AssemblyIntervalInfoListFromSeqAlign (salp, overlap);
10681 
10682   for (vnp = dlg->list; vnp != NULL; vnp = vnp->next) {
10683     str = SummarizeOneIntervalResolutionRow (vnp->data.ptrvalue);
10684     ValNodeAddPointer (&(tlp->vnp), 0, str);
10685   }
10686 
10687   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
10688   tlp->max = MAX ((Int2) 0, (Int2) (ValNodeLen (tlp->vnp) - tlp->rows));
10689   CorrectBarMax (tlp->bar, tlp->max);
10690   CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
10691   if (tlp->max > 0) {
10692     SafeShow (tlp->bar);
10693   } else {
10694     SafeHide (tlp->bar);
10695   }
10696   SendMessageToDialog (tlp->dialog, VIB_MSG_ENTER);
10697 
10698 }
10699 
10700 
AssemblyAlignmentIntervalResolutionDialogToSeqAlign(DialoG d)10701 static Pointer AssemblyAlignmentIntervalResolutionDialogToSeqAlign (DialoG d)
10702 {
10703   AssemblyAlignmentIntervalResolutionDlgPtr dlg;
10704   AssemblyIntervalInfoPtr ai;
10705   SeqAlignPtr salp_list = NULL, salp_prev = NULL, salp;
10706   ValNodePtr vnp;
10707 
10708   dlg = (AssemblyAlignmentIntervalResolutionDlgPtr) GetObjectExtra (d);
10709   if (dlg == NULL) {
10710     return NULL;
10711   }
10712 
10713   for (vnp = dlg->list; vnp != NULL; vnp = vnp->next) {
10714     ai = vnp->data.ptrvalue;
10715     if (ai->action != eAssemblyIntervalInfo_Remove) {
10716       salp = (SeqAlignPtr) AsnIoMemCopy (ai->salp, (AsnReadFunc) SeqAlignAsnRead, (AsnWriteFunc) SeqAlignAsnWrite);
10717       /* TODO: truncate alignments */
10718 
10719       /* add to list */
10720       if (salp_prev == NULL) {
10721         salp_list = salp;
10722       } else {
10723         salp_prev->next = salp;
10724       }
10725       salp_prev = salp;
10726     }
10727   }
10728 
10729   return (Pointer) salp_list;
10730 }
10731 
10732 
ChangeAssemblyAlignmentIntervalResolutionOverlap(TexT t)10733 static void ChangeAssemblyAlignmentIntervalResolutionOverlap (TexT t)
10734 {
10735   AssemblyAlignmentIntervalResolutionDlgPtr  dlg;
10736   AssemblyIntervalInfoPtr ip;
10737   TagListPtr tlp;
10738   ValNodePtr vnp, vnp_t;
10739   CharPtr    str;
10740   Int4       overlap = 0;
10741 
10742   dlg = (AssemblyAlignmentIntervalResolutionDlgPtr) GetObjectExtra (t);
10743   if (dlg == NULL) {
10744     return;
10745   }
10746 
10747   tlp = (TagListPtr) GetObjectExtra (dlg->intervals_dialog);
10748   if (tlp == NULL) {
10749     return;
10750   }
10751 
10752   if (!TextHasNoText (dlg->overlap)) {
10753     str = SaveStringFromText (dlg->overlap);
10754     overlap = atoi (str);
10755     str = MemFree (str);
10756     if (overlap < 0) {
10757       overlap = 0;
10758     }
10759   }
10760 
10761   BuildConflictLists (dlg->list, overlap);
10762 
10763   /* change text */
10764   for (vnp = dlg->list, vnp_t = tlp->vnp; vnp != NULL && tlp->vnp != NULL; vnp = vnp->next, vnp_t = vnp_t->next) {
10765     ip = (AssemblyIntervalInfoPtr) vnp->data.ptrvalue;
10766     RecalculateAssemblyIntervalInfoEndpoints (ip, overlap);
10767     vnp_t->data.ptrvalue = MemFree (vnp_t->data.ptrvalue);
10768     vnp_t->data.ptrvalue = SummarizeOneIntervalResolutionRow (ip);
10769   }
10770 
10771   /* update dialog */
10772   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
10773   SendMessageToDialog (tlp->dialog, VIB_MSG_ENTER);
10774 
10775 }
10776 
10777 
CleanupAssemblyAlignmentIntervalResolutionDialog(GraphiC g,VoidPtr data)10778 static void CleanupAssemblyAlignmentIntervalResolutionDialog (GraphiC g, VoidPtr data)
10779 
10780 {
10781   AssemblyAlignmentIntervalResolutionDlgPtr  dlg;
10782 
10783   dlg = (AssemblyAlignmentIntervalResolutionDlgPtr) data;
10784   if (dlg != NULL) {
10785     dlg->list =  AssemblyIntervalInfoListFree (dlg->list);
10786     dlg = MemFree (dlg);
10787   }
10788 }
10789 
10790 
CreateAssemblyAlignmentIntervalResolutionDialog(GrouP g)10791 static DialoG CreateAssemblyAlignmentIntervalResolutionDialog (GrouP g)
10792 
10793 {
10794   AssemblyAlignmentIntervalResolutionDlgPtr dlg;
10795   GrouP                   p;
10796   GrouP                   x, y, z;
10797   Int4                    i;
10798   Int4                    num_columns = sizeof (assmbly_aln_int_res_labels) / sizeof (CharPtr);
10799 
10800   p = HiddenGroup (g, -1, 0, NULL);
10801   SetGroupSpacing (p, 10, 10);
10802 
10803   dlg = (AssemblyAlignmentIntervalResolutionDlgPtr) MemNew (sizeof (AssemblyAlignmentIntervalResolutionDlgData));
10804   if (dlg == NULL) return NULL;
10805 
10806   SetObjectExtra (p, dlg, CleanupAssemblyAlignmentIntervalResolutionDialog);
10807   dlg->dialog = (DialoG) p;
10808 
10809   dlg->todialog = SeqAlignToAssemblyAlignmentIntervalResolutionDialog;
10810   dlg->fromdialog = AssemblyAlignmentIntervalResolutionDialogToSeqAlign;
10811 
10812   z = HiddenGroup (p, 2, 0, NULL);
10813   StaticPrompt (z, "Allowable Overlap", 0, 0, programFont, 'r');
10814   dlg->overlap = DialogText (z, "5", 5, ChangeAssemblyAlignmentIntervalResolutionOverlap);
10815   SetObjectExtra (dlg->overlap, dlg, NULL);
10816 
10817   x = HiddenGroup (p, 0, 2, NULL);
10818   y = HiddenGroup (x, num_columns, 0, NULL);
10819   for (i = 0; i < num_columns; i++) {
10820       StaticPrompt (y, assmbly_aln_int_res_labels[i], assmbly_aln_int_res_widths[i] * stdCharWidth, 0, programFont, 'l');
10821   }
10822   dlg->intervals_dialog = CreateTagListDialogExEx (x, 6, num_columns, -1, assmbly_aln_int_res_types,
10823                                                    assmbly_aln_int_res_widths, assmbly_aln_int_res_alists,
10824                                                    TRUE, TRUE, NULL, NULL,
10825                                                    assmbly_int_res_callback_list, dlg, FALSE);
10826 
10827   AlignObjects (ALIGN_CENTER, (HANDLE) z, (HANDLE) x, NULL);
10828   return (DialoG) p;
10829 }
10830 
10831 
10832 typedef struct assemblyalignmentintervalresolutionfrm {
10833   FORM_MESSAGE_BLOCK
10834   DialoG dlg;
10835 
10836   BioseqPtr bsp;
10837 } AssemblyAlignmentIntervalResolutionFrmData, PNTR AssemblyAlignmentIntervalResolutionFrmPtr;
10838 
10839 
AcceptAssemblyAlignmentIntervalResolution(ButtoN b)10840 static void AcceptAssemblyAlignmentIntervalResolution (ButtoN b)
10841 {
10842   AssemblyAlignmentIntervalResolutionFrmPtr frm;
10843   SeqAlignPtr new_assem, salp, salp_next;
10844 
10845   frm = (AssemblyAlignmentIntervalResolutionFrmPtr) GetObjectExtra (b);
10846   if (frm == NULL) {
10847     return;
10848   }
10849 
10850   /* TODO: check for problems before accepting */
10851 
10852   new_assem = DialogToPointer (frm->dlg);
10853   if (new_assem == NULL) {
10854     Message (MSG_ERROR, "No intervals left in assembly!");
10855     return;
10856   }
10857 
10858   /* remove old assembly */
10859   salp = frm->bsp->hist->assembly;
10860   frm->bsp->hist->assembly = NULL;
10861   while (salp != NULL) {
10862     salp_next = salp->next;
10863     salp->next = NULL;
10864     salp = SeqAlignFree (salp);
10865     salp = salp_next;
10866   }
10867 
10868   /* assign new assembly */
10869   frm->bsp->hist->assembly = new_assem;
10870 
10871   ObjMgrSetDirtyFlag (frm->bsp->idx.entityID, TRUE);
10872   ObjMgrSendMsg (OM_MSG_UPDATE, frm->bsp->idx.entityID, 0, 0);
10873   Remove (frm->form);
10874 }
10875 
10876 
AssemblyAlignmentIntervalResolution(IteM i)10877 extern void AssemblyAlignmentIntervalResolution (IteM i)
10878 {
10879   BaseFormPtr        bfp;
10880   BioseqPtr   bsp;
10881   WindoW      w;
10882   GrouP       h, c;
10883   AssemblyAlignmentIntervalResolutionFrmPtr frm;
10884   ButtoN                   b;
10885 
10886 #ifdef WIN_MAC
10887   bfp = currentFormDataPtr;
10888 #else
10889   bfp = GetObjectExtra (i);
10890 #endif
10891   if (bfp == NULL) return;
10892 
10893   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
10894   if (bsp == NULL) {
10895     Message (MSG_ERROR, "Must select single Bioseq!");
10896     return;
10897   }
10898   if (bsp->hist == NULL || bsp->hist->assembly == NULL) {
10899     Message (MSG_ERROR, "No assembly alignment!");
10900     return;
10901   }
10902   frm = (AssemblyAlignmentIntervalResolutionFrmPtr) MemNew (sizeof (AssemblyAlignmentIntervalResolutionFrmData));
10903   frm->bsp = bsp;
10904 
10905   w = FixedWindow (-50, -33, -10, -10, "Resolve Assembly Alignment Intervals", StdCloseWindowProc);
10906   SetObjectExtra (w, frm, StdCleanupExtraProc);
10907   frm->form = (ForM) w;
10908 
10909   h = HiddenGroup (w, -1, 0, NULL);
10910   SetGroupSpacing (h, 10, 10);
10911 
10912   frm->dlg = CreateAssemblyAlignmentIntervalResolutionDialog(h);
10913   PointerToDialog (frm->dlg, bsp->hist->assembly);
10914 
10915   c = HiddenGroup (h, 3, 0, NULL);
10916   b = PushButton (c, "Accept", AcceptAssemblyAlignmentIntervalResolution);
10917   SetObjectExtra (b, frm, NULL);
10918 /*  b = PushButton (c, "Check", CheckAssemblyAlignmentIntervalResolution);
10919   SetObjectExtra (b, frm, NULL); */
10920   b = PushButton (c, "Cancel", StdCancelButtonProc);
10921 
10922   AlignObjects (ALIGN_CENTER, (HANDLE) frm->dlg, (HANDLE) c, NULL);
10923   Show (w);
10924   Update ();
10925 }
10926 
10927 
10928 
10929 typedef struct historyformdata {
10930   FEATURE_FORM_BLOCK
10931 
10932   BioseqPtr      bsp;
10933   DialoG         replace_date;
10934   DialoG         replace_ids;
10935   ButtoN         secondary_on_part;
10936   DialoG         replaced_by_date;
10937   DialoG         replaced_by_ids;
10938   ButtoN         deleted;
10939   DialoG         deleted_date;
10940 } HistoryFormData, PNTR HistoryFormPtr;
10941 
VisStrDialogToSeqIdSet(DialoG d)10942 static SeqIdPtr VisStrDialogToSeqIdSet (DialoG d)
10943 
10944 {
10945   long        gi;
10946   SeqIdPtr    head = NULL;
10947   ValNodePtr  list;
10948   SeqIdPtr    sip;
10949   CharPtr     str;
10950   ValNodePtr  vnp;
10951 
10952   if (d == NULL) return NULL;
10953   list = DialogToPointer (d);
10954   for (vnp = list; vnp != NULL; vnp = vnp->next) {
10955     str = (CharPtr) vnp->data.ptrvalue;
10956     if (str != NULL) {
10957       if (sscanf (str, "%ld", &gi)) {
10958         ValNodeAddInt (&head, SEQID_GI, (Int4) gi);
10959       } else {
10960         sip = SeqIdFromAccessionDotVersion (str);
10961         if (sip != NULL) {
10962           ValNodeLink (&head, sip);
10963         }
10964       }
10965     }
10966   }
10967   ValNodeFreeData (list);
10968   return head;
10969 }
10970 
SortByName(VoidPtr ptr1,VoidPtr ptr2)10971 static int LIBCALLBACK SortByName (VoidPtr ptr1, VoidPtr ptr2)
10972 
10973 {
10974   CharPtr     str1;
10975   CharPtr     str2;
10976   ValNodePtr  vnp1;
10977   ValNodePtr  vnp2;
10978 
10979   if (ptr1 != NULL && ptr2 != NULL) {
10980     vnp1 = *((ValNodePtr PNTR) ptr1);
10981     vnp2 = *((ValNodePtr PNTR) ptr2);
10982     if (vnp1 != NULL && vnp2 != NULL) {
10983       str1 = (CharPtr) vnp1->data.ptrvalue;
10984       str2 = (CharPtr) vnp2->data.ptrvalue;
10985       if (str1 != NULL && str2 != NULL) {
10986         return StringICmp (str1, str2);
10987       } else {
10988         return 0;
10989       }
10990     } else {
10991       return 0;
10992     }
10993   } else {
10994     return 0;
10995   }
10996 }
10997 
GetStringsForSeqIDs(SeqIdPtr sip)10998 static ValNodePtr GetStringsForSeqIDs (SeqIdPtr sip)
10999 
11000 {
11001   Char          buf [40];
11002   Int4
11003         gi;
11004   ValNodePtr    head = NULL;
11005   TextSeqIdPtr  tsip;
11006 
11007   if (sip == NULL) return NULL;
11008   while (sip != NULL) {
11009     buf [0] = '\0';
11010     switch (sip->choice) {
11011       case SEQID_GENBANK :
11012       case SEQID_EMBL :
11013       case SEQID_DDBJ :
11014       case SEQID_OTHER :
11015       case SEQID_TPG :
11016       case SEQID_TPE :
11017       case SEQID_TPD :
11018 
11019         tsip = (TextSeqIdPtr) sip->data.ptrvalue;
11020         if (tsip != NULL && (! StringHasNoText (tsip->accession))) {
11021           StringNCpy_0 (buf, tsip->accession, sizeof (buf));
11022         }
11023         break;
11024 
11025       case SEQID_GI :
11026         gi = sip->data.intvalue;
11027         if (gi > 0) {
11028           sprintf (buf, "%ld", (long) gi);
11029         }
11030         break;
11031       default :
11032         break;
11033     }
11034     if (! StringHasNoText (buf)) {
11035       ValNodeCopyStr (&head, 0, buf);
11036     }
11037     sip = sip->next;
11038   }
11039   return head;
11040 }
11041 
AddGenBankBlockToBioseq(BioseqPtr bsp,ValNodePtr head1,ValNodePtr head2)11042 static void AddGenBankBlockToBioseq (BioseqPtr bsp, ValNodePtr head1, ValNodePtr head2)
11043 
11044 {
11045   GBBlockPtr       gbp = NULL;
11046   CharPtr          last = NULL;
11047   ValNodePtr       next;
11048   ValNodePtr PNTR  prev;
11049   ValNodePtr       sdp;
11050   SeqEntryPtr      sep;
11051   CharPtr          str1, str2;
11052   ValNodePtr       vnp, vnp1, vnp2;
11053 
11054   sdp = BioseqGetSeqDescr (bsp, Seq_descr_genbank, NULL);
11055   if (sdp != NULL) {
11056     gbp = (GBBlockPtr) sdp->data.ptrvalue;
11057     if (gbp != NULL) {
11058       for (vnp1 = head1; vnp1 != NULL; vnp1 = vnp1->next) {
11059         str1 = (CharPtr) vnp1->data.ptrvalue;
11060         if (str1 != NULL) {
11061           for (vnp2 = gbp->extra_accessions; vnp2 != NULL; vnp2 = vnp2->next) {
11062             str2 = (CharPtr) vnp2->data.ptrvalue;
11063             if (StringICmp (str1, str2) == 0) {
11064               vnp2->data.ptrvalue = MemFree (vnp2->data.ptrvalue);
11065             }
11066           }
11067         }
11068       }
11069     }
11070   }
11071   if (sdp == NULL) {
11072     sep = SeqMgrGetSeqEntryForData (bsp);
11073     sdp = CreateNewDescriptor (sep, Seq_descr_genbank);
11074     if (sdp != NULL) {
11075       sdp->data.ptrvalue = GBBlockNew ();
11076     }
11077   }
11078   if (sdp != NULL) {
11079     gbp = (GBBlockPtr) sdp->data.ptrvalue;
11080     if (gbp != NULL) {
11081       while (head2 != NULL) {
11082         ValNodeCopyStr (&(gbp->extra_accessions), 0, (CharPtr) head2->data.ptrvalue);
11083         head2 = head2->next;
11084       }
11085       /*
11086       ValNodeLink (&(gbp->extra_accessions), head2);
11087       head2 = NULL;
11088       */
11089       gbp->extra_accessions = SortValNode (gbp->extra_accessions, SortByName);
11090       prev = &(gbp->extra_accessions);
11091       vnp = gbp->extra_accessions;
11092       last = NULL;
11093       while (vnp != NULL) {
11094         next = vnp->next;
11095         str2 = (CharPtr) vnp->data.ptrvalue;
11096         if (str2 == NULL || StringHasNoText (str2) || StringICmp (last, str2) == 0) {
11097           *prev = next;
11098           vnp->next = NULL;
11099           MemFree (vnp);
11100           vnp = next;
11101         } else {
11102           last = str2;
11103           prev = &(vnp->next);
11104           vnp = next;
11105         }
11106       }
11107     }
11108   }
11109 
11110 }
11111 
DoChangeHistory(ButtoN b)11112 static void DoChangeHistory (ButtoN b)
11113 
11114 {
11115   MsgAnswer       ans;
11116   BioseqPtr       bsp;
11117   ValNodePtr      head1 = NULL, head2 = NULL;
11118   HistoryFormPtr  hfp;
11119   SeqHistPtr      hist;
11120   BioseqPtr       pbsp;
11121   SeqEntryPtr     sep;
11122   SeqLocPtr       slp;
11123   CharPtr         str1, str2;
11124   ValNodePtr      vnp1, vnp2;
11125 
11126   hfp = (HistoryFormPtr) GetObjectExtra (b);
11127   if (hfp == NULL) return;
11128   ans = Message (MSG_OKC, "Are you sure you want to edit the history?");
11129   if (ans == ANS_CANCEL) {
11130     return;
11131   }
11132   Hide (hfp->form);
11133   Update ();
11134   bsp = hfp->bsp;
11135   hist = bsp->hist;
11136   if (hist == NULL) {
11137     hist = SeqHistNew ();
11138     bsp->hist = hist;
11139   }
11140   if (hist != NULL) {
11141 
11142     hist->replace_date = DateFree (hist->replace_date);
11143     hist->replace_date = DialogToPointer (hfp->replace_date);
11144     head1 = GetStringsForSeqIDs (hist->replace_ids);
11145     hist->replace_ids = SeqIdSetFree (hist->replace_ids);
11146     hist->replace_ids = VisStrDialogToSeqIdSet (hfp->replace_ids);
11147     head2 = GetStringsForSeqIDs (hist->replace_ids);
11148 
11149     hist->replaced_by_date = DateFree (hist->replaced_by_date);
11150     hist->replaced_by_date = DialogToPointer (hfp->replaced_by_date);
11151     hist->replaced_by_ids = SeqIdSetFree (hist->replaced_by_ids);
11152     hist->replaced_by_ids = VisStrDialogToSeqIdSet (hfp->replaced_by_ids);
11153 
11154     hist->deleted = GetStatus (hfp->deleted);
11155     hist->deleted_date = DateFree (hist->deleted_date);
11156     hist->deleted_date = DialogToPointer (hfp->deleted_date);
11157   }
11158 
11159   if (hist != NULL && hist->assembly == NULL &&
11160       hist->replace_date == NULL && hist->replace_ids == NULL &&
11161       hist->replaced_by_date == NULL && hist->replaced_by_ids == NULL &&
11162       (! hist->deleted) && hist->deleted_date == NULL) {
11163     bsp->hist = SeqHistFree (bsp->hist);
11164   }
11165 
11166   head1 = SortValNode (head1, SortByName);
11167   head2 = SortValNode (head2, SortByName);
11168   for (vnp1 = head1; vnp1 != NULL; vnp1 = vnp1->next) {
11169     str1 = (CharPtr) vnp1->data.ptrvalue;
11170     for (vnp2 = head2; vnp2 != NULL; vnp2 = vnp2->next) {
11171       str2 = (CharPtr) vnp2->data.ptrvalue;
11172       if (StringICmp (str1, str2) == 0) {
11173         vnp1->data.ptrvalue = MemFree (vnp1->data.ptrvalue);
11174       }
11175     }
11176   }
11177 
11178   AddGenBankBlockToBioseq (bsp, head1, head2);
11179 
11180   if (GetStatus (hfp->secondary_on_part)) {
11181     if (bsp->repr == Seq_repr_seg) {
11182       for (slp = (SeqLocPtr) bsp->seq_ext; slp != NULL; slp = slp->next) {
11183         pbsp = BioseqFind (SeqLocId (slp));
11184         if (pbsp != NULL) {
11185           AddGenBankBlockToBioseq (pbsp, head1, head2);
11186         }
11187       }
11188     }
11189   }
11190 
11191   ValNodeFreeData (head1);
11192   ValNodeFreeData (head2);
11193 
11194   sep = GetTopSeqEntryForEntityID (hfp->input_entityID);
11195   EntryCheckGBBlock (sep);
11196 
11197   Update ();
11198   ObjMgrSetDirtyFlag (hfp->input_entityID, TRUE);
11199   ObjMgrSendMsg (OM_MSG_UPDATE, hfp->input_entityID, 0, 0);
11200   ObjMgrDeSelect (0, 0, 0, 0, NULL);
11201   Remove (hfp->form);
11202 }
11203 
SeqIdSetToVisStrDialog(DialoG d,SeqIdPtr sip)11204 static void SeqIdSetToVisStrDialog (DialoG d, SeqIdPtr sip)
11205 
11206 {
11207   ValNodePtr  head = NULL;
11208 
11209   if (d == NULL || sip == NULL) return;
11210   head = GetStringsForSeqIDs (sip);
11211   PointerToDialog (d, head);
11212   ValNodeFreeData (head);
11213 }
11214 
HistoryMessageProc(ForM f,Int2 mssg)11215 static void HistoryMessageProc (ForM f, Int2 mssg)
11216 
11217 {
11218   HistoryFormPtr  hfp;
11219 
11220   hfp = (HistoryFormPtr) GetObjectExtra (f);
11221   if (hfp != NULL) {
11222     if (hfp->appmessage != NULL) {
11223       hfp->appmessage (f, mssg);
11224     }
11225   }
11226 }
11227 
CleanupHistoryPage(GraphiC g,VoidPtr data)11228 static void CleanupHistoryPage (GraphiC g, VoidPtr data)
11229 
11230 {
11231   HistoryFormPtr  hfp;
11232 
11233   hfp = (HistoryFormPtr) data;
11234   if (hfp != NULL) {
11235   }
11236   StdCleanupFormProc (g, data);
11237 }
11238 
EditSequenceHistory(IteM i)11239 extern void EditSequenceHistory (IteM i)
11240 
11241 {
11242   ButtoN             b;
11243   BaseFormPtr        bfp;
11244   BioseqPtr          bsp;
11245   GrouP              c;
11246   GrouP              g;
11247   GrouP              h;
11248   HistoryFormPtr     hfp;
11249   SeqHistPtr         hist;
11250   GrouP              j;
11251   GrouP              k;
11252   PrompT             ppt1, ppt2, ppt3;
11253   SeqEntryPtr        sep;
11254   StdEditorProcsPtr  sepp;
11255   WindoW             w;
11256 
11257 #ifdef WIN_MAC
11258   bfp = currentFormDataPtr;
11259 #else
11260   bfp = GetObjectExtra (i);
11261 #endif
11262   if (bfp == NULL) return;
11263   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
11264   if (sep == NULL) return;
11265   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
11266   if (bsp == NULL) return;
11267   hist = bsp->hist;
11268 
11269   hfp = (HistoryFormPtr) MemNew (sizeof (HistoryFormData));
11270   if (hfp == NULL) return;
11271   w = FixedWindow (-50, -33, -10, -10, "Sequence History", StdCloseWindowProc);
11272   SetObjectExtra (w, hfp, CleanupHistoryPage);
11273   hfp->form = (ForM) w;
11274   hfp->formmessage = HistoryMessageProc;
11275 
11276   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
11277   if (sepp != NULL) {
11278     SetActivate (w, sepp->activateForm);
11279     hfp->appmessage = sepp->handleMessages;
11280   }
11281 
11282   hfp->input_entityID = bfp->input_entityID;
11283   hfp->input_itemID = bfp->input_itemID;
11284   hfp->input_itemtype = bfp->input_itemtype;
11285 
11286   hfp->bsp = bsp;
11287 
11288   h = HiddenGroup (w, -1, 0, NULL);
11289   SetGroupSpacing (h, 10, 10);
11290 
11291   ppt1 = StaticPrompt (h, "Replaces", 0, 0, systemFont, 'c');
11292 
11293   g = HiddenGroup (h, -1, 0, NULL);
11294   hfp->replace_ids = CreateVisibleStringDialog (g, 4, -1, 10);
11295   hfp->secondary_on_part = CheckBox (g, "Secondary on Parts", NULL);
11296   hfp->replace_date = CreateDateDialog (g, NULL);
11297   AlignObjects (ALIGN_CENTER, (HANDLE) hfp->replace_ids, (HANDLE) hfp->secondary_on_part, (HANDLE) hfp->replace_date, NULL);
11298 
11299   ppt2 = StaticPrompt (h, "Replaced By", 0, 0, systemFont, 'c');
11300 
11301   j = HiddenGroup (h, -1, 0, NULL);
11302   hfp->replaced_by_ids = CreateVisibleStringDialog (j, 4, -1, 10);
11303   hfp->replaced_by_date = CreateDateDialog (j, NULL);
11304   AlignObjects (ALIGN_CENTER, (HANDLE) hfp->replaced_by_ids, (HANDLE) hfp->replaced_by_date, NULL);
11305 
11306   ppt3 = StaticPrompt (h, "Status", 0, 0, systemFont, 'c');
11307 
11308   k = HiddenGroup (h, -1, 0, NULL);
11309   hfp->deleted = CheckBox (k, "Deleted", NULL);
11310   hfp->deleted_date = CreateDateDialog (k, NULL);
11311   AlignObjects (ALIGN_CENTER, (HANDLE) hfp->deleted, (HANDLE) hfp->deleted_date, NULL);
11312 
11313   c = HiddenGroup (h, 4, 0, NULL);
11314   b = DefaultButton (c, "Accept", DoChangeHistory);
11315   SetObjectExtra (b, hfp, NULL);
11316   PushButton (c, "Cancel", StdCancelButtonProc);
11317 
11318   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) j, (HANDLE) k, (HANDLE) c,
11319                 (HANDLE) ppt1, (HANDLE) ppt2, (HANDLE) ppt3, NULL);
11320   RealizeWindow (w);
11321 
11322   if (bsp->repr != Seq_repr_seg) {
11323     Disable (hfp->secondary_on_part);
11324   } else {
11325     SetStatus (hfp->secondary_on_part, TRUE);
11326   }
11327 
11328   if (hist != NULL) {
11329     PointerToDialog (hfp->replace_date, hist->replace_date);
11330     SeqIdSetToVisStrDialog (hfp->replace_ids, hist->replace_ids);
11331     PointerToDialog (hfp->replaced_by_date, hist->replaced_by_date);
11332     SeqIdSetToVisStrDialog (hfp->replaced_by_ids, hist->replaced_by_ids);
11333     PointerToDialog (hfp->deleted_date, hist->deleted_date);
11334     SetStatus (hfp->deleted, hist->deleted);
11335   }
11336 
11337   Show (w);
11338   Update ();
11339 }
11340 
11341 
11342 typedef struct nw {
11343   Int4 score;
11344   Int4 traceback_pos;
11345 } NWData, PNTR NWPtr;
11346 
11347 
SegmentsNeededForAlignment(CharPtr buf1,CharPtr buf2)11348 static Int4 SegmentsNeededForAlignment (CharPtr buf1, CharPtr buf2)
11349 {
11350   CharPtr cp1, cp2;
11351   Boolean gap1, gap2, change = FALSE;
11352   Int4    num_segs = 1;
11353 
11354   cp1 = buf1;
11355   cp2 = buf2;
11356   if (*cp1 == '-') {
11357     gap1 = TRUE;
11358   } else {
11359     gap1 = FALSE;
11360   }
11361   cp1++;
11362   if (*cp2 == '-') {
11363     gap2 = TRUE;
11364   } else {
11365     gap2 = FALSE;
11366   }
11367   cp2++;
11368   while (*cp1 != 0 && *cp2 != 0) {
11369     change = FALSE;
11370     if (*cp1 == '-') {
11371       if (!gap1) {
11372         gap1 = TRUE;
11373         change = TRUE;
11374       }
11375     } else if (gap1) {
11376       gap1 = FALSE;
11377       change = TRUE;
11378     }
11379     if (*cp2 == '-') {
11380       if (!gap2) {
11381         gap2 = TRUE;
11382         change = TRUE;
11383       }
11384     } else if (gap2) {
11385       gap2 = FALSE;
11386       change = TRUE;
11387     }
11388     if (change) {
11389       num_segs ++;
11390     }
11391     cp1++;
11392     cp2++;
11393   }
11394   return num_segs;
11395 }
11396 
11397 static void
FillInStartsAndLensForAlignment(DenseSegPtr dsp,CharPtr buf1,CharPtr buf2)11398 FillInStartsAndLensForAlignment
11399 (DenseSegPtr dsp,
11400  CharPtr     buf1,
11401  CharPtr     buf2)
11402 {
11403   CharPtr cp1, cp2;
11404   Boolean gap1, gap2, change = FALSE;
11405   Int4    num_segs = 0;
11406   Int4    pos1 = 0, pos2 = 0;
11407 
11408   cp1 = buf1;
11409   cp2 = buf2;
11410   if (*cp1 == '-') {
11411     dsp->starts[dsp->dim * num_segs] = -1;
11412     gap1 = TRUE;
11413   } else {
11414     dsp->starts[dsp->dim * num_segs] = pos1;
11415     gap1 = FALSE;
11416     pos1++;
11417   }
11418   cp1++;
11419   if (*cp2 == '-') {
11420     gap2 = TRUE;
11421     dsp->starts[dsp->dim * num_segs + 1] = -1;
11422   } else {
11423     dsp->starts[dsp->dim * num_segs + 1] = pos2;
11424     gap2 = FALSE;
11425     pos2++;
11426   }
11427   cp2++;
11428   dsp->lens[num_segs] = 1;
11429 
11430   while (*cp1 != 0 && *cp2 != 0) {
11431     change = FALSE;
11432     if (*cp1 == '-') {
11433       if (!gap1) {
11434         gap1 = TRUE;
11435         change = TRUE;
11436       }
11437     } else {
11438       if (gap1) {
11439         gap1 = FALSE;
11440         change = TRUE;
11441       }
11442     }
11443     if (*cp2 == '-') {
11444       if (!gap2) {
11445         gap2 = TRUE;
11446         change = TRUE;
11447       }
11448     } else {
11449       if (gap2) {
11450         gap2 = FALSE;
11451         change = TRUE;
11452       }
11453     }
11454     if (change) {
11455       num_segs ++;
11456       if (gap1) {
11457         dsp->starts[dsp->dim * num_segs] = -1;
11458       } else {
11459         dsp->starts[dsp->dim * num_segs] = pos1;
11460       }
11461       if (gap2) {
11462         dsp->starts[dsp->dim * num_segs + 1] = -1;
11463       } else {
11464         dsp->starts[dsp->dim * num_segs + 1] = pos2;
11465       }
11466       dsp->lens[num_segs] = 1;
11467     } else {
11468       dsp->lens[num_segs]++;
11469     }
11470     cp1++;
11471     cp2++;
11472     if (!gap1) {
11473       pos1++;
11474     }
11475     if (!gap2) {
11476       pos2++;
11477     }
11478   }
11479 }
11480 
11481 
AdjustStringAlingmentForOffsetAndStrand(DenseSegPtr dsp,Int4 start1,Int4 start2,Int4 stop2,Uint1 strand2)11482 static void AdjustStringAlingmentForOffsetAndStrand (DenseSegPtr dsp, Int4 start1, Int4 start2, Int4 stop2, Uint1 strand2)
11483 {
11484   Int4 i;
11485 
11486   if (dsp == NULL) {
11487     return;
11488   }
11489 
11490   for (i = 0; i < dsp->numseg; i++) {
11491     if (dsp->starts[2 * i] != -1) {
11492       dsp->starts[2 * i] += start1;
11493     }
11494     if (dsp->starts[2 * i + 1] != -1) {
11495       if (strand2 == Seq_strand_plus) {
11496         dsp->starts[2 * i + 1] += start2;
11497       } else {
11498         dsp->starts[2 * i + 1] = stop2 - dsp->starts[2 * i + 1] - dsp->lens[i];
11499       }
11500     }
11501   }
11502 }
11503 
11504 
11505 /* assumption - first interval always on plus strand */
NWAlignmentForInterval(SeqIdPtr sip1,SeqIdPtr sip2,Int4 start1,Int4 stop1,Int4 start2,Int4 stop2)11506 static SeqAlignPtr NWAlignmentForInterval (SeqIdPtr sip1, SeqIdPtr sip2, Int4 start1, Int4 stop1, Int4 start2, Int4 stop2)
11507 {
11508   BioseqPtr bsp1, bsp2;
11509   Int4      len1, len2, tmp, i, row, col, back_row, back_col;
11510   Uint1     strand2 = Seq_strand_plus;
11511   CharPtr   buf1, buf2;
11512   CharPtr   alnbuf1, alnbuf2, cp1, cp2;
11513   NWPtr     matrix;
11514   Int4      gap_penalty = -1;
11515   Int4      mismatch_penalty = -1;
11516   Int4      match_score = 1;
11517   Int4      left, up, diag;
11518   Int4      num_segs;
11519   DenseSegPtr dsp;
11520   SeqAlignPtr salp = NULL;
11521 
11522   if (sip1 == NULL || sip2 == NULL) {
11523     return NULL;
11524   }
11525 
11526   bsp1 = BioseqLockById (sip1);
11527   bsp2 = BioseqLockById (sip2);
11528 
11529   if (bsp1 != NULL && bsp2 != NULL) {
11530     if (stop2 < start2) {
11531       strand2 = Seq_strand_minus;
11532       tmp = start2;
11533       start2 = stop2;
11534       stop2 = tmp;
11535     }
11536     len1 = stop1 - start1 + 1;
11537     len2 = stop2 - start2 + 1;
11538     buf1 = MemNew (sizeof (Char) * (len1 + 1));
11539     buf2 = MemNew (sizeof (Char) * (len2 + 1));
11540     SeqPortStreamInt (bsp1, start1, stop1, Seq_strand_plus, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf1, NULL);
11541     SeqPortStreamInt (bsp2, start2, stop2, strand2, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf2, NULL);
11542 
11543     matrix = (NWPtr) MemNew (sizeof (NWData) * (len1 + 1) * (len2 + 1));
11544     /* initalize matrix */
11545     MemSet (matrix, 0, sizeof (NWData) * (len1 + 1) * (len2 + 1));
11546     matrix[0].score = 0;
11547     matrix[0].traceback_pos = 0;
11548     row = 0;
11549     for (col = 1; col <= len1; col++) {
11550       matrix[(row * (len1  + 1)) + col].score = matrix[(row * (len1  + 1)) + col - 1].score + gap_penalty;
11551       matrix[(row * (len1  + 1)) + col].traceback_pos = (row * (len1  + 1)) + col - 1;
11552     }
11553     col = 0;
11554     for (row = 1; row <= len2; row++) {
11555       matrix[(row * (len1  + 1)) + col].score = matrix[((row - 1) * (len1  + 1)) + col].score + gap_penalty;
11556       matrix[(row * (len1  + 1)) + col].traceback_pos = ((row - 1) * (len1  + 1)) + col;
11557     }
11558 
11559     /* fill in scores */
11560     for (row = 1; row <= len2; row++) {
11561       for (col = 1; col <= len1; col++) {
11562         /* diagonal */
11563         diag = matrix[((row - 1) * (len1  + 1)) + col - 1].score;
11564         if (buf1[col - 1] == buf2[row - 1]) {
11565           diag += match_score;
11566         } else {
11567           diag += mismatch_penalty;
11568         }
11569         left = matrix[((row) * (len1  + 1)) + col - 1].score + gap_penalty;
11570         up = matrix[((row - 1) * (len1  + 1)) + col].score + gap_penalty;
11571 
11572         /* choose best */
11573         if (left > diag && left > up) {
11574           matrix[((row) * (len1 + 1)) + col].score = left + gap_penalty;
11575           matrix[((row) * (len1 + 1)) + col].traceback_pos = ((row) * (len1  + 1)) + col - 1;
11576         } else if (up > diag && up > left) {
11577           matrix[((row) * (len1 + 1)) + col].score = up + gap_penalty;
11578           matrix[((row) * (len1 + 1)) + col].traceback_pos = ((row - 1) * (len1  + 1)) + col;
11579         } else {
11580           matrix[((row) * (len1 + 1)) + col].score = diag;
11581           matrix[((row) * (len1 + 1)) + col].traceback_pos = ((row - 1) * (len1  + 1)) + col - 1;
11582         }
11583 
11584       }
11585     }
11586 
11587     /* trace back, create alignment strings */
11588     alnbuf1 = (CharPtr) MemNew (sizeof (Char) * (len1 + len2 + 1));
11589     alnbuf2 = (CharPtr) MemNew (sizeof (Char) * (len1 + len2 + 1));
11590     cp1 = alnbuf1 + len1 + len2;
11591     cp2 = alnbuf2 + len1 + len2;
11592     *cp1 = 0;
11593     *cp2 = 0;
11594     cp1--;
11595     cp2--;
11596     row = len2;
11597     col = len1;
11598     while (row > 0 || col > 0) {
11599       back_row = matrix[(row * (len1 + 1)) + col].traceback_pos / (len1 + 1);
11600       back_col = matrix[(row * (len1 + 1)) + col].traceback_pos % (len1 + 1);
11601       if (row == back_row) {
11602         *cp1 = buf1[col - 1];
11603         *cp2 = '-';
11604       } else if (col == back_col) {
11605         *cp1 = '-';
11606         *cp2 = buf2[row - 1];
11607       } else {
11608         *cp1 = buf1[col - 1];
11609         *cp2 = buf2[row - 1];
11610       }
11611       cp1--;
11612       cp2--;
11613       row = back_row;
11614       col = back_col;
11615     }
11616 
11617     /* no longer need matrix or original sequence buffers */
11618     matrix = MemFree (matrix);
11619     buf1 = MemFree (buf1);
11620     buf2 = MemFree (buf2);
11621 
11622     /* count number of segments needed */
11623     num_segs = SegmentsNeededForAlignment (cp1 + 1, cp2 + 1);
11624 
11625     /* create DenseSeg */
11626     dsp = DenseSegNew ();
11627     dsp->dim = 2;
11628     dsp->ids = SeqIdDup (sip1);
11629     dsp->ids->next = SeqIdDup (sip2);
11630     dsp->numseg = num_segs;
11631     dsp->lens = (Int4Ptr)MemNew (sizeof (Int4) * dsp->numseg);
11632     dsp->starts = (Int4Ptr)MemNew (sizeof (Int4) * dsp->dim * dsp->numseg);
11633     dsp->strands = (Uint1Ptr)MemNew (sizeof (Uint1) * dsp->dim * dsp->numseg);
11634 
11635     /* fill in strands */
11636     for (i = 0; i < dsp->numseg; i++) {
11637       dsp->strands[2 * i] = Seq_strand_plus;
11638       dsp->strands[2 * i + 1] = strand2;
11639     }
11640     /* fill in starts and lens */
11641     FillInStartsAndLensForAlignment (dsp, cp1 + 1, cp2 + 1);
11642 
11643     /* no longer need FASTA+GAP alignment strings */
11644     alnbuf1 = MemFree (alnbuf1);
11645     alnbuf2 = MemFree (alnbuf2);
11646 
11647     /* adjust for real sequence position and strand */
11648     AdjustStringAlingmentForOffsetAndStrand (dsp, start1, start2, stop2, strand2);
11649 
11650     salp = SeqAlignNew ();
11651     salp->segs = dsp;
11652     salp->segtype = SAS_DENSEG;
11653     salp->dim = 2;
11654   }
11655   BioseqUnlock (bsp1);
11656   BioseqUnlock (bsp2);
11657   AlnMgr2IndexSingleChildSeqAlign (salp);
11658   return salp;
11659 }
11660 
11661 
11662 /* Assumptions:
11663  * first interval always on plus strand
11664  */
AlignmentForInterval(SeqIdPtr sip1,SeqIdPtr sip2,Int4 start1,Int4 stop1,Int4 start2,Int4 stop2)11665 static SeqAlignPtr AlignmentForInterval (SeqIdPtr sip1, SeqIdPtr sip2, Int4 start1, Int4 stop1, Int4 start2, Int4 stop2)
11666 {
11667   DenseSegPtr dsp;
11668   SeqAlignPtr salp = NULL;
11669   Int4        len1, len2, i;
11670   Uint1       strand = Seq_strand_plus;
11671 
11672   if (sip1 == NULL || sip2 == NULL) {
11673     return NULL;
11674   }
11675 
11676   salp = NWAlignmentForInterval(sip1, sip2, start1, stop1, start2, stop2);
11677   if (salp != NULL) {
11678     return salp;
11679   }
11680 
11681   dsp = DenseSegNew ();
11682   dsp->dim = 2;
11683   dsp->ids = SeqIdDup (sip1);
11684   dsp->ids->next = SeqIdDup (sip2);
11685   len1 = stop1 - start1 + 1;
11686 
11687   if (stop2 > start2) {
11688     len2 = stop2 - start2 + 1;
11689   } else {
11690     len2 = start2 - stop2 + 1;
11691     strand = Seq_strand_minus;
11692   }
11693 
11694   if (len1 == len2) {
11695     dsp->numseg = 1;
11696   } else {
11697     dsp->numseg = 2;
11698   }
11699 
11700   dsp->starts = (Int4Ptr) MemNew (sizeof (Int4) * dsp->dim * dsp->numseg);
11701   dsp->strands = (Uint1Ptr) MemNew (sizeof (Uint1) * dsp->dim * dsp->numseg);
11702   dsp->lens = (Int4Ptr) MemNew (sizeof (Int4) * dsp->dim);
11703 
11704   if (len1 == len2) {
11705     dsp->lens[0] = len1;
11706   } else if (len1 > len2) {
11707     dsp->lens[0] = len2;
11708     dsp->lens[1] = len1 - len2;
11709   } else {
11710     dsp->lens[0] = len1;
11711     dsp->lens[1] = len2 - len1;
11712   }
11713 
11714   dsp->starts[0] = start1;
11715   if (strand == Seq_strand_minus) {
11716     dsp->starts[1] = stop2;
11717   } else {
11718     dsp->starts[1] = start2;
11719   }
11720 
11721   for (i = 0; i < dsp->numseg; i++) {
11722     dsp->strands[2 * i] = Seq_strand_plus;
11723     dsp->strands[2 * i + 1] = strand;
11724   }
11725 
11726   if (dsp->numseg > 1) {
11727     if (len1 > len2) {
11728       dsp->starts[2] = dsp->starts[0] + dsp->lens[0];
11729       dsp->starts[3] = -1;
11730     } else {
11731       dsp->starts[2] = -1;
11732       if (strand == Seq_strand_minus) {
11733         dsp->starts[3] = dsp->starts[1] + dsp->lens[0] + dsp->lens[1] - 1;
11734       } else {
11735         dsp->starts[3] = dsp->starts[1] + dsp->lens[0];
11736       }
11737     }
11738   }
11739 
11740   salp = SeqAlignNew ();
11741   salp->segtype = SAS_DENSEG;
11742   salp->segs = dsp;
11743 
11744   AlnMgr2IndexSingleChildSeqAlign (salp);
11745   return salp;
11746 }
11747 
11748 
ReportCreatedAlignment(LogInfoPtr lip,SeqAlignPtr salp)11749 static void ReportCreatedAlignment (LogInfoPtr lip, SeqAlignPtr salp)
11750 {
11751   Int4        from_1, to_1, from_2, to_2;
11752   Uint1       strand;
11753   Char        id1[255], id2[255];
11754   SeqIdPtr    sip;
11755   BioseqPtr   bsp;
11756 
11757   if (lip == NULL || lip->fp == NULL || salp == NULL) {
11758     return;
11759   }
11760 
11761   sip = AlnMgr2GetNthSeqIdPtr (salp, 1);
11762   bsp = BioseqLockById (sip);
11763   if (bsp != NULL) {
11764     sip = SeqIdFree (sip);
11765     sip = SeqIdDup (SeqIdFindBest (bsp->id, SEQID_GENBANK));
11766     BioseqUnlock (bsp);
11767   }
11768 
11769   SeqIdWrite (sip, id1, PRINTID_REPORT, sizeof (id1) - 1);
11770   sip = SeqIdFree (sip);
11771   sip = AlnMgr2GetNthSeqIdPtr (salp, 2);
11772   bsp = BioseqLockById (sip);
11773   if (bsp != NULL) {
11774     sip = SeqIdFree (sip);
11775     sip = SeqIdDup (SeqIdFindBest (bsp->id, SEQID_GENBANK));
11776     BioseqUnlock (bsp);
11777   }
11778   SeqIdWrite (sip, id2, PRINTID_REPORT, sizeof (id2) - 1);
11779   sip = SeqIdFree (sip);
11780 
11781   strand = SeqAlignStrand (salp, 2);
11782   AlnMgr2GetNthSeqRangeInSA (salp, 1, &from_1, &to_1);
11783   AlnMgr2GetNthSeqRangeInSA (salp, 2, &from_2, &to_2);
11784   fprintf (lip->fp, "Created alignment to cover space between local alignments: %s:%d-%d, %s:%d-%d%s\n",
11785                      id1, from_1, to_1, id2, from_2, to_2,
11786                      strand == Seq_strand_minus ? "(c)" : "");
11787 
11788   WriteAlignmentInterleaveToFileEx (salp, lip->fp, 40, FALSE, TRUE);
11789 }
11790 
11791 
FillInAlignmentHoles(SeqAlignPtr salp_list,LogInfoPtr lip)11792 static void FillInAlignmentHoles (SeqAlignPtr salp_list, LogInfoPtr lip)
11793 {
11794   SeqAlignPtr salp, salp_new;
11795   Int4        start1_this, start1_next;
11796   Int4        stop1_this, stop1_next;
11797   Int4        start2_this, start2_next;
11798   Int4        stop2_this, stop2_next;
11799   Uint1       strand;
11800   SeqIdPtr    sip1, sip2;
11801 
11802   if (salp_list == NULL || salp_list->next == NULL) {
11803     return;
11804   }
11805 
11806   sip1 = AlnMgr2GetNthSeqIdPtr (salp_list, 1);
11807   sip2 = AlnMgr2GetNthSeqIdPtr (salp_list, 2);
11808 
11809   /* note - unlike the other functions, SeqAlignStrand uses 0-based index */
11810   strand = SeqAlignStrand (salp_list, 1);
11811 
11812   salp = salp_list;
11813   AlnMgr2GetNthSeqRangeInSA (salp, 1, &start1_this, &stop1_this);
11814   AlnMgr2GetNthSeqRangeInSA (salp, 2, &start2_this, &stop2_this);
11815 
11816   while (salp->next != NULL) {
11817     AlnMgr2GetNthSeqRangeInSA (salp->next, 1, &start1_next, &stop1_next);
11818     AlnMgr2GetNthSeqRangeInSA (salp->next, 2, &start2_next, &stop2_next);
11819     if (start1_next > stop1_this + 1
11820         || (strand == Seq_strand_minus && start2_next < stop2_this - 1)
11821         || (strand != Seq_strand_minus && start2_next > stop2_this + 1)) {
11822       if (strand == Seq_strand_minus) {
11823         salp_new = AlignmentForInterval (sip1, sip2, stop1_this + 1, start1_next - 1, stop2_this - 1, start2_next + 1);
11824       } else {
11825         salp_new = AlignmentForInterval (sip1, sip2, stop1_this + 1, start1_next - 1, stop2_this + 1, start2_next - 1);
11826       }
11827       ReportCreatedAlignment (lip, salp_new);
11828       salp_new->next = salp->next;
11829       salp->next = salp_new;
11830       salp = salp_new;
11831     }
11832     start1_this = start1_next;
11833     stop1_this = stop1_next;
11834     start2_this = start2_next;
11835     stop2_this = stop2_next;
11836     salp = salp->next;
11837   }
11838 
11839 }
11840 
11841 
MergeAlignments(SeqAlignPtr salp_list)11842 static SeqAlignPtr MergeAlignments (SeqAlignPtr salp_list)
11843 {
11844   SeqAlignPtr salp_new = NULL, salp, salp_next;
11845   DenseSegPtr dsp, dsp_new;
11846   Int4        seg_num, k;
11847 
11848   if (salp_list == NULL || salp_list->next == NULL) {
11849     return salp_list;
11850   }
11851 
11852   dsp_new = DenseSegNew ();
11853   dsp_new->dim = 2;
11854   dsp_new->ids = AlnMgr2GetNthSeqIdPtr (salp_list, 1);
11855   dsp_new->ids->next = AlnMgr2GetNthSeqIdPtr (salp_list, 2);
11856 
11857   /* get total number of segments */
11858   for (salp = salp_list; salp != NULL; salp = salp->next) {
11859     dsp = (DenseSegPtr) salp->segs;
11860     dsp_new->numseg += dsp->numseg;
11861   }
11862 
11863   dsp_new->starts = (Int4Ptr) MemNew (sizeof (Int4) * dsp_new->dim * dsp_new->numseg);
11864   dsp_new->strands = (Uint1Ptr) MemNew (sizeof (Uint1) * dsp_new->dim * dsp_new->numseg);
11865   dsp_new->lens = (Int4Ptr) MemNew (sizeof (Int4) * dsp_new->numseg);
11866 
11867   seg_num = 0;
11868   for (salp = salp_list; salp != NULL; salp = salp_next) {
11869     salp_next = salp->next;
11870     dsp = (DenseSegPtr) salp->segs;
11871     for (k = 0; k < dsp->numseg; k++) {
11872       dsp_new->lens[seg_num] = dsp->lens[k];
11873       dsp_new->starts[2 * seg_num] = dsp->starts[2 * k];
11874       dsp_new->starts[2 * seg_num + 1] = dsp->starts[2 * k + 1];
11875       dsp_new->strands[2 * seg_num] = dsp->strands[2 * k];
11876       dsp_new->strands[2 * seg_num + 1] = dsp->strands[2 * k + 1];
11877       seg_num++;
11878     }
11879     salp->next = NULL;
11880     salp = SeqAlignFree (salp);
11881   }
11882 
11883   salp_new = SeqAlignNew ();
11884   salp_new->segtype = SAS_DENSEG;
11885   salp_new->segs = dsp_new;
11886   salp_new->dim = 2;
11887 
11888   return salp_new;
11889 }
11890 
11891 
MatchWithAmbiguity(Char ch1,Char ch2)11892 static Boolean MatchWithAmbiguity (Char ch1, Char ch2)
11893 {
11894   Boolean rval = FALSE;
11895 
11896   ch1 = toupper (ch1);
11897   ch2 = toupper (ch2);
11898 
11899   if (ch1 == ch2) {
11900     return TRUE;
11901   }
11902   if (ch1 == 'X' || ch2 == 'X') {
11903     return TRUE;
11904   }
11905   switch (ch1) {
11906     case 'A':
11907       if (ch2 == 'M' || ch2 == 'R' || ch2 == 'W' || ch2 == 'V' || ch2 == 'H' || ch2 == 'D') {
11908         rval = TRUE;
11909       }
11910       break;
11911     case 'T':
11912       if (ch2 == 'K' || ch2 == 'Y' || ch2 == 'W' || ch2 == 'B' || ch2 == 'H' || ch2 == 'D') {
11913         rval = TRUE;
11914       }
11915       break;
11916     case 'G':
11917       if (ch2 == 'K' || ch2 == 'R' || ch2 == 'S' || ch2 == 'B' || ch2 == 'V' || ch2 == 'D') {
11918         rval = TRUE;
11919       }
11920       break;
11921     case 'C':
11922       if (ch2 == 'M' || ch2 == 'Y' || ch2 == 'S' || ch2 == 'B' || ch2 == 'V' || ch2 == 'H') {
11923         rval = TRUE;
11924       }
11925       break;
11926     case 'K':
11927       if (ch2 == 'G' || ch2 == 'T' || ch2 == 'B' || ch2 == 'D') {
11928         rval = TRUE;
11929       }
11930       break;
11931     case 'M':
11932       if (ch2 == 'A' || ch2 == 'C' || ch2 == 'V' || ch2 == 'H') {
11933         rval = TRUE;
11934       }
11935       break;
11936     case 'R':
11937       if (ch2 == 'A' || ch2 == 'G' || ch2 == 'V' || ch2 == 'D') {
11938         rval = TRUE;
11939       }
11940       break;
11941     case 'Y':
11942       if (ch2 == 'C' || ch2 == 'T' || ch2 == 'B' || ch2 == 'H') {
11943         rval = TRUE;
11944       }
11945       break;
11946     case 'S':
11947       if (ch2 == 'C' || ch2 == 'G' || ch2 == 'B' || ch2 == 'V') {
11948         rval = TRUE;
11949       }
11950       break;
11951     case 'W':
11952       if (ch2 == 'A' || ch2 == 'T' || ch2 == 'H' || ch2 == 'D') {
11953         rval = TRUE;
11954       }
11955       break;
11956     case 'B':
11957       if (ch2 == 'C' || ch2 == 'G' || ch2 == 'T' || ch2 == 'K' || ch2 == 'Y' || ch2 == 'S') {
11958         rval = TRUE;
11959       }
11960       break;
11961     case 'V':
11962       if (ch2 == 'A' || ch2 == 'C' || ch2 == 'G' || ch2 == 'M' || ch2 == 'R' || ch2 == 'S') {
11963         rval = TRUE;
11964       }
11965       break;
11966     case 'H':
11967       if (ch2 == 'A' || ch2 == 'C' || ch2 == 'T' || ch2 == 'M' || ch2 == 'Y' || ch2 == 'W') {
11968         rval = TRUE;
11969       }
11970       break;
11971     case 'D':
11972       if (ch2 == 'A' || ch2 == 'G' || ch2 == 'T' || ch2 == 'K' || ch2 == 'R' || ch2 == 'W') {
11973         rval = TRUE;
11974       }
11975       break;
11976   }
11977   return rval;
11978 }
11979 
11980 
11981 /* expand for ambiguity characters and poly-A tail */
ExtendAlignmentList(SeqAlignPtr salp_list)11982 static SeqAlignPtr ExtendAlignmentList (SeqAlignPtr salp_list)
11983 {
11984   Int4        from_1, to_1, from_2, to_2, len1, len2, len_check, len_extend;
11985   SeqAlignPtr salp_tmp;
11986   BioseqPtr   bsp1 = NULL;
11987   BioseqPtr   bsp2 = NULL;
11988   Uint1       strand;
11989   CharPtr     buf1, buf2;
11990   Int2        ctr;
11991   SeqIdPtr    sip1, sip2;
11992   DenseSegPtr dsp;
11993 
11994   if (salp_list == NULL) {
11995     return salp_list;
11996   }
11997 
11998   strand = SeqAlignStrand (salp_list, 1);
11999   AlnMgr2IndexSingleChildSeqAlign (salp_list);
12000 
12001   sip1 = AlnMgr2GetNthSeqIdPtr (salp_list, 1);
12002   bsp1 = BioseqLockById (sip1);
12003   sip2 = AlnMgr2GetNthSeqIdPtr (salp_list, 2);
12004   bsp2 = BioseqLockById (sip2);
12005 
12006   AlnMgr2GetNthSeqRangeInSA (salp_list, 1, &from_1, &to_1);
12007   AlnMgr2GetNthSeqRangeInSA (salp_list, 2, &from_2, &to_2);
12008 
12009   if (from_1 > 0
12010       && ((strand == Seq_strand_plus && from_2 > 0)
12011           || (strand == Seq_strand_minus && to_2 < bsp2->length - 1))) {
12012     len1 = from_1;
12013     if (strand == Seq_strand_plus) {
12014       len2 = from_2;
12015     } else {
12016       len2 = bsp2->length - to_2 - 1;
12017     }
12018     if (len1 > len2) {
12019       len_check = len2;
12020     } else {
12021       len_check = len1;
12022     }
12023     buf1 = (CharPtr) MemNew (sizeof (Char) * (len_check  + 1));
12024     buf2 = (CharPtr) MemNew (sizeof (Char) * (len_check  + 1));
12025     ctr = SeqPortStreamInt (bsp1, from_1 - len_check, from_1 - 1, Seq_strand_plus, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf1, NULL);
12026     buf1[ctr] = 0;
12027     if (strand == Seq_strand_plus) {
12028       ctr = SeqPortStreamInt (bsp2, from_2 - len_check, from_2 - 1, Seq_strand_plus, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf2, NULL);
12029     } else {
12030       ctr = SeqPortStreamInt (bsp2, to_2 + 1, to_2 + len_check, Seq_strand_minus, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf2, NULL);
12031     }
12032     buf2[ctr] = 0;
12033 
12034     len_extend = 0;
12035     while (len_extend < len_check
12036            && MatchWithAmbiguity (buf1[len_check - len_extend - 1], buf2[len_check - len_extend - 1])) {
12037       len_extend++;
12038     }
12039     buf1 = MemFree (buf1);
12040     buf2 = MemFree (buf2);
12041     if (len_extend > 0) {
12042       dsp = (DenseSegPtr) salp_list->segs;
12043       dsp->lens[0] += len_extend;
12044       dsp->starts[0] -= len_extend;
12045       if (strand == Seq_strand_plus) {
12046         dsp->starts[1] -= len_extend;
12047       }
12048       SeqAlignIndexFree(salp_list->saip);
12049       salp_list->saip = NULL;
12050       AlnMgr2IndexSingleChildSeqAlign (salp_list);
12051     }
12052   }
12053 
12054   /* extend at other end */
12055   salp_tmp = salp_list;
12056   while (salp_tmp->next != NULL) {
12057     salp_tmp = salp_tmp->next;
12058   }
12059 
12060   AlnMgr2IndexSingleChildSeqAlign (salp_tmp);
12061 
12062   AlnMgr2GetNthSeqRangeInSA (salp_tmp, 1, &from_1, &to_1);
12063   AlnMgr2GetNthSeqRangeInSA (salp_tmp, 2, &from_2, &to_2);
12064   if (to_1 < bsp1->length - 1
12065       && ((strand == Seq_strand_plus && to_2 < bsp2->length - 1)
12066           || (strand == Seq_strand_minus && from_2 > 0))) {
12067     len1 = bsp1->length - to_1 - 1;
12068     if (strand == Seq_strand_plus) {
12069       len2 = bsp2->length - to_2 - 1;
12070     } else {
12071       len2 = from_2;
12072     }
12073     if (len1 > len2) {
12074       len_check = len2;
12075     } else {
12076       len_check = len1;
12077     }
12078     if (len_check > 0) {
12079       buf1 = (CharPtr) MemNew (sizeof (Char) * (len_check  + 1));
12080       buf2 = (CharPtr) MemNew (sizeof (Char) * (len_check  + 1));
12081       ctr = SeqPortStreamInt (bsp1, to_1 + 1, to_1 + len_check, Seq_strand_plus, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf1, NULL);
12082       buf1[ctr] = 0;
12083       if (strand == Seq_strand_plus) {
12084         ctr = SeqPortStreamInt (bsp2, to_2 + 1, to_2 + len_check, Seq_strand_plus, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf2, NULL);
12085       } else {
12086         ctr = SeqPortStreamInt (bsp2, from_2 - len_check, from_2 - 1, Seq_strand_minus, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, (Pointer) buf2, NULL);
12087       }
12088       buf2[ctr] = 0;
12089 
12090       len_extend = 0;
12091       while (len_extend < len_check
12092             && MatchWithAmbiguity (buf1[len_extend], buf2[len_extend])) {
12093         len_extend++;
12094       }
12095       buf1 = MemFree (buf1);
12096       buf2 = MemFree (buf2);
12097       if (len_extend > 0) {
12098         dsp = (DenseSegPtr) salp_tmp->segs;
12099         dsp->lens[dsp->numseg - 1] += len_extend;
12100         if (strand == Seq_strand_minus) {
12101           dsp->starts[(dsp->numseg - 1) * dsp->dim + 1] -= len_extend;
12102         }
12103         SeqAlignIndexFree(salp_tmp->saip);
12104         salp_tmp->saip = NULL;
12105         AlnMgr2IndexSingleChildSeqAlign (salp_tmp);
12106       }
12107     }
12108   }
12109 
12110   BioseqUnlock (bsp1);
12111   BioseqUnlock (bsp2);
12112   sip1 = SeqIdFree (sip1);
12113   sip2 = SeqIdFree (sip2);
12114 
12115   return salp_list;
12116 }
12117 
12118 
ReportInitialBlastResults(LogInfoPtr lip,SeqAlignPtr salp_list)12119 static void ReportInitialBlastResults (LogInfoPtr lip, SeqAlignPtr salp_list)
12120 {
12121   Int4        from_1, to_1, from_2, to_2;
12122   Uint1       strand;
12123   Char        id1[255], id2[255];
12124   SeqIdPtr    sip;
12125   BioseqPtr   bsp;
12126 
12127   if (lip == NULL || lip->fp == NULL || salp_list == NULL) {
12128     return;
12129   }
12130 
12131   AlnMgr2IndexSingleChildSeqAlign (salp_list);
12132   sip = AlnMgr2GetNthSeqIdPtr (salp_list, 1);
12133   bsp = BioseqLockById (sip);
12134   if (bsp != NULL) {
12135     sip = SeqIdFree (sip);
12136     sip = SeqIdDup (SeqIdFindBest (bsp->id, SEQID_GENBANK));
12137     BioseqUnlock (bsp);
12138   }
12139   SeqIdWrite (sip, id1, PRINTID_REPORT, sizeof (id1) - 1);
12140   sip = SeqIdFree (sip);
12141   sip = AlnMgr2GetNthSeqIdPtr (salp_list, 2);
12142   bsp = BioseqLockById (sip);
12143   if (bsp != NULL) {
12144     sip = SeqIdFree (sip);
12145     sip = SeqIdDup (SeqIdFindBest (bsp->id, SEQID_GENBANK));
12146     BioseqUnlock (bsp);
12147   }
12148   SeqIdWrite (sip, id2, PRINTID_REPORT, sizeof (id2) - 1);
12149   sip = SeqIdFree (sip);
12150   fprintf (lip->fp, "Initial BLAST results\n");
12151   while (salp_list != NULL) {
12152     AlnMgr2IndexSingleChildSeqAlign (salp_list);
12153     strand = SeqAlignStrand (salp_list, 2);
12154     AlnMgr2GetNthSeqRangeInSA (salp_list, 1, &from_1, &to_1);
12155     AlnMgr2GetNthSeqRangeInSA (salp_list, 2, &from_2, &to_2);
12156     fprintf (lip->fp, "%s:%d-%d, %s:%d-%d%s\n", id1, from_1, to_1, id2, from_2, to_2,
12157              strand == Seq_strand_minus ? "(c)" : "");
12158     salp_list = salp_list->next;
12159   }
12160   lip->data_in_log = TRUE;
12161 }
12162 
12163 
ReportForRemoval(LogInfoPtr lip,SeqAlignPtr salp,CharPtr reason)12164 static void ReportForRemoval (LogInfoPtr lip, SeqAlignPtr salp, CharPtr reason)
12165 {
12166   Int4        from_1, to_1, from_2, to_2;
12167   Uint1       strand;
12168   Char        id1[255], id2[255];
12169   SeqIdPtr    sip;
12170 
12171   if (lip == NULL || lip->fp == NULL || salp == NULL) {
12172     return;
12173   }
12174 
12175   sip = AlnMgr2GetNthSeqIdPtr (salp, 1);
12176   SeqIdWrite (sip, id1, PRINTID_REPORT, sizeof (id1) - 1);
12177   sip = SeqIdFree (sip);
12178   sip = AlnMgr2GetNthSeqIdPtr (salp, 2);
12179   SeqIdWrite (sip, id2, PRINTID_REPORT, sizeof (id2) - 1);
12180   sip = SeqIdFree (sip);
12181   AlnMgr2IndexSingleChildSeqAlign (salp);
12182   strand = SeqAlignStrand (salp, 2);
12183   AlnMgr2GetNthSeqRangeInSA (salp, 1, &from_1, &to_1);
12184   AlnMgr2GetNthSeqRangeInSA (salp, 2, &from_2, &to_2);
12185   fprintf (lip->fp, "Removed alignment %s:%d-%d, %s:%d-%d%s %s\n",
12186                      id1, from_1, to_1, id2, from_2, to_2,
12187                      strand == Seq_strand_minus ? "(c)" : "", reason);
12188 }
12189 
12190 
12191 /* Assume earlier alignments are better.
12192  * Remove all alignments that are not the same strand as the first.
12193  * Remove all alignments that overlap on the first sequence.
12194  * Remove all alignments that overlap on the second sequence.
12195  * use Needleman-Wunsch to fill in holes between alignments.
12196  */
CombineTSAAlignments(SeqAlignPtr salp)12197 static SeqAlignPtr CombineTSAAlignments (SeqAlignPtr salp)
12198 {
12199   SeqAlignPtr salp_tmp, salp_match, salp_prev, salp_next;
12200   Uint1       strand;
12201   Int4        from_1, to_1, from_2, to_2;
12202   LogInfoPtr  lip = NULL;
12203 
12204   if (salp == NULL) {
12205     return salp;
12206   }
12207 
12208   for (salp_tmp = salp; salp_tmp != NULL; salp_tmp = salp_tmp->next) {
12209     /* if alignment is to minus strand for first sequence, flip alignment */
12210     if (SeqAlignStrand (salp_tmp, 0) != Seq_strand_plus) {
12211       FlipAlignment (salp_tmp);
12212     }
12213   }
12214 
12215   if (salp->next != NULL) {
12216     lip = OpenLog ("TSA Alignment Adjustments");
12217   }
12218 
12219   ReportInitialBlastResults (lip, salp);
12220 
12221   if (salp->next != NULL) {
12222     /* remove alignments that are not the same strand as the initial alignment */
12223     strand = SeqAlignStrand (salp, 1);
12224     salp_prev = salp;
12225     AlnMgr2IndexSingleChildSeqAlign (salp);
12226     salp_tmp = salp->next;
12227     while (salp_tmp != NULL) {
12228       AlnMgr2IndexSingleChildSeqAlign (salp_tmp);
12229       salp_next = salp_tmp->next;
12230       if (SeqAlignStrand (salp_tmp, 1) != strand) {
12231         ReportForRemoval (lip, salp_tmp, "because strands do not match.");
12232         salp_prev->next = salp_tmp->next;
12233         salp_tmp->next = NULL;
12234         salp_tmp = SeqAlignFree (salp_tmp);
12235       }
12236       salp_tmp = salp_next;
12237     }
12238   }
12239 
12240   /* remove alignments that overlap on the first sequence */
12241   salp_match = salp;
12242   while (salp_match != NULL) {
12243     salp_prev = salp_match;
12244     salp_tmp = salp_match->next;
12245     AlnMgr2GetNthSeqRangeInSA (salp_match, 1, &from_1, &to_1);
12246     while (salp_tmp != NULL) {
12247       salp_next = salp_tmp->next;
12248       AlnMgr2GetNthSeqRangeInSA (salp_tmp, 1, &from_2, &to_2);
12249       if ((from_2 >= from_1 && from_2 <= to_1) || (to_2 >= from_1 && to_2 <= to_1)) {
12250         ReportForRemoval (lip, salp_tmp, "because alignments overlap for first sequence.");
12251         salp_prev->next = salp_tmp->next;
12252         salp_tmp->next = NULL;
12253         salp_tmp = SeqAlignFree (salp_tmp);
12254       }
12255       salp_tmp = salp_next;
12256     }
12257     salp_match = salp_match->next;
12258   }
12259 
12260   if (salp->next != NULL) {
12261     /* remove alignments that overlap on the second sequence */
12262     salp_match = salp;
12263     while (salp_match != NULL) {
12264       salp_prev = salp_match;
12265       salp_tmp = salp_match->next;
12266       AlnMgr2GetNthSeqRangeInSA (salp_match, 2, &from_1, &to_1);
12267       while (salp_tmp != NULL) {
12268         salp_next = salp_tmp->next;
12269         AlnMgr2GetNthSeqRangeInSA (salp_tmp, 2, &from_2, &to_2);
12270         if ((from_2 >= from_1 && from_2 <= to_1) || (to_2 >= from_1 && to_2 <= to_1)) {
12271           ReportForRemoval (lip, salp_tmp, "because alignments overlap for second sequence.");
12272           salp_prev->next = salp_tmp->next;
12273           salp_tmp->next = NULL;
12274           salp_tmp = SeqAlignFree (salp_tmp);
12275         }
12276         salp_tmp = salp_next;
12277       }
12278       salp_match = salp_match->next;
12279     }
12280   }
12281 
12282   /* sort remaining alignments by start position on the first sequence */
12283   salp = SortPairwiseAlignmentsByFirstSeqRange (salp);
12284 
12285   /* temporary hack.  only interested in "unusual" errors. */
12286   if (lip != NULL) {
12287     lip->data_in_log = FALSE;
12288   }
12289 
12290   if (salp->next != NULL) {
12291     /* remove alignments that are out of order on the second sequence */
12292     salp_prev = salp;
12293     AlnMgr2GetNthSeqRangeInSA (salp_prev, 2, &from_1, &to_1);
12294     salp_tmp = salp->next;
12295     while (salp_tmp != NULL) {
12296       AlnMgr2GetNthSeqRangeInSA (salp_tmp, 2, &from_2, &to_2);
12297       if (from_2 < from_1) {
12298         ReportForRemoval (lip, salp_tmp, "because alignments are out of order for second sequence.");
12299         salp_prev->next = salp_tmp->next;
12300         salp_tmp->next = NULL;
12301         salp_tmp = SeqAlignFree (salp_tmp);
12302       } else {
12303         salp_prev = salp_tmp;
12304         from_1 = from_2;
12305         to_1 = to_2;
12306       }
12307       salp_tmp = salp_prev->next;
12308     }
12309   }
12310 
12311   /* fill in holes */
12312   FillInAlignmentHoles (salp, lip);
12313 
12314   /* extend for good matches */
12315   salp = ExtendAlignmentList (salp);
12316 
12317   /* make new alignment by stringing together local alignments */
12318   salp = MergeAlignments (salp);
12319   CloseLog (lip);
12320   lip = FreeLog (lip);
12321   return salp;
12322 }
12323 
12324 
GetSeqAlignTSA(BioseqPtr bsp1,BioseqPtr bsp2)12325 NLM_EXTERN SeqAlignPtr GetSeqAlignTSA (BioseqPtr bsp1, BioseqPtr bsp2)
12326 {
12327    BLAST_SummaryOptions *options = NULL;
12328    SeqAlignPtr           salp = NULL;
12329 
12330    if (bsp1 == NULL || bsp2 == NULL) return NULL;
12331 
12332    BLAST_SummaryOptionsInit(&options);
12333    options->filter_string = StringSave ("m L");
12334    options->word_size = 20;
12335    options->cutoff_evalue = act_get_eval (1);
12336    options->hint = eBlastHint_None;
12337    if (ISA_na (bsp1->mol))
12338    {
12339      options->program = eBlastn;
12340    }
12341    else
12342    {
12343      options->program = eBlastp;
12344    }
12345 
12346    BLAST_TwoSequencesSearch(options, bsp1, bsp2, &salp);
12347 
12348    /* if there were no alignments from the first search, try again
12349     * with low-complexity masking turned off.
12350     */
12351    if (salp == NULL) {
12352      options->filter_string = MemFree (options->filter_string);
12353      options->filter_string = StringSave ("m F");
12354      BLAST_TwoSequencesSearch(options, bsp1, bsp2, &salp);
12355    }
12356 
12357    BLAST_SummaryOptionsFree(options);
12358 
12359    if (salp != NULL) {
12360      salp = CombineTSAAlignments (salp);
12361      AlnMgr2IndexSeqAlign(salp);
12362    }
12363    return salp;
12364 }
12365 
12366 
ShowAssemblyAlignment(SeqAlignPtr salp)12367 static void ShowAssemblyAlignment (SeqAlignPtr salp)
12368 {
12369   LogInfoPtr lip;
12370 
12371   if (salp == NULL) {
12372     return;
12373   }
12374 
12375   lip = OpenLog ("Assembly Alignments");
12376   while (salp != NULL) {
12377     WriteAlignmentInterleaveToFileEx (salp, lip->fp, 40, FALSE, TRUE);
12378     lip->data_in_log = TRUE;
12379     salp = salp->next;
12380   }
12381   CloseLog (lip);
12382   lip = FreeLog (lip);
12383 }
12384 
12385 
12386 /* automatic defline generator */
12387 
12388 typedef struct deffeats {
12389   SeqFeatPtr  sfp;
12390   SeqFeatPtr  gene;
12391   SeqFeatPtr  prot;
12392   CharPtr     genename;
12393   CharPtr     allelename;
12394   CharPtr     protname;
12395   Boolean     alreadyTrimmed;
12396   Uint2       entityID;
12397   Uint4       itemID;
12398   Uint2       subtype;
12399   Boolean     isDNA;
12400   Boolean     isAlleleGroup;
12401   Boolean     lastInString;
12402   Boolean     lastInGroup;
12403   Boolean     lastInType;
12404   Boolean     lastInPenultimate;
12405   Boolean     pseudo;
12406   Boolean     ignore;
12407   Boolean     suppressprefix;
12408   Int2        altSplices;
12409   Int2        numUnknown;
12410 } DefFeatsData, PNTR DefFeatsPtr;
12411 
GetMolBioFeatsGatherFunc(GatherContextPtr gcp,Boolean getGene,Boolean getSnoRNA)12412 static Boolean GetMolBioFeatsGatherFunc (GatherContextPtr gcp, Boolean getGene, Boolean getSnoRNA)
12413 
12414 {
12415   DefFeatsPtr  dfp;
12416   RnaRefPtr    rrp;
12417   SeqFeatPtr   sfp;
12418   CharPtr      str;
12419   Uint1        type;
12420   ValNodePtr   PNTR vnpp;
12421 
12422   if (gcp == NULL || gcp->thisitem == NULL || gcp->userdata == NULL)
12423     return TRUE;
12424   if (gcp->thistype != OBJ_SEQFEAT) return TRUE;
12425   vnpp = (ValNodePtr PNTR) gcp->userdata;
12426   sfp = (SeqFeatPtr) gcp->thisitem;
12427   switch (sfp->data.choice) {
12428     case SEQFEAT_GENE :
12429       if (getGene) {
12430         dfp = MemNew (sizeof (DefFeatsData));
12431         if (dfp == NULL) return TRUE;
12432         dfp->entityID = gcp->entityID;
12433         dfp->itemID = gcp->itemID;
12434         dfp->sfp = sfp;
12435         dfp->subtype = FEATDEF_GENE;
12436         ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12437       }
12438       break;
12439     case SEQFEAT_CDREGION :
12440       dfp = MemNew (sizeof (DefFeatsData));
12441       if (dfp == NULL) return TRUE;
12442       dfp->entityID = gcp->entityID;
12443       dfp->itemID = gcp->itemID;
12444       dfp->sfp = sfp;
12445       dfp->subtype = FEATDEF_CDS;
12446       dfp->altSplices = 1;
12447       ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12448       break;
12449     case SEQFEAT_RNA :
12450       rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
12451       if (rrp == NULL) return TRUE;
12452       switch (rrp->type) {
12453         case 3 :
12454           dfp = MemNew (sizeof (DefFeatsData));
12455           if (dfp == NULL) return TRUE;
12456           dfp->entityID = gcp->entityID;
12457           dfp->itemID = gcp->itemID;
12458           dfp->sfp = sfp;
12459           dfp->subtype = FEATDEF_tRNA;
12460           ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12461           break;
12462         case 4 :
12463           dfp = MemNew (sizeof (DefFeatsData));
12464           if (dfp == NULL) return TRUE;
12465           dfp->entityID = gcp->entityID;
12466           dfp->itemID = gcp->itemID;
12467           dfp->sfp = sfp;
12468           dfp->subtype = FEATDEF_rRNA;
12469           ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12470           break;
12471          case 5 :
12472           if (getSnoRNA) {
12473             dfp = MemNew (sizeof (DefFeatsData));
12474             if (dfp == NULL) return TRUE;
12475             dfp->entityID = gcp->entityID;
12476             dfp->itemID = gcp->itemID;
12477             dfp->sfp = sfp;
12478             dfp->subtype = FEATDEF_snRNA;
12479             ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12480           }
12481           break;
12482        case 7 :
12483           if (getSnoRNA) {
12484             dfp = MemNew (sizeof (DefFeatsData));
12485             if (dfp == NULL) return TRUE;
12486             dfp->entityID = gcp->entityID;
12487             dfp->itemID = gcp->itemID;
12488             dfp->sfp = sfp;
12489             dfp->subtype = FEATDEF_snoRNA;
12490             ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12491           }
12492           break;
12493         case 255 :
12494           if (rrp->ext.choice == 1) {
12495             str = (CharPtr) rrp->ext.value.ptrvalue;
12496             if (StringICmp (str, "internal transcribed spacer 1") == 0 ||
12497                 StringICmp (str, "internal transcribed spacer 2") == 0 ||
12498                 StringICmp (str, "internal transcribed spacer 3") == 0 ||
12499                 StringICmp (str, "internal transcribed spacer ITS1") == 0 ||
12500                 StringICmp (str, "internal transcribed spacer ITS2") == 0 ||
12501                 StringICmp (str, "internal transcribed spacer ITS3") == 0 ||
12502                 StringICmp (str, "ITS1") == 0 ||
12503                 StringICmp (str, "ITS2") == 0 ||
12504                 StringICmp (str, "ITS3") == 0) {
12505               dfp = MemNew (sizeof (DefFeatsData));
12506               if (dfp == NULL) return TRUE;
12507               dfp->entityID = gcp->entityID;
12508               dfp->itemID = gcp->itemID;
12509               dfp->sfp = sfp;
12510               dfp->subtype = FEATDEF_otherRNA;
12511               ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12512             }
12513           }
12514           break;
12515         default :
12516           break;
12517       }
12518       break;
12519     case SEQFEAT_IMP :
12520       type = FindFeatDefType (sfp);
12521       if (type == FEATDEF_LTR || type == FEATDEF_exon) {
12522         dfp = MemNew (sizeof (DefFeatsData));
12523         if (dfp == NULL) return TRUE;
12524         dfp->entityID = gcp->entityID;
12525         dfp->itemID = gcp->itemID;
12526         dfp->sfp = sfp;
12527         dfp->subtype = type;
12528         ValNodeAddPointer (vnpp, 0, (Pointer) dfp);
12529       }
12530       break;
12531     default :
12532       break;
12533   }
12534   return TRUE;
12535 }
12536 
GetCDStRNArRNAGatherFunc(GatherContextPtr gcp)12537 static Boolean GetCDStRNArRNAGatherFunc (GatherContextPtr gcp)
12538 
12539 {
12540   return GetMolBioFeatsGatherFunc (gcp, FALSE, FALSE);
12541 }
12542 
12543 
StringHasEqualSignOrBrackets(CharPtr str)12544 static Boolean StringHasEqualSignOrBrackets (CharPtr str)
12545 
12546 {
12547   Char  ch;
12548 
12549   if (StringHasNoText (str)) return FALSE;
12550   ch = *str;
12551   while (ch != '\0') {
12552     if (ch == '=' || ch == '[' || ch == ']') return TRUE;
12553     str++;
12554     ch = *str;
12555   }
12556   return FALSE;
12557 }
12558 
MakeProteinTitlesInSequinStyle(Uint2 entityID,SeqEntryPtr sep)12559 static void MakeProteinTitlesInSequinStyle (Uint2 entityID, SeqEntryPtr sep)
12560 
12561 {
12562   BioseqPtr     bsp;
12563   BioseqSetPtr  bssp;
12564   DefFeatsPtr   dfp;
12565   Char          quot [4];
12566   GeneRefPtr    grp;
12567   GatherScope   gs;
12568   Boolean       has_equal_or_brackets;
12569   ValNodePtr    head;
12570   SeqEntryPtr   nsep;
12571   ProtRefPtr    prp;
12572   SeqEntryPtr   psep;
12573   Char          str [256];
12574   Char          text [256];
12575   ValNodePtr    ttl;
12576   ValNodePtr    vnp;
12577 
12578   if (sep == NULL) return;
12579   if (IS_Bioseq_set (sep)) {
12580     bssp = (BioseqSetPtr) sep->data.ptrvalue;
12581     if (bssp == NULL) return;
12582     if (bssp->_class == 7 ||
12583         (IsPopPhyEtcSet (bssp->_class))) {
12584       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
12585         MakeProteinTitlesInSequinStyle (entityID, sep);
12586       }
12587       return;
12588     }
12589   }
12590   nsep = FindNucSeqEntry (sep);
12591   if (nsep == NULL) return;
12592 
12593   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
12594   gs.seglevels = 1;
12595   gs.get_feats_location = TRUE;
12596   MemSet ((Pointer) (gs.ignore), (int)(TRUE), (size_t) (OBJ_MAX * sizeof(Boolean)));
12597   gs.ignore[OBJ_BIOSEQ] = FALSE;
12598   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
12599   gs.ignore[OBJ_SEQANNOT] = FALSE;
12600   gs.ignore[OBJ_SEQFEAT] = FALSE;
12601   gs.scope = sep;
12602   gs.target = NULL;
12603   head = NULL;
12604   GatherEntity (entityID, (Pointer) (&head), GetCDStRNArRNAGatherFunc, &gs);
12605   /* head = SortValNode (head, SortCDStRNArRNAByLocation); */
12606   if (head == NULL) return;
12607 
12608   quot [0] = '"';
12609   quot [1] = '\0';
12610 
12611   vnp = head;
12612   while (vnp != NULL) {
12613     dfp = (DefFeatsPtr) vnp->data.ptrvalue;
12614     if (dfp != NULL && dfp->sfp != NULL && dfp->subtype == FEATDEF_CDS) {
12615       FindGeneAndProtForCDS (entityID, dfp->sfp, &(dfp->gene), &(dfp->prot));
12616       bsp = GetBioseqGivenSeqLoc (dfp->sfp->product, entityID);
12617       if (bsp != NULL) {
12618         str [0] = '\0';
12619         if (dfp->gene != NULL) {
12620           grp = (GeneRefPtr) dfp->gene->data.value.ptrvalue;
12621           if (grp != NULL) {
12622             StringNCpy_0 (text, (CharPtr) grp->locus, sizeof (text));
12623             if (! StringHasNoText (text)) {
12624               StringCat (str, "[gene=");
12625               StringCat (str, text);
12626               StringCat (str, "]");
12627             }
12628             if (grp->syn != NULL) {
12629               StringNCpy_0 (text, (CharPtr) grp->syn->data.ptrvalue, sizeof (text));
12630               if (! StringHasNoText (text)) {
12631                 if (str [0] != '\0') {
12632                   StringCat (str, " ");
12633                 }
12634                 StringCat (str, "[gene_syn=");
12635                 StringCat (str, text);
12636                 StringCat (str, "]");
12637               }
12638             }
12639           }
12640         }
12641         if (dfp->prot != NULL) {
12642           prp = (ProtRefPtr) dfp->prot->data.value.ptrvalue;
12643           if (prp != NULL) {
12644             if (prp->name != NULL) {
12645               StringNCpy_0 (text, (CharPtr) prp->name->data.ptrvalue, sizeof (text));
12646               if (! StringHasNoText (text)) {
12647                 if (str [0] != '\0') {
12648                   StringCat (str, " ");
12649                 }
12650                 StringCat (str, "[protein=");
12651                 has_equal_or_brackets = StringHasEqualSignOrBrackets (text);
12652                 if (has_equal_or_brackets) {
12653                   StringCat (str, quot);
12654                 }
12655                 StringCat (str, text);
12656                 if (has_equal_or_brackets) {
12657                   StringCat (str, quot);
12658                 }
12659                 StringCat (str, "]");
12660               }
12661             }
12662             StringNCpy_0 (text, (CharPtr) prp->desc, sizeof (text));
12663             if (! StringHasNoText (text)) {
12664               StringCat (str, "[prot_desc=");
12665               has_equal_or_brackets = StringHasEqualSignOrBrackets (text);
12666               if (has_equal_or_brackets) {
12667                 StringCat (str, quot);
12668               }
12669               StringCat (str, text);
12670               if (has_equal_or_brackets) {
12671                 StringCat (str, quot);
12672               }
12673               StringCat (str, "]");
12674             }
12675           }
12676         }
12677         if (! StringHasNoText (str)) {
12678           psep = SeqMgrGetSeqEntryForData (bsp);
12679           if (psep != NULL) {
12680             ttl = CreateNewDescriptor (psep, Seq_descr_title);
12681             if (ttl != NULL) {
12682               ttl->data.ptrvalue = StringSave (str);
12683             }
12684           }
12685         }
12686       }
12687     }
12688     vnp = vnp->next;
12689   }
12690   ValNodeFreeData (head);
12691 }
12692 
12693 
InsertGeneLocusTagPrefixCallback(SeqFeatPtr sfp,Pointer userdata)12694 static void InsertGeneLocusTagPrefixCallback (SeqFeatPtr sfp, Pointer userdata)
12695 {
12696   CharPtr    prefix;
12697   GeneRefPtr grp;
12698   CharPtr    new_locus_tag = NULL;
12699   Int4       new_locus_tag_len = 0;
12700 
12701   if (sfp == NULL || userdata == NULL || sfp->data.choice != SEQFEAT_GENE)
12702   {
12703     return;
12704   }
12705 
12706   prefix = (CharPtr) userdata;
12707 
12708   if (StringHasNoText (prefix))
12709   {
12710     return;
12711   }
12712 
12713   grp = (GeneRefPtr) sfp->data.value.ptrvalue;
12714   if (grp == NULL)
12715   {
12716     grp = GeneRefNew();
12717     sfp->data.value.ptrvalue = grp;
12718   }
12719   if (grp == NULL)
12720   {
12721     return;
12722   }
12723 
12724   if (StringHasNoText (grp->locus_tag))
12725   {
12726     grp->locus_tag = MemFree (grp->locus_tag);
12727     grp->locus_tag = StringSave (prefix);
12728   }
12729   else
12730   {
12731     new_locus_tag_len = StringLen (prefix) + StringLen (grp->locus_tag) + 1;
12732     new_locus_tag = (CharPtr) MemNew (sizeof (Char) * new_locus_tag_len);
12733     if (new_locus_tag != NULL)
12734     {
12735       StringCpy (new_locus_tag, prefix);
12736       StringCat (new_locus_tag, grp->locus_tag);
12737       grp->locus_tag = MemFree (grp->locus_tag);
12738       grp->locus_tag = new_locus_tag;
12739     }
12740   }
12741 }
12742 
12743 typedef struct locustagprefix
12744 {
12745   FEATURE_FORM_BLOCK
12746 
12747   TexT prefix_txt;
12748 } LocusTagPrefixData, PNTR LocusTagPrefixPtr;
12749 
InsertGeneLocusTagPrefixButton(ButtoN b)12750 static void InsertGeneLocusTagPrefixButton (ButtoN b)
12751 {
12752   LocusTagPrefixPtr ltpp;
12753   CharPtr           prefix;
12754   SeqEntryPtr       sep;
12755 
12756   ltpp = (LocusTagPrefixPtr) GetObjectExtra (b);
12757   if (ltpp == NULL)
12758   {
12759     return;
12760   }
12761 
12762   prefix = SaveStringFromText (ltpp->prefix_txt);
12763   if (!StringHasNoText (prefix))
12764   {
12765     sep = GetTopSeqEntryForEntityID (ltpp->input_entityID);
12766     if (sep != NULL)
12767     {
12768       VisitFeaturesInSep (sep, prefix, InsertGeneLocusTagPrefixCallback);
12769     }
12770 
12771   }
12772   prefix = MemFree (prefix);
12773   ObjMgrSetDirtyFlag (ltpp->input_entityID, TRUE);
12774   ObjMgrSendMsg (OM_MSG_UPDATE, ltpp->input_entityID, 0, 0);
12775   Remove (ltpp->form);
12776   Update ();
12777 }
12778 
InsertGeneLocusTagPrefix(IteM i)12779 extern void InsertGeneLocusTagPrefix (IteM i)
12780 {
12781   BaseFormPtr        bfp;
12782   WindoW             w;
12783   LocusTagPrefixPtr  ltpp;
12784   GrouP              h, g, c;
12785   ButtoN             b;
12786 
12787 #ifdef WIN_MAC
12788   bfp = currentFormDataPtr;
12789 #else
12790   bfp = GetObjectExtra (i);
12791 #endif
12792   if (bfp == NULL) return;
12793 
12794   ltpp = (LocusTagPrefixPtr) MemNew (sizeof (LocusTagPrefixData));
12795   if (ltpp == NULL) return;
12796   ltpp->input_entityID = bfp->input_entityID;
12797 
12798   w = FixedWindow (-50, -33, -10, -10, "Feature Evidence", StdCloseWindowProc);
12799   SetObjectExtra (w, ltpp, StdCleanupFormProc);
12800   ltpp->form = (ForM) w;
12801   h = HiddenGroup (w, -1, 0, NULL);
12802   g = HiddenGroup (h, 2, 0, NULL);
12803   StaticPrompt (g, "Prefix for Gene Locus Tag", 0, 0, programFont, 'c');
12804   ltpp->prefix_txt = DialogText (g, "", 14, NULL);
12805   c = HiddenGroup (h, 2, 0, NULL);
12806   b = PushButton (c, "Accept", InsertGeneLocusTagPrefixButton);
12807   SetObjectExtra (b, ltpp, NULL);
12808   PushButton (c, "Cancel", StdCancelButtonProc);
12809 
12810   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
12811   RealizeWindow (w);
12812   Show (w);
12813   Update ();
12814 }
12815 
12816 
SetPrimerBindPairStrandsCallback(BioseqPtr bsp,Pointer userdata)12817 static void SetPrimerBindPairStrandsCallback (BioseqPtr bsp, Pointer userdata)
12818 {
12819   SeqFeatPtr        primer_1 = NULL, primer_2 = NULL, sfp;
12820   SeqMgrFeatContext context;
12821   Uint1             first_strand, second_strand;
12822 
12823   if (bsp == NULL)
12824   {
12825     return;
12826   }
12827 
12828   /* must have exactly two primer_bind features */
12829   primer_1 = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_primer_bind, &context);
12830   if (primer_1 == NULL)
12831   {
12832     return;
12833   }
12834   primer_2 = SeqMgrGetNextFeature (bsp, primer_1, 0, FEATDEF_primer_bind, &context);
12835   if (primer_2 == NULL)
12836   {
12837     return;
12838   }
12839 
12840   /* if there are three, must abandon */
12841   sfp = SeqMgrGetNextFeature (bsp, primer_1, 0, FEATDEF_primer_bind, &context);
12842   if (sfp != NULL)
12843   {
12844     return;
12845   }
12846 
12847   first_strand = SeqLocStrand (primer_1->location);
12848   second_strand = SeqLocStrand (primer_2->location);
12849 
12850   if (first_strand == Seq_strand_minus)
12851   {
12852     if (second_strand == Seq_strand_minus)
12853     {
12854       SetSeqLocStrand (primer_2->location, Seq_strand_plus);
12855     }
12856   }
12857   else
12858   {
12859     if (second_strand != Seq_strand_minus)
12860     {
12861       SetSeqLocStrand (primer_2->location, Seq_strand_minus);
12862     }
12863   }
12864 }
12865 
SetPrimerBindPairStrands(IteM i)12866 extern void SetPrimerBindPairStrands (IteM i)
12867 {
12868   BaseFormPtr       bfp;
12869   SeqEntryPtr       sep;
12870 
12871 #ifdef WIN_MAC
12872   bfp = currentFormDataPtr;
12873 #else
12874   bfp = GetObjectExtra (i);
12875 #endif
12876   if (bfp == NULL) return;
12877 
12878   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
12879   if (sep == NULL) return;
12880 
12881   VisitBioseqsInSep (sep, NULL, SetPrimerBindPairStrandsCallback);
12882 
12883   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
12884   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
12885   Update ();
12886 }
12887 
12888 /* This function returns the length change, so that the start
12889  * position for subsequent features can be adjusted.
12890  */
12891 static Int4
FindAndConvertGapFeat(BioseqPtr bsp,Int4 start,Boolean make_known)12892 FindAndConvertGapFeat
12893 (BioseqPtr  bsp,
12894  Int4       start,
12895  Boolean    make_known)
12896 {
12897   ValNodePtr vnp;
12898   SeqLocPtr  slp;
12899   SeqLitPtr  litp;
12900   Int4       currpos = 0, len_diff = 0;
12901 
12902   if (bsp == NULL || bsp->repr != Seq_repr_delta
12903       || start < 0)
12904   {
12905     return 0;
12906   }
12907   for (vnp = (ValNodePtr)(bsp->seq_ext);
12908        vnp != NULL && currpos < start;
12909        vnp = vnp->next)
12910   {
12911     if (vnp->choice == 1)
12912     {
12913       slp = (SeqLocPtr) vnp->data.ptrvalue;
12914       if (slp == NULL) continue;
12915       currpos += SeqLocLen (slp);
12916     }
12917     else if (vnp->choice == 2)
12918     {
12919       litp = (SeqLitPtr) vnp->data.ptrvalue;
12920       if (litp == NULL) continue;
12921       currpos += litp->length;
12922     }
12923   }
12924 
12925   if (currpos < start || vnp == NULL || vnp->choice != 2)
12926   {
12927     return 0;
12928   }
12929 
12930   litp = (SeqLitPtr) vnp->data.ptrvalue;
12931   if (litp == NULL)
12932   {
12933     return 0;
12934   }
12935 
12936   if (make_known)
12937   {
12938     litp->fuzz = IntFuzzFree (litp->fuzz);
12939     len_diff = 0;
12940   }
12941   else if (litp->fuzz == NULL)
12942   {
12943     litp->fuzz = IntFuzzNew ();
12944     litp->fuzz->choice = 4;
12945     len_diff = litp->length - 100;
12946     litp->length = 100;
12947     bsp->length -= len_diff;
12948   }
12949   return len_diff;
12950 }
12951 
12952 typedef struct gapadjust
12953 {
12954   Int4 adjust_start;
12955   Int4 adjust_len;
12956 } GapAdjustData, PNTR GapAdjustPtr;
12957 
GetAdjustedGapStart(Int4 feat_left,ValNodePtr prev_adjust)12958 static Int4 GetAdjustedGapStart (Int4 feat_left, ValNodePtr prev_adjust)
12959 {
12960   GapAdjustPtr p;
12961   Int4         new_feat_left;
12962 
12963   new_feat_left = feat_left;
12964   while (prev_adjust != NULL)
12965   {
12966     p = (GapAdjustPtr) prev_adjust->data.ptrvalue;
12967     if (p != NULL && feat_left > p->adjust_start)
12968     {
12969       new_feat_left -= p->adjust_len;
12970     }
12971     prev_adjust = prev_adjust->next;
12972   }
12973   return new_feat_left;
12974 }
12975 
ConvertSelectedGapFeatures(IteM i,Boolean to_known)12976 static void ConvertSelectedGapFeatures (IteM i, Boolean to_known)
12977 {
12978   BaseFormPtr       bfp;
12979   SelStructPtr      sel;
12980   SeqMgrFeatContext fcontext;
12981   BioseqPtr         bsp;
12982   SeqFeatPtr        sfp;
12983   Int4              adjusted_start, len_diff;
12984   ValNodePtr        adjustment_list = NULL;
12985   GapAdjustPtr      p;
12986 
12987 #ifdef WIN_MAC
12988   bfp = currentFormDataPtr;
12989 #else
12990   bfp = GetObjectExtra (i);
12991 #endif
12992   if (bfp == NULL) return;
12993 
12994   sel = ObjMgrGetSelected ();
12995   if (sel == NULL)
12996   {
12997     Message (MSG_ERROR, "Must select gap features to convert!");
12998     return;
12999   }
13000   WatchCursor ();
13001   Update ();
13002   while (sel != NULL)
13003   {
13004     if (sel->entityID == bfp->input_entityID
13005         && sel->itemtype == OBJ_SEQFEAT)
13006     {
13007       sfp = SeqMgrGetDesiredFeature (bfp->input_entityID, NULL, sel->itemID, 0, NULL, &fcontext);
13008       if (sfp != NULL && sfp->idx.subtype == FEATDEF_gap)
13009       {
13010         bsp = BioseqFindFromSeqLoc (sfp->location);
13011         if (bsp != NULL && bsp->repr == Seq_repr_delta)
13012         {
13013           adjusted_start = GetAdjustedGapStart (fcontext.left, adjustment_list);
13014           len_diff = FindAndConvertGapFeat (bsp, adjusted_start, to_known);
13015           if (len_diff != 0)
13016           {
13017             p = (GapAdjustPtr) MemNew (sizeof (GapAdjustData));
13018             if (p != NULL)
13019             {
13020               p->adjust_start = fcontext.left;
13021               p->adjust_len = len_diff;
13022               ValNodeAddPointer (&adjustment_list, 0, p);
13023             }
13024           }
13025         }
13026       }
13027     }
13028     sel = sel->next;
13029   }
13030 
13031   adjustment_list = ValNodeFreeData (adjustment_list);
13032   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13033   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13034   ArrowCursor ();
13035   Update ();
13036 }
13037 
13038 
13039 typedef struct convertgaptounknown
13040 {
13041   FEATURE_FORM_BLOCK
13042 
13043   TexT start_unknown_txt;
13044   Int4 start_unknown;
13045 } ConvertGapToUnknownData, PNTR ConvertGapToUnknownPtr;
13046 
13047 
FixDeltaFeatures(BioseqPtr bsp,Int4 offset,Int4 len_diff)13048 static void FixDeltaFeatures (BioseqPtr bsp, Int4 offset, Int4 len_diff)
13049 {
13050   SeqFeatPtr             sfp;
13051   SeqMgrFeatContext      fcontext;
13052 
13053   if (len_diff == 0)
13054   {
13055     return;
13056   }
13057   for (sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
13058        sfp != NULL;
13059        sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext))
13060   {
13061     AdjustFeatureForGapChange (sfp, bsp, offset, len_diff);
13062   }
13063 }
13064 
13065 
ConvertGapFeaturesToUnknownCallback(BioseqPtr bsp,Pointer userdata)13066 static void ConvertGapFeaturesToUnknownCallback (BioseqPtr bsp, Pointer userdata)
13067 {
13068   ConvertGapToUnknownPtr cgtup;
13069   DeltaSeqPtr            dsp;
13070   SeqLitPtr              slip;
13071   Int4                   len_diff;
13072   Int4                   offset = 0, add_len;
13073 
13074   if (bsp == NULL || bsp->repr != Seq_repr_delta
13075       || bsp->seq_ext_type != 4 || bsp->seq_ext == NULL
13076       || userdata == NULL)
13077   {
13078     return;
13079   }
13080 
13081   cgtup = (ConvertGapToUnknownPtr) userdata;
13082 
13083   dsp = (DeltaSeqPtr) bsp->seq_ext;
13084   while (dsp != NULL)
13085   {
13086     add_len = GetDeltaSeqLen (dsp);
13087     if (IsDeltaSeqGap (dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp) && add_len >= cgtup->start_unknown)
13088     {
13089       slip = (SeqLitPtr) (dsp->data.ptrvalue);
13090       len_diff = slip->length - 100;
13091       slip->length = 100;
13092       if (slip->fuzz != NULL)
13093       {
13094         slip->fuzz = IntFuzzFree (slip->fuzz);
13095       }
13096       slip->fuzz = IntFuzzNew();
13097       slip->fuzz->choice = 4;
13098 
13099       if (len_diff > 0) {
13100         FixDeltaFeatures (bsp, offset, len_diff);
13101       }
13102       add_len -= len_diff;
13103     }
13104     offset += add_len;
13105     dsp = dsp->next;
13106   }
13107   bsp->length = offset;
13108 }
13109 
ConvertGapFeaturesToUnknownButton(ButtoN b)13110 static void ConvertGapFeaturesToUnknownButton (ButtoN b)
13111 {
13112   ConvertGapToUnknownPtr cgtup;
13113   SeqEntryPtr            sep;
13114   CharPtr                str;
13115 
13116   cgtup = (ConvertGapToUnknownPtr) GetObjectExtra (b);
13117   if (cgtup == NULL)
13118   {
13119     return;
13120   }
13121 
13122   str = SaveStringFromText (cgtup->start_unknown_txt);
13123   if (StringHasNoText (str))
13124   {
13125     str = MemFree (str);
13126     return;
13127   }
13128 
13129   cgtup->start_unknown = atoi (str);
13130   str = MemFree (str);
13131   if (cgtup->start_unknown <= 0)
13132   {
13133     return;
13134   }
13135 
13136   WatchCursor();
13137   Update();
13138 
13139   sep = GetTopSeqEntryForEntityID (cgtup->input_entityID);
13140 
13141   VisitBioseqsInSep (sep, cgtup, ConvertGapFeaturesToUnknownCallback);
13142 
13143   ObjMgrSetDirtyFlag (cgtup->input_entityID, TRUE);
13144   ObjMgrSendMsg (OM_MSG_UPDATE, cgtup->input_entityID, 0, 0);
13145   Remove (cgtup->form);
13146   ArrowCursor ();
13147   Update ();
13148 }
13149 
ConvertGapFeaturesToUnknown(IteM i)13150 extern void ConvertGapFeaturesToUnknown (IteM i)
13151 {
13152   BaseFormPtr            bfp;
13153   ConvertGapToUnknownPtr cgtup;
13154   WindoW                 w;
13155   GrouP                  h, g, c;
13156   ButtoN                 b;
13157 
13158 #ifdef WIN_MAC
13159   bfp = currentFormDataPtr;
13160 #else
13161   bfp = GetObjectExtra (i);
13162 #endif
13163   if (bfp == NULL) return;
13164 
13165   cgtup = (ConvertGapToUnknownPtr) MemNew (sizeof (ConvertGapToUnknownData));
13166   if (cgtup == NULL) return;
13167   w = FixedWindow (-50, -33, -10, -10, "Convert Known Length Gaps to Unknown", StdCloseWindowProc);
13168   SetObjectExtra (w, cgtup, StdCleanupFormProc);
13169   cgtup->form = (ForM) w;
13170   cgtup->input_entityID = bfp->input_entityID;
13171 
13172   h = HiddenGroup (w, -1, 0, NULL);
13173   SetGroupSpacing (h, 10, 10);
13174   g = HiddenGroup (h, 2, 0, NULL);
13175   StaticPrompt (g, "Convert gaps longer or equal to", 0, popupMenuHeight, programFont, 'r');
13176   cgtup->start_unknown_txt = DialogText (g, "100", 10, NULL);
13177 
13178   c = HiddenGroup (h, 2, 0, NULL);
13179   SetGroupSpacing (c, 10, 10);
13180   b = PushButton (c, "Accept", ConvertGapFeaturesToUnknownButton);
13181   SetObjectExtra (b, cgtup, NULL);
13182   PushButton (c, "Cancel", StdCancelButtonProc);
13183 
13184   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
13185 
13186   Show (w);
13187 }
13188 
13189 
13190 typedef struct changegaplen
13191 {
13192   FEATURE_FORM_BLOCK
13193 
13194   TexT   length_txt;
13195   Int4   length;
13196 } ChangeGapLenData, PNTR ChangeGapLenPtr;
13197 
13198 
ChangeOneGapLength(SeqFeatPtr sfp,Int4 new_length)13199 static void ChangeOneGapLength (SeqFeatPtr sfp, Int4 new_length)
13200 {
13201   BioseqPtr   bsp;
13202   DeltaSeqPtr dsp;
13203   SeqLitPtr              slip;
13204   SeqLocPtr              slp;
13205   Int4                   len_diff = 0;
13206   Int4                   offset = 0, gap_start;
13207 
13208   if (sfp == NULL || sfp->idx.subtype != FEATDEF_gap || new_length < 0
13209       || new_length == SeqLocLen (sfp->location))
13210   {
13211     return;
13212   }
13213 
13214   bsp = BioseqFindFromSeqLoc (sfp->location);
13215   if (bsp == NULL || bsp->repr != Seq_repr_delta
13216       || bsp->seq_ext_type != 4 || bsp->seq_ext == NULL)
13217   {
13218     return;
13219   }
13220 
13221   gap_start = SeqLocStart (sfp->location);
13222 
13223   dsp = (DeltaSeqPtr) bsp->seq_ext;
13224   while (dsp != NULL && offset < gap_start)
13225   {
13226     if (dsp->choice == 1 && dsp->data.ptrvalue != NULL)
13227     {
13228       slp = (SeqLocPtr) dsp->data.ptrvalue;
13229       offset += SeqLocLen (slp);
13230     }
13231     else if (dsp->choice == 2 && dsp->data.ptrvalue != NULL)
13232     {
13233       slip = (SeqLitPtr) (dsp->data.ptrvalue);
13234       offset += slip->length;
13235     }
13236     dsp = dsp->next;
13237   }
13238 
13239   if (offset == gap_start && dsp != NULL && dsp->choice == 2 && dsp->data.ptrvalue != NULL)
13240   {
13241     slip = (SeqLitPtr) (dsp->data.ptrvalue);
13242     if (IsDeltaSeqKnownGap (dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp))
13243     {
13244       len_diff = slip->length - new_length;
13245       slip->length = new_length;
13246       FixDeltaFeatures (bsp, offset, len_diff);
13247     }
13248   }
13249 
13250 
13251   bsp->length -= len_diff;
13252 }
13253 
13254 
ChangeGapLength(ButtoN b)13255 static void ChangeGapLength (ButtoN b)
13256 {
13257   ChangeGapLenPtr   cglp;
13258   SelStructPtr      sel;
13259   SeqFeatPtr        sfp;
13260   SeqMgrFeatContext fcontext;
13261   CharPtr           str;
13262 
13263   cglp = (ChangeGapLenPtr) GetObjectExtra (b);
13264   if (cglp == NULL)
13265   {
13266     return;
13267   }
13268 
13269   cglp->length = 0;
13270   str = SaveStringFromText (cglp->length_txt);
13271   if (!StringHasNoText (str))
13272   {
13273     cglp->length = atoi (str);
13274   }
13275   str = MemFree (str);
13276   if (cglp->length < 1)
13277   {
13278     Message (MSG_ERROR, "Must select a gap size greater than zero!");
13279     return;
13280   }
13281 
13282   sel = ObjMgrGetSelected ();
13283   if (sel == NULL)
13284   {
13285     Message (MSG_ERROR, "No gaps selected!");
13286     return;
13287   }
13288   WatchCursor ();
13289   Update ();
13290   while (sel != NULL)
13291   {
13292     if (sel->entityID == cglp->input_entityID
13293         && sel->itemtype == OBJ_SEQFEAT)
13294     {
13295       sfp = SeqMgrGetDesiredFeature (cglp->input_entityID, NULL, sel->itemID, 0, NULL, &fcontext);
13296       if (sfp != NULL && sfp->idx.subtype == FEATDEF_gap)
13297       {
13298         ChangeOneGapLength (sfp, cglp->length);
13299       }
13300     }
13301     sel = sel->next;
13302   }
13303 
13304   ObjMgrSetDirtyFlag (cglp->input_entityID, TRUE);
13305   ObjMgrSendMsg (OM_MSG_UPDATE, cglp->input_entityID, 0, 0);
13306   ArrowCursor ();
13307   Update ();
13308 
13309   if (!GetStatus (cglp->leave_dlg_up))
13310   {
13311     Remove (cglp->form);
13312   }
13313 }
13314 
ChangeKnownGapLength(IteM i)13315 extern void ChangeKnownGapLength (IteM i)
13316 {
13317   BaseFormPtr     bfp;
13318   ChangeGapLenPtr cglp;
13319   WindoW          w;
13320   GrouP           h, g, c;
13321   ButtoN          b;
13322 
13323 #ifdef WIN_MAC
13324   bfp = currentFormDataPtr;
13325 #else
13326   bfp = GetObjectExtra (i);
13327 #endif
13328   if (bfp == NULL) return;
13329 
13330   cglp = (ChangeGapLenPtr) MemNew (sizeof (ChangeGapLenData));
13331   if (cglp == NULL) return;
13332   w = FixedWindow (-50, -33, -10, -10, "Change Length of Selected Known Length Gaps", StdCloseWindowProc);
13333   SetObjectExtra (w, cglp, StdCleanupFormProc);
13334   cglp->form = (ForM) w;
13335   cglp->input_entityID = bfp->input_entityID;
13336 
13337   h = HiddenGroup (w, -1, 0, NULL);
13338   SetGroupSpacing (h, 10, 10);
13339   g = HiddenGroup (h, 2, 0, NULL);
13340   StaticPrompt (g, "Change length to", 0, popupMenuHeight, programFont, 'r');
13341   cglp->length_txt = DialogText (g, "100", 10, NULL);
13342 
13343   c = HiddenGroup (h, 3, 0, NULL);
13344   SetGroupSpacing (c, 10, 10);
13345   b = PushButton (c, "Accept", ChangeGapLength);
13346   SetObjectExtra (b, cglp, NULL);
13347   PushButton (c, "Cancel", StdCancelButtonProc);
13348   cglp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
13349 
13350   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
13351 
13352   Show (w);
13353 }
13354 
ConvertSelectedGapFeaturesToKnown(IteM i)13355 extern void ConvertSelectedGapFeaturesToKnown (IteM i)
13356 {
13357   ConvertSelectedGapFeatures (i, TRUE);
13358 }
13359 
ConvertSelectedGapFeaturesToUnknown(IteM i)13360 extern void ConvertSelectedGapFeaturesToUnknown (IteM i)
13361 {
13362   ConvertSelectedGapFeatures (i, FALSE);
13363 }
13364 
13365 
CountNsAtEndOfSeqLit(SeqLitPtr slip,Uint2 which_end)13366 static Int4 CountNsAtEndOfSeqLit (SeqLitPtr slip, Uint2 which_end)
13367 {
13368   Int2         residue;
13369   Int4         change_len = 0;
13370 
13371   if (slip == NULL || slip->seq_data == NULL || slip->seq_data_type == Seq_code_gap)
13372   {
13373     return 0;
13374   }
13375 
13376   if (slip->seq_data_type != Seq_code_iupacna)
13377   {
13378     slip->seq_data = (SeqDataPtr) BSConvertSeq((ByteStorePtr) slip->seq_data, Seq_code_iupacna,
13379                           slip->seq_data_type,
13380                           slip->length);
13381     slip->seq_data_type = Seq_code_iupacna;
13382   }
13383 
13384   if (which_end == SEQLOC_LEFT_END)
13385   {
13386     BSSeek((ByteStorePtr) slip->seq_data, 0, SEEK_SET);
13387   }
13388   else
13389   {
13390     BSSeek((ByteStorePtr) slip->seq_data, slip->length - 1, SEEK_SET);
13391   }
13392 
13393   residue = BSGetByte((ByteStorePtr) slip->seq_data);
13394   while (change_len < slip->length && residue == 'N')
13395   {
13396     change_len++;
13397     if (which_end != SEQLOC_LEFT_END)
13398     {
13399       BSSeek ((ByteStorePtr) slip->seq_data, slip->length - change_len - 1, SEEK_SET);
13400     }
13401     residue = BSGetByte ((ByteStorePtr) slip->seq_data);
13402   }
13403 
13404   return change_len;
13405 }
13406 
RemoveSeqLitEnd(SeqLitPtr slip,Int4 change_len,Uint2 which_end)13407 static void RemoveSeqLitEnd (SeqLitPtr slip, Int4 change_len, Uint2 which_end)
13408 {
13409   ByteStorePtr bs_new;
13410 
13411   if (slip == NULL || change_len < 1)
13412   {
13413     return;
13414   }
13415 
13416   if (slip->seq_data_type == Seq_code_gap) return;
13417 
13418   if (slip->seq_data_type != Seq_code_iupacna)
13419   {
13420     slip->seq_data = (SeqDataPtr) BSConvertSeq((ByteStorePtr) slip->seq_data, Seq_code_iupacna,
13421                                   slip->seq_data_type,
13422                                   slip->length);
13423     slip->seq_data_type = Seq_code_iupacna;
13424   }
13425   bs_new = BSNew (slip->length - change_len);
13426   if (which_end == SEQLOC_LEFT_END)
13427   {
13428     BSSeek ((ByteStorePtr) slip->seq_data, change_len, SEEK_SET);
13429   }
13430   else
13431   {
13432     BSSeek((ByteStorePtr) slip->seq_data, 0, SEEK_SET);
13433   }
13434   BSInsertFromBS (bs_new, (ByteStorePtr) slip->seq_data, slip->length - change_len);
13435   slip->seq_data = SeqDataFree (slip->seq_data, slip->seq_data_type);
13436   slip->seq_data = (SeqDataPtr) bs_new;
13437   slip->length -= change_len;
13438 }
13439 
ExpandGapsToIncludeFlankingNs(BioseqPtr bsp,Pointer userdata)13440 static void ExpandGapsToIncludeFlankingNs (BioseqPtr bsp, Pointer userdata)
13441 {
13442   DeltaSeqPtr  dsp, prev_dsp = NULL, next_dsp = NULL, prev_prev_dsp = NULL;
13443   Int4         change_len;
13444   SeqLitPtr    slip, prev_slip = NULL, next_slip;
13445 
13446   if (bsp == NULL || bsp->repr != Seq_repr_delta
13447       || bsp->seq_ext_type != 4 || bsp->seq_ext == NULL)
13448   {
13449     return;
13450   }
13451 
13452   dsp = bsp->seq_ext;
13453   while (dsp != NULL)
13454   {
13455     next_dsp = dsp->next;
13456     /* look for gap of known length */
13457     if (IsDeltaSeqKnownGap(dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp))
13458     {
13459       /* check for Ns before gap of known length */
13460       if (prev_dsp != NULL && prev_dsp->choice == 2
13461           && prev_dsp->data.ptrvalue != NULL
13462           && !IsDeltaSeqGap (prev_dsp))
13463       {
13464         slip = (SeqLitPtr) dsp->data.ptrvalue;
13465         prev_slip = (SeqLitPtr) prev_dsp->data.ptrvalue;
13466 
13467         change_len = CountNsAtEndOfSeqLit (prev_slip, SEQLOC_RIGHT_END);
13468         if (change_len > 0)
13469         {
13470           RemoveSeqLitEnd (prev_slip, change_len, SEQLOC_RIGHT_END);
13471           slip->length += change_len;
13472           if (prev_slip->length == 0) {
13473             if (prev_prev_dsp == NULL) {
13474               bsp->seq_ext = dsp;
13475             } else {
13476               prev_prev_dsp->next = dsp;
13477             }
13478             prev_dsp->next = NULL;
13479             prev_dsp = DeltaSeqFree (prev_dsp);
13480             prev_dsp = dsp;
13481           }
13482         }
13483       } else {
13484         prev_prev_dsp = prev_dsp;
13485         prev_dsp = dsp;
13486       }
13487       /* check for Ns after gap of known length */
13488       if (dsp->next != NULL && dsp->next->choice == 2
13489           && dsp->next->data.ptrvalue != NULL
13490           && !IsDeltaSeqGap (dsp->next))
13491       {
13492         slip = (SeqLitPtr) dsp->data.ptrvalue;
13493         next_slip = (SeqLitPtr) dsp->next->data.ptrvalue;
13494         change_len = CountNsAtEndOfSeqLit (next_slip, SEQLOC_LEFT_END);
13495 
13496         if (change_len < next_slip->length)
13497         {
13498           RemoveSeqLitEnd (next_slip, change_len, SEQLOC_LEFT_END);
13499           slip->length += change_len;
13500         }
13501         else
13502         {
13503           dsp->next = next_dsp->next;
13504           next_dsp->next = NULL;
13505           next_dsp = DeltaSeqFree (next_dsp);
13506           next_dsp = dsp->next;
13507         }
13508       }
13509     } else {
13510       prev_prev_dsp = prev_dsp;
13511       prev_dsp = dsp;
13512     }
13513     dsp = next_dsp;
13514   }
13515   BioseqPack (bsp);
13516 }
13517 
AddFlankingNsToKnownLengthGaps(IteM i)13518 extern void AddFlankingNsToKnownLengthGaps (IteM i)
13519 {
13520   BaseFormPtr       bfp;
13521   SeqEntryPtr       sep;
13522 
13523 #ifdef WIN_MAC
13524   bfp = currentFormDataPtr;
13525 #else
13526   bfp = GetObjectExtra (i);
13527 #endif
13528   if (bfp == NULL) return;
13529 
13530   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13531 
13532   WatchCursor ();
13533   Update ();
13534   VisitBioseqsInSep (sep, NULL, ExpandGapsToIncludeFlankingNs);
13535 
13536   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13537   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13538   ArrowCursor ();
13539   Update ();
13540 }
13541 
13542 
CanCombineDeltaSeq(DeltaSeqPtr dsp1,DeltaSeqPtr dsp2)13543 static Boolean CanCombineDeltaSeq (DeltaSeqPtr dsp1, DeltaSeqPtr dsp2)
13544 {
13545 
13546   if (dsp1 == NULL || dsp2 == NULL || dsp1->choice != 2 || dsp2->choice != 2
13547       || dsp1->data.ptrvalue == NULL || dsp2->data.ptrvalue == NULL
13548       || DoesDeltaSeqHaveGapTypeOrLinkage(dsp1) || DoesDeltaSeqHaveGapTypeOrLinkage(dsp2)) {
13549     return FALSE;
13550   } else {
13551     return TRUE;
13552   }
13553 }
13554 
13555 
CombineAdjacentGapsOnBioseq(BioseqPtr bsp,Pointer userdata)13556 extern void CombineAdjacentGapsOnBioseq (BioseqPtr bsp, Pointer userdata)
13557 {
13558   SeqLitPtr  litp, pitp;
13559   Boolean    l_unknown, p_unknown;
13560   Int4       offset = 0;
13561   Int4       len_diff;
13562   SeqFeatPtr sfp;
13563   SeqMgrFeatContext fcontext;
13564   DeltaSeqPtr prev, last;
13565 
13566   if (bsp == NULL || bsp->repr != Seq_repr_delta)
13567   {
13568     return;
13569   }
13570 
13571   /* combine adjacent gaps */
13572   prev = (DeltaSeqPtr) bsp->seq_ext;
13573   if (prev == NULL) return;
13574   last = prev->next;
13575   while (last != NULL) {
13576     if (IsDeltaSeqGap (prev) && IsDeltaSeqGap (last) && CanCombineDeltaSeq (prev, last)) {
13577       pitp = (SeqLitPtr) prev->data.ptrvalue;
13578       litp = (SeqLitPtr) last->data.ptrvalue;
13579       p_unknown = IsDeltaSeqUnknownGap (prev);
13580       l_unknown = IsDeltaSeqUnknownGap (last);
13581       len_diff = 0;
13582       if (p_unknown && l_unknown) {
13583         /* combine two unknown length gaps to make one unknown length gap */
13584         len_diff = litp->length;
13585       } else if (!p_unknown && !l_unknown) {
13586         /* combine two known length gaps into one known length gap */
13587         pitp->length += litp->length;
13588       } else {
13589         if (l_unknown) {
13590           /* swap gaps to put unknown length gap into prev */
13591           prev->data.ptrvalue = litp;
13592           last->data.ptrvalue = pitp;
13593           pitp = (SeqLitPtr) prev->data.ptrvalue;
13594           litp = (SeqLitPtr) last->data.ptrvalue;
13595         }
13596         /* remove length of known gap */
13597         len_diff = litp->length;
13598       }
13599       prev->next = last->next;
13600       last->next = NULL;
13601       SeqLitFree (litp);
13602       MemFree (last);
13603       last = prev;
13604 
13605       if (len_diff > 0) {
13606         FixDeltaFeatures (bsp, offset, len_diff);
13607         bsp->length -= len_diff;
13608       }
13609     } else {
13610       offset += GetDeltaSeqLen (prev);
13611     }
13612     prev = last;
13613     last = last->next;
13614   }
13615 
13616   /* adjust coding region locations for unknown gaps */
13617   for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext);
13618        sfp != NULL;
13619        sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext))
13620   {
13621     AdjustCDSLocationsForUnknownGapsCallback (sfp, NULL);
13622   }
13623 }
13624 
CombineAdjacentGaps(IteM i)13625 extern void CombineAdjacentGaps (IteM i)
13626 {
13627   BaseFormPtr       bfp;
13628   SeqEntryPtr       sep;
13629 
13630 #ifdef WIN_MAC
13631   bfp = currentFormDataPtr;
13632 #else
13633   bfp = GetObjectExtra (i);
13634 #endif
13635   if (bfp == NULL) return;
13636 
13637   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13638 
13639   WatchCursor ();
13640   Update ();
13641   VisitBioseqsInSep (sep, NULL, CombineAdjacentGapsOnBioseq);
13642 
13643   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13644   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13645   ArrowCursor ();
13646   Update ();
13647 }
13648 
MarkPseudoGenesCallback(SeqFeatPtr sfp,Pointer userdata)13649 static void MarkPseudoGenesCallback (SeqFeatPtr sfp, Pointer userdata)
13650 {
13651   SeqFeatPtr gene;
13652   GBQualPtr gbqual, gg;
13653 
13654   if (sfp == NULL || ! sfp->pseudo
13655       || sfp->data.choice == SEQFEAT_GENE
13656       || SeqMgrGetGeneXref (sfp) != NULL)
13657   {
13658     return;
13659   }
13660   gbqual = sfp->qual;
13661   while (gbqual != NULL && StringICmp (gbqual->qual, "pseudogene") != 0) {
13662     gbqual = gbqual->next;
13663   }
13664 
13665   gene = SeqMgrGetOverlappingGene (sfp->location, NULL);
13666   if (gene != NULL)
13667   {
13668     gene->pseudo = TRUE;
13669     if (gbqual != NULL) {
13670       gg = gene->qual;
13671       while (gg != NULL && StringICmp (gg->qual, "pseudogene") != 0) {
13672         gg = gg->next;
13673       }
13674       if (gg == NULL) {
13675         gg = GBQualNew ();
13676         gg->qual = StringSave ("pseudogene");
13677         gg->val = StringSave (gbqual->val);
13678         gg->next = gene->qual;
13679         gene->qual = gg;
13680       } else {
13681         gg->val = MemFree (gg->val);
13682         gg->val = StringSave (gbqual->val);
13683       }
13684     }
13685   }
13686 }
13687 
MarkGenesWithPseudoFeaturesPseudo(IteM i)13688 extern void MarkGenesWithPseudoFeaturesPseudo (IteM i)
13689 {
13690   BaseFormPtr       bfp;
13691   SeqEntryPtr       sep;
13692 
13693 #ifdef WIN_MAC
13694   bfp = currentFormDataPtr;
13695 #else
13696   bfp = GetObjectExtra (i);
13697 #endif
13698   if (bfp == NULL) return;
13699 
13700   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13701 
13702   WatchCursor ();
13703   Update ();
13704   VisitFeaturesInSep (sep, NULL, MarkPseudoGenesCallback);
13705 
13706   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13707   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13708   ArrowCursor ();
13709   Update ();
13710 
13711 }
13712 
RemoveOneNomenclature(UserObjectPtr PNTR puop)13713 static void RemoveOneNomenclature (UserObjectPtr PNTR puop)
13714 {
13715   UserObjectPtr  uop, obj, prev_obj, next_obj;
13716   UserFieldPtr   prev_ufp, next_ufp, ufp;
13717   ObjectIdPtr    oip;
13718 
13719   if (puop == NULL || *puop == NULL) return;
13720   uop = *puop;
13721 
13722   for (ufp = uop->data, prev_ufp = NULL;
13723        ufp != NULL;
13724        ufp = next_ufp) {
13725     next_ufp = ufp->next;
13726     if (ufp->choice == 6) {
13727       obj = (UserObjectPtr) ufp->data.ptrvalue;
13728       RemoveOneNomenclature (&obj);
13729       ufp->data.ptrvalue = obj;
13730     } else if (ufp->choice == 12) {
13731       for (obj = (UserObjectPtr) ufp->data.ptrvalue, prev_obj = NULL;
13732            obj != NULL;
13733            obj = next_obj) {
13734         next_obj = obj->next;
13735         RemoveOneNomenclature (&obj);
13736         if (obj == NULL)
13737         {
13738           if (prev_obj == NULL)
13739           {
13740             ufp->data.ptrvalue = next_obj;
13741           }
13742           else
13743           {
13744             prev_obj->next = next_obj;
13745           }
13746           obj = UserObjectFree (obj);
13747         }
13748         else
13749         {
13750           prev_obj = obj;
13751         }
13752       }
13753     }
13754     if ((ufp->choice == 6 || ufp->choice == 12) && ufp->data.ptrvalue == NULL)
13755     {
13756       if (prev_ufp == NULL)
13757       {
13758         uop->data = ufp->next;
13759       }
13760       else
13761       {
13762         prev_ufp->next = ufp->next;
13763       }
13764       ufp = UserFieldFree (ufp);
13765     }
13766     else
13767     {
13768       prev_ufp = ufp;
13769     }
13770   }
13771 
13772   oip = uop->type;
13773   if (oip != NULL && StringCmp (oip->str, "OfficialNomenclature") == 0)
13774   {
13775     uop = UserObjectFree (uop);
13776     *puop = uop;
13777   }
13778 }
13779 
RemoveNomenclatureCallback(SeqFeatPtr sfp,Pointer userdata)13780 static void RemoveNomenclatureCallback (SeqFeatPtr sfp, Pointer userdata)
13781 {
13782   UserObjectPtr uop;
13783   GeneRefPtr    grp;
13784 
13785   if (sfp == NULL) {
13786     return;
13787   }
13788 
13789   if (sfp->ext != NULL) {
13790     uop = sfp->ext;
13791     RemoveOneNomenclature (&uop);
13792     sfp->ext = uop;
13793   }
13794   if (sfp->data.choice == SEQFEAT_GENE
13795       && (grp = (GeneRefPtr) sfp->data.value.ptrvalue) != NULL
13796       && grp->formal_name != NULL) {
13797     grp->formal_name = GeneNomenclatureFree (grp->formal_name);
13798   }
13799 }
13800 
RemoveNomenclature(IteM i)13801 extern void RemoveNomenclature (IteM i)
13802 {
13803   BaseFormPtr       bfp;
13804   SeqEntryPtr       sep;
13805 
13806 #ifdef WIN_MAC
13807   bfp = currentFormDataPtr;
13808 #else
13809   bfp = GetObjectExtra (i);
13810 #endif
13811   if (bfp == NULL) return;
13812 
13813   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13814 
13815   WatchCursor ();
13816   Update ();
13817 
13818   VisitFeaturesInSep (sep, NULL, RemoveNomenclatureCallback);
13819 
13820   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13821   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13822   ArrowCursor ();
13823   Update ();
13824 }
13825 
13826 
RemoveUnindexedFeaturesInSeqEntry(SeqEntryPtr sep,Uint2 entityID)13827 static void RemoveUnindexedFeaturesInSeqEntry (SeqEntryPtr sep, Uint2 entityID)
13828 {
13829   BioseqPtr         bsp;
13830   BioseqSetPtr      bssp;
13831   SeqAnnotPtr       sap = NULL;
13832   SeqFeatPtr        sfp;
13833   SeqMgrFeatContext context;
13834 
13835   if (sep == NULL || sep->data.ptrvalue == NULL)
13836   {
13837 	return;
13838   }
13839 
13840   if (IS_Bioseq(sep))
13841   {
13842 	bsp = (BioseqPtr) sep->data.ptrvalue;
13843     sap = bsp->annot;
13844   }
13845   else if (IS_Bioseq_set (sep))
13846   {
13847     bssp = (BioseqSetPtr) sep->data.ptrvalue;
13848 
13849 	sep = bssp->seq_set;
13850 	while (sep != NULL)
13851 	{
13852       RemoveUnindexedFeaturesInSeqEntry (sep, entityID);
13853 	  sep = sep->next;
13854 	}
13855     sap = bssp->annot;
13856   }
13857 
13858   while (sap != NULL)
13859   {
13860     if (sap->type == 1)
13861 	{
13862       sfp = (SeqFeatPtr) sap->data;
13863 	  while (sfp != NULL)
13864 	  {
13865 	    if (SeqMgrGetDesiredFeature (entityID, NULL, 0, 0, sfp, &context) == NULL)
13866 		{
13867 		  sfp->idx.deleteme = TRUE;
13868 		}
13869 		sfp = sfp->next;
13870 	  }
13871 	}
13872 	sap = sap->next;
13873   }
13874 }
13875 
13876 
RemoveUnindexedFeatures(IteM i)13877 extern void RemoveUnindexedFeatures (IteM i)
13878 {
13879   BaseFormPtr       bfp;
13880   SeqEntryPtr       sep;
13881 
13882 #ifdef WIN_MAC
13883   bfp = currentFormDataPtr;
13884 #else
13885   bfp = GetObjectExtra (i);
13886 #endif
13887   if (bfp == NULL) return;
13888 
13889   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13890 
13891   WatchCursor ();
13892   Update ();
13893 
13894   RemoveUnindexedFeaturesInSeqEntry (sep, bfp->input_entityID);
13895 
13896   DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
13897   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13898   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13899   ArrowCursor ();
13900   Update ();
13901 }
13902 
13903 
13904 /* data structure and functions for a generic form displaying a clickable list */
13905 typedef  void  (*Nlm_AddClickableListEntityIDProc) PROTO ((ButtoN, Uint2));
13906 typedef  void  (*Nlm_ReorderResultsProc) PROTO ((ValNodePtr PNTR));
13907 typedef  void  (*Nlm_RelabelResultsProc) PROTO ((ValNodePtr));
13908 
13909 #define CLICKABLE_LIST_FORM_BLOCK   \
13910   FORM_MESSAGE_BLOCK                \
13911   ValNodePtr      clickable_list_data; \
13912   DialoG          clickable_list_dlg;  \
13913   ButtoN          recheck_btn;         \
13914   CharPtr         log_name;            \
13915   Nlm_AddClickableListEntityIDProc add_entity_proc;        \
13916   Nlm_ReorderResultsProc reorder_results_proc; \
13917   Nlm_RelabelResultsProc relabel_results_proc;
13918 
13919 typedef struct clickablelistform {
13920   CLICKABLE_LIST_FORM_BLOCK
13921 } ClickableListFormData, PNTR ClickableListFormPtr;
13922 
CleanupClickableListForm(GraphiC g,VoidPtr data)13923 static void CleanupClickableListForm (GraphiC g, VoidPtr data)
13924 
13925 {
13926   ClickableListFormPtr clfp;
13927 
13928   clfp = (ClickableListFormPtr) data;
13929   if (clfp != NULL) {
13930     clfp->clickable_list_data = FreeClickableList (clfp->clickable_list_data);
13931     ObjMgrFreeUserData (clfp->input_entityID, clfp->procid, clfp->proctype, clfp->userkey);
13932   }
13933   StdCleanupFormProc (g, data);
13934 }
13935 
ClickableListFormMsgFunc(OMMsgStructPtr ommsp)13936 static Int2 LIBCALLBACK ClickableListFormMsgFunc (OMMsgStructPtr ommsp)
13937 {
13938   WindoW                   currentport,
13939                            temport;
13940   OMUserDataPtr            omudp;
13941   ClickableListFormPtr     clfp = NULL;
13942 
13943   omudp = (OMUserDataPtr)(ommsp->omuserdata);
13944   if (omudp == NULL) return OM_MSG_RET_ERROR;
13945   clfp = (ClickableListFormPtr) omudp->userdata.ptrvalue;
13946   if (clfp == NULL) return OM_MSG_RET_ERROR;
13947 
13948   currentport = ParentWindow (clfp->form);
13949   temport = SavePort (currentport);
13950   UseWindow (currentport);
13951   switch (ommsp->message)
13952   {
13953       case OM_MSG_UPDATE:
13954           break;
13955       case OM_MSG_DESELECT:
13956           break;
13957 
13958       case OM_MSG_SELECT:
13959           break;
13960       case OM_MSG_DEL:
13961           clfp->clickable_list_data = FreeClickableList (clfp->clickable_list_data);
13962           PointerToDialog (clfp->clickable_list_dlg, NULL);
13963           break;
13964       case OM_MSG_HIDE:
13965           break;
13966       case OM_MSG_SHOW:
13967           break;
13968       case OM_MSG_FLUSH:
13969           clfp->clickable_list_data = FreeClickableList (clfp->clickable_list_data);
13970           PointerToDialog (clfp->clickable_list_dlg, NULL);
13971           break;
13972       case OM_MSG_CREATE:
13973           /* when a new item is created, refresh */
13974           if (clfp->add_entity_proc != NULL && clfp->recheck_btn != NULL) {
13975               (clfp->add_entity_proc)(clfp->recheck_btn, ommsp->entityID);
13976           }
13977           break;
13978       default:
13979           break;
13980   }
13981   RestorePort (temport);
13982   UseWindow (temport);
13983   return OM_MSG_RET_OK;
13984 }
13985 
13986 
ClickableListFormMessage(ForM f,Int2 mssg)13987 static void ClickableListFormMessage (ForM f, Int2 mssg)
13988 
13989 {
13990   ClickableListFormPtr drfp;
13991 
13992   drfp = (ClickableListFormPtr) GetObjectExtra (f);
13993   if (drfp != NULL) {
13994     switch (mssg) {
13995       case VIB_MSG_EXPORT :
13996         if (drfp->exportform != NULL) {
13997           (drfp->exportform) (f, NULL);
13998         }
13999         break;
14000       case VIB_MSG_PRINT :
14001         break;
14002       case VIB_MSG_CLOSE :
14003         Remove (f);
14004         break;
14005       case VIB_MSG_CUT :
14006       case VIB_MSG_COPY :
14007         SendMessageToDialog (drfp->clickable_list_dlg, VIB_MSG_COPY);
14008         break;
14009       case VIB_MSG_PASTE :
14010         break;
14011       case VIB_MSG_DELETE :
14012         drfp->clickable_list_data = FreeClickableList (drfp->clickable_list_data);
14013         PointerToDialog (drfp->clickable_list_dlg, NULL);
14014         break;
14015       default :
14016         if (drfp->appmessage != NULL) {
14017           drfp->appmessage (f, mssg);
14018         }
14019         break;
14020     }
14021   }
14022 }
14023 
14024 /* Discrepancy Report */
14025 
14026 /* There will only be one Discrepancy Report window at a time */
14027 static WindoW discrepancyReportWindow = NULL;
14028 static WindoW oncallerReportWindow = NULL;
14029 static WindoW megaReportWindow = NULL;
14030 
GetWindowForReportType(EDiscrepancyReportType report_type)14031 static WindoW GetWindowForReportType (EDiscrepancyReportType report_type)
14032 {
14033   WindoW w = NULL;
14034 
14035   switch (report_type) {
14036     case eReportTypeDiscrepancy:
14037       w = discrepancyReportWindow;
14038       break;
14039     case eReportTypeOnCaller:
14040       w = oncallerReportWindow;
14041       break;
14042     case eReportTypeMegaReport:
14043       w = megaReportWindow;
14044       break;
14045     default:
14046       break;
14047   }
14048   return w;
14049 }
14050 
14051 
ClearWindowForReportType(WindoW w)14052 static void ClearWindowForReportType (WindoW w)
14053 {
14054   if (discrepancyReportWindow == w) {
14055     discrepancyReportWindow = NULL;
14056   }
14057   if (oncallerReportWindow == w) {
14058     oncallerReportWindow = NULL;
14059   }
14060   if (megaReportWindow == w) {
14061     megaReportWindow = NULL;
14062   }
14063 }
14064 
14065 
SetWindowForReportType(WindoW w,EDiscrepancyReportType report_type)14066 static void SetWindowForReportType (WindoW w, EDiscrepancyReportType report_type)
14067 {
14068   switch (report_type) {
14069     case eReportTypeDiscrepancy:
14070       discrepancyReportWindow = w;
14071       break;
14072     case eReportTypeOnCaller:
14073       oncallerReportWindow = w;
14074       break;
14075     case eReportTypeMegaReport:
14076       megaReportWindow = w;
14077       break;
14078     default:
14079       break;
14080   }
14081 }
14082 
14083 
GetReportConfigName(EDiscrepancyReportType report_type)14084 static CharPtr GetReportConfigName (EDiscrepancyReportType report_type)
14085 {
14086   CharPtr report_name = "";
14087 
14088   switch (report_type) {
14089     case eReportTypeDiscrepancy:
14090       report_name = "DISCREPANCY_REPORT";
14091       break;
14092     case eReportTypeOnCaller:
14093       report_name = "ON_CALLER_TOOL";
14094       break;
14095     case eReportTypeMegaReport:
14096       report_name = "MEGA_REPORT";
14097       break;
14098     default:
14099       break;
14100   }
14101   return report_name;
14102 }
14103 
14104 
14105 typedef void (*DiscrepancyCallback) (ValNodePtr item_list, Pointer userdata);
14106 typedef void (*DiscrepancyCallbackDataFree) (Pointer userdata);
14107 
14108 
14109 
14110 
14111 typedef struct discrepancyreportform
14112 {
14113   CLICKABLE_LIST_FORM_BLOCK
14114 
14115   DiscrepancyConfigPtr dcp;
14116   Int4 report_type;
14117   ButtoN show_names;
14118 } DiscrepancyReportFormData, PNTR DiscrepancyReportFormPtr;
14119 
CleanupDiscrepancyReportForm(GraphiC g,VoidPtr data)14120 static void CleanupDiscrepancyReportForm (GraphiC g, VoidPtr data)
14121 
14122 {
14123   DiscrepancyReportFormPtr drfp;
14124   ValNodePtr               vnp;
14125   ClickableItemPtr         cip;
14126 
14127   drfp = (DiscrepancyReportFormPtr) data;
14128   if (drfp != NULL) {
14129     /* find whether source qual report is open or closed */
14130     for (vnp = drfp->clickable_list_data; vnp != NULL; vnp = vnp->next) {
14131       cip = vnp->data.ptrvalue;
14132       if (cip != NULL) {
14133         if (cip->clickable_item_type == DISC_SRC_QUAL_PROBLEM) {
14134           if (cip->expanded) {
14135             SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_SRCQUAL_REPORT", "TRUE");
14136           } else {
14137             SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_SRCQUAL_REPORT", "FALSE");
14138           }
14139         } else if (cip->clickable_item_type == ONCALLER_DEFLINE_ON_SET) {
14140           if (cip->expanded) {
14141             SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_DEFLINE_ON_SET", "TRUE");
14142           } else {
14143             SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_DEFLINE_ON_SET", "FALSE");
14144           }
14145         }
14146       }
14147     }
14148     drfp->clickable_list_data = FreeClickableList (drfp->clickable_list_data);
14149     drfp->dcp = DiscrepancyConfigFree (drfp->dcp);
14150     ObjMgrFreeUserData (drfp->input_entityID, drfp->procid, drfp->proctype, drfp->userkey);
14151     ClearWindowForReportType ((WindoW) drfp->form);
14152     drfp->log_name = MemFree (drfp->log_name);
14153   }
14154   StdCleanupFormProc (g, data);
14155 }
14156 
14157 
UnselectDiscrepancyList(ButtoN b)14158 static void UnselectDiscrepancyList(ButtoN b)
14159 {
14160   ButtoN *test_options;
14161   Int4    i;
14162 
14163   test_options = (ButtoN *) GetObjectExtra (b);
14164   if (test_options != NULL)
14165   {
14166     for (i = 0; i < MAX_DISC_TYPE; i++)
14167     {
14168       SetStatus (test_options[i], FALSE);
14169     }
14170   }
14171 }
14172 
SelectDiscrepancyList(ButtoN b)14173 static void SelectDiscrepancyList(ButtoN b)
14174 {
14175   ButtoN *test_options;
14176   Int4    i;
14177 
14178   test_options = (ButtoN *) GetObjectExtra (b);
14179   if (test_options != NULL)
14180   {
14181     for (i = 0; i < MAX_DISC_TYPE; i++)
14182     {
14183       SetStatus (test_options[i], TRUE);
14184     }
14185   }
14186 }
14187 
14188 
14189 typedef struct discrepancyconfigpage {
14190   GrouP PNTR            grp_list;
14191   Int4                  num_pages;
14192 } DiscrepancyConfigPageData, PNTR DiscrepancyConfigPagePtr;
14193 
ChangeDiscrepancyConfigPage(VoidPtr data,Int2 newval,Int2 oldval)14194 static void ChangeDiscrepancyConfigPage (VoidPtr data, Int2 newval, Int2 oldval)
14195 
14196 {
14197   DiscrepancyConfigPagePtr cfg_page;
14198 
14199   cfg_page = (DiscrepancyConfigPagePtr) data;
14200   if (cfg_page == NULL || cfg_page->grp_list == NULL) {
14201     return;
14202   }
14203 
14204   if (oldval > -1 && oldval < cfg_page->num_pages) {
14205     Hide (cfg_page->grp_list[oldval]);
14206   }
14207   if (newval > -1 && newval < cfg_page->num_pages) {
14208     Show (cfg_page->grp_list[newval]);
14209   }
14210 
14211 }
14212 
14213 
14214 /* This function returns TRUE if there was a change to the discrepancy config,
14215  * FALSE otherwise.
14216  */
EditDiscrepancyConfig(DiscrepancyConfigPtr dcp,EDiscrepancyReportType report_type)14217 static Boolean EditDiscrepancyConfig (DiscrepancyConfigPtr dcp, EDiscrepancyReportType report_type)
14218 {
14219   WindoW                w;
14220   GrouP                 h, g, k, c;
14221   ButtoN                b, use_feature_table_format_btn;
14222   ModalAcceptCancelData acd;
14223   Int4                  i;
14224   ButtoN                test_options[MAX_DISC_TYPE];
14225   Boolean               rval = FALSE;
14226   DialoG                tbs = NULL;
14227   CharPtr PNTR          page_name_list = NULL;
14228   Char                  page_name[50];
14229   DiscrepancyConfigPageData cfg_page;
14230   Int4                  num_rows = 15;
14231   Int4                  num_columns = 2;
14232   Int4                  num_per_page = num_rows * num_columns;
14233   Int4                  num_appropriate = 0;
14234   Int4                  num_on_page = 0, page_num = 0;
14235   ValNodePtr            button_list = NULL, vnp;
14236   CharPtr conf_name, setting_name, full_name;
14237   CharPtr fmt = "%s (%s)";
14238 
14239   if (dcp == NULL)
14240   {
14241     return rval;
14242   }
14243 
14244   acd.accepted = FALSE;
14245   acd.cancelled = FALSE;
14246 
14247   w = ModalWindow(-20, -13, -10, -10, NULL);
14248   h = HiddenGroup (w, -1, 0, NULL);
14249   SetGroupSpacing (h, 10, 10);
14250 
14251   for (i = 0; i < MAX_DISC_TYPE; i++)
14252   {
14253     if (IsTestTypeAppropriateForReportType (i, report_type) && i != DISC_CATEGORY_HEADER) {
14254       num_appropriate ++;
14255       conf_name = GetDiscrepancyTestConfName((DiscrepancyType) i);
14256       setting_name = GetDiscrepancyTestSettingName((DiscrepancyType) i);
14257       full_name = (CharPtr) MemNew (sizeof (Char) *
14258                                     (StringLen (fmt)
14259                                      + StringLen (conf_name)
14260                                      + StringLen (setting_name)));
14261       sprintf (full_name, fmt, setting_name, conf_name);
14262       ValNodeAddPointer (&button_list, i, full_name);
14263     }
14264   }
14265 
14266   button_list = ValNodeSort (button_list, SortVnpByString);
14267   MemSet (test_options, 0, sizeof (test_options));
14268 
14269   if (num_appropriate > num_per_page) {
14270     /* set up page headers */
14271     cfg_page.num_pages = num_appropriate / num_per_page;
14272     if (num_appropriate % num_per_page > 0) {
14273       cfg_page.num_pages ++;
14274     }
14275     page_name_list = (CharPtr PNTR) MemNew (sizeof (CharPtr) * (cfg_page.num_pages + 1));
14276     for (i = 0; i < cfg_page.num_pages; i++) {
14277       sprintf (page_name, "Page %d", i + 1);
14278       page_name_list[i] = StringSave (page_name);
14279     }
14280     page_name_list[i] = NULL;
14281     tbs = CreateFolderTabs (h, page_name_list, 0,
14282                                     0, 0, SYSTEM_FOLDER_TAB,
14283                                     ChangeDiscrepancyConfigPage, &cfg_page);
14284 
14285     g = NormalGroup (h, 0, 0, "Discrepancy Tests to Run", programFont, NULL);
14286     cfg_page.grp_list = (GrouP PNTR) MemNew (sizeof (GrouP) * cfg_page.num_pages );
14287     cfg_page.grp_list[page_num] = HiddenGroup (g, 0, num_rows, NULL);
14288     SetGroupSpacing (cfg_page.grp_list[page_num], 10, 10);
14289     for (vnp = button_list; vnp != NULL; vnp = vnp->next) {
14290       if (num_on_page == num_per_page) {
14291         page_num++;
14292         cfg_page.grp_list[page_num] = HiddenGroup (g, 0, num_rows, NULL);
14293         SetGroupSpacing (cfg_page.grp_list[page_num], 10, 10);
14294         Hide (cfg_page.grp_list[page_num]);
14295         num_on_page = 0;
14296       }
14297       test_options[vnp->choice] = CheckBox (cfg_page.grp_list[page_num], vnp->data.ptrvalue, NULL);
14298       SetStatus (test_options[vnp->choice], dcp->conf_list[vnp->choice]);
14299       num_on_page++;
14300     }
14301   } else {
14302     g = NormalGroup (h, 0, num_rows, "Discrepancy Tests to Run", programFont, NULL);
14303     SetGroupSpacing (g, 10, 10);
14304     for (vnp = button_list; vnp != NULL; vnp = vnp->next) {
14305       test_options[vnp->choice] = CheckBox (g, vnp->data.ptrvalue, NULL);
14306       SetStatus (test_options[vnp->choice], dcp->conf_list[vnp->choice]);
14307     }
14308   }
14309 
14310   button_list = ValNodeFreeData (button_list);
14311 
14312   k = HiddenGroup (h, 3, 0, NULL);
14313   b = PushButton (k, "Select All", SelectDiscrepancyList);
14314   SetObjectExtra (b, test_options, NULL);
14315   b = PushButton (k, "Unselect All", UnselectDiscrepancyList);
14316   SetObjectExtra (b, test_options, NULL);
14317   use_feature_table_format_btn = CheckBox (k, "Use feature table format for features in report", NULL);
14318   SetStatus (use_feature_table_format_btn, dcp->use_feature_table_format);
14319 
14320 
14321   c = HiddenGroup (h, 3, 0, NULL);
14322   b = PushButton (c, "Accept", ModalAcceptButton);
14323   SetObjectExtra (b, &acd, NULL);
14324   b = PushButton (c, "Cancel", ModalCancelButton);
14325   SetObjectExtra (b, &acd, NULL);
14326   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) k, (HANDLE) c, (HANDLE) tbs, NULL);
14327 
14328   Show(w);
14329   Select (w);
14330   while (!acd.accepted && ! acd.cancelled)
14331   {
14332     ProcessExternalEvent ();
14333     Update ();
14334   }
14335   ProcessAnEvent ();
14336   if (acd.accepted)
14337   {
14338     for (i = 0; i < MAX_DISC_TYPE; i++)
14339     {
14340       dcp->conf_list [i] = GetStatus (test_options[i]);
14341     }
14342     dcp->use_feature_table_format = GetStatus (use_feature_table_format_btn);
14343     rval = TRUE;
14344     SaveDiscrepancyConfigEx (dcp, GetReportConfigName (report_type));
14345   }
14346 
14347   Remove (w);
14348   return rval;
14349 }
14350 
VisitFeaturesInViewedBioseqs(Pointer userdata,VisitFeaturesFunc callback)14351 static void VisitFeaturesInViewedBioseqs (Pointer userdata, VisitFeaturesFunc callback)
14352 {
14353   ValNodePtr  base_form_list, vnp;
14354   BaseFormPtr bfp;
14355   SeqEntryPtr sep;
14356   SeqEntryPtr orig_scope;
14357 
14358   orig_scope = SeqEntryGetScope ();
14359   base_form_list = GetBaseFormList();
14360   for (vnp = base_form_list; vnp != NULL; vnp = vnp->next) {
14361     bfp = (BaseFormPtr) vnp->data.ptrvalue;
14362     if (bfp != NULL && bfp->input_entityID != 0) {
14363       sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
14364       SeqEntrySetScope (sep);
14365       VisitFeaturesInSep (sep, userdata, callback);
14366     }
14367   }
14368   base_form_list = ValNodeFree (base_form_list);
14369   SeqEntrySetScope (orig_scope);
14370 }
14371 
14372 
CountChosenDiscrepancies(ValNodePtr discrepancy_list,Boolean count_all)14373 extern Int4 CountChosenDiscrepancies (ValNodePtr discrepancy_list, Boolean count_all)
14374 {
14375   Int4               num_chosen = 0;
14376   ClickableItemPtr dip;
14377 
14378   while (discrepancy_list != NULL)
14379   {
14380     dip = (ClickableItemPtr) discrepancy_list->data.ptrvalue;
14381     if (dip != NULL)
14382     {
14383       if (dip->chosen || count_all)
14384       {
14385         if (dip->expanded && dip->subcategories != NULL)
14386         {
14387           num_chosen += CountChosenDiscrepancies (dip->subcategories, TRUE);
14388         }
14389         else
14390         {
14391           num_chosen ++;
14392         }
14393       }
14394       else if (dip->expanded)
14395       {
14396         num_chosen += CountChosenDiscrepancies (dip->subcategories, FALSE);
14397       }
14398     }
14399     discrepancy_list = discrepancy_list->next;
14400   }
14401   return num_chosen;
14402 }
14403 
EditDiscrepancyItem(ValNodePtr vnp,Pointer userdata)14404 extern void EditDiscrepancyItem (ValNodePtr vnp, Pointer userdata)
14405 {
14406   SeqFeatPtr sfp, cds;
14407   BioseqPtr  bsp;
14408   SeqDescrPtr sdp;
14409   ObjValNodePtr ovp;
14410   OMUserDataPtr omudp;
14411   BaseFormPtr   bfp;
14412   SeqSubmitPtr  ssp;
14413   Uint2         procid;
14414   Boolean       special_flag = FALSE;
14415   Uint1         data_choice;
14416   WindoW        w;
14417 
14418   if (vnp == NULL)
14419   {
14420     return;
14421   }
14422 
14423   data_choice = vnp->choice;
14424   if (data_choice > OBJ_MAX) {
14425     special_flag = TRUE;
14426     data_choice -= OBJ_MAX;
14427   }
14428 
14429   if (data_choice == OBJ_SEQFEAT)
14430   {
14431     sfp = (SeqFeatPtr) vnp->data.ptrvalue;
14432     if (sfp != NULL)
14433     {
14434       if (sfp->idx.subtype == FEATDEF_PROT) {
14435         bsp = BioseqFindFromSeqLoc (sfp->location);
14436         if (bsp != NULL) {
14437           cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
14438           if (cds != NULL) {
14439             sfp = cds;
14440           }
14441         }
14442       }
14443       if (special_flag && sfp->data.choice == SEQFEAT_PUB) {
14444         w = EditCitFeatDirectly (sfp);
14445         Show (w);
14446       } else {
14447         GatherProcLaunch (OMPROC_EDIT, FALSE, sfp->idx.entityID, sfp->idx.itemID,
14448                           OBJ_SEQFEAT, 0, 0, OBJ_SEQFEAT, 0);
14449       }
14450     }
14451   }
14452   else if (data_choice == OBJ_BIOSEQ)
14453   {
14454     bsp = (BioseqPtr) vnp->data.ptrvalue;
14455     if (bsp != NULL)
14456     {
14457       GatherProcLaunch (OMPROC_EDIT, FALSE, bsp->idx.entityID, bsp->idx.itemID,
14458                          OBJ_BIOSEQ, 0, 0, OBJ_BIOSEQ, 0);
14459     }
14460   }
14461   else if (data_choice == OBJ_SEQDESC)
14462   {
14463     sdp = (SeqDescrPtr) (vnp->data.ptrvalue);
14464     if (sdp != NULL && sdp->extended != 0)
14465     {
14466       ovp = (ObjValNodePtr) sdp;
14467       if (special_flag && sdp->choice == Seq_descr_pub) {
14468         w = EditCitDescDirectly (sdp);
14469         Show (w);
14470       } else {
14471         GatherProcLaunch (OMPROC_EDIT, FALSE, ovp->idx.entityID, ovp->idx.itemID,
14472                           OBJ_SEQDESC, 0, 0, OBJ_SEQDESC, 0);
14473       }
14474     }
14475   }
14476   else if (data_choice == OBJ_SEQSUB)
14477   {
14478     ssp = (SeqSubmitPtr) (vnp->data.ptrvalue);
14479     procid = GetProcIdForItemEditor (ssp->idx.entityID, ssp->idx.itemID, OBJ_SEQSUB_CIT, 0);
14480     omudp = ItemAlreadyHasEditor (ssp->idx.entityID, ssp->idx.itemID,
14481                                     OBJ_SUBMIT_BLOCK, procid);
14482     if (omudp == NULL) {
14483       GatherProcLaunch (OMPROC_EDIT, FALSE, ssp->idx.entityID, ssp->idx.itemID,
14484                         OBJ_SEQSUB_CIT, 0, 0, OBJ_SEQSUB_CIT, 0);
14485       omudp = ItemAlreadyHasEditor (ssp->idx.entityID, ssp->idx.itemID,
14486                                       OBJ_SUBMIT_BLOCK, procid);
14487     }
14488     if (omudp != NULL) {
14489       bfp = (BaseFormPtr) omudp->userdata.ptrvalue;
14490       if (bfp != NULL) {
14491         Select (bfp->form);
14492         SendMessageToForm (bfp->form, NUM_VIB_MSG + 1);
14493       }
14494     }
14495   }
14496 
14497 }
14498 
14499 
BulkEditDiscrepancy(ValNodePtr vnp,Pointer userdata)14500 extern void BulkEditDiscrepancy (ValNodePtr vnp, Pointer userdata)
14501 {
14502   SeqFeatPtr       sfp;
14503   SeqDescrPtr      sdp;
14504   ValNodePtr       feat_list, desc_list;
14505   ValNodePtr       feat_list_list = NULL, desc_list_list = NULL, list_vnp;
14506   Uint2            entityID = 0;
14507 
14508   if (vnp == NULL)
14509   {
14510     return;
14511   }
14512   while (vnp != NULL)
14513   {
14514     if (vnp->choice == OBJ_SEQFEAT)
14515     {
14516       sfp = (SeqFeatPtr) vnp->data.ptrvalue;
14517       if (sfp != NULL)
14518       {
14519         for (list_vnp = feat_list_list;
14520              list_vnp != NULL && list_vnp->choice != sfp->idx.entityID;
14521              list_vnp = list_vnp->next)
14522         {
14523         }
14524 
14525         if (list_vnp == NULL) {
14526           list_vnp = ValNodeAddPointer (&feat_list_list, sfp->idx.entityID, NULL);
14527         }
14528         feat_list = (ValNodePtr) list_vnp->data.ptrvalue;
14529         ValNodeAddPointer (&feat_list, OBJ_SEQFEAT, sfp);
14530         list_vnp->data.ptrvalue = feat_list;
14531         entityID = sfp->idx.entityID;
14532       }
14533     }
14534     else if (vnp->choice == OBJ_SEQDESC)
14535     {
14536       sdp = (SeqDescrPtr) vnp->data.ptrvalue;
14537       if (sdp != NULL)
14538       {
14539         for (list_vnp = desc_list_list;
14540              list_vnp != NULL && list_vnp->choice != sdp->choice;
14541              list_vnp = list_vnp->next)
14542         {
14543         }
14544 
14545         if (list_vnp == NULL) {
14546           list_vnp = ValNodeAddPointer (&desc_list_list, sdp->choice, NULL);
14547         }
14548         desc_list = (ValNodePtr) list_vnp->data.ptrvalue;
14549         ValNodeAddPointer (&desc_list, OBJ_SEQDESC, sdp);
14550         list_vnp->data.ptrvalue = desc_list;
14551         if (sdp->extended > 0) {
14552           entityID = ((ObjValNodePtr)sdp)->idx.entityID;
14553         }
14554       }
14555     }
14556     vnp = vnp->next;
14557   }
14558 
14559   for (list_vnp = feat_list_list; list_vnp != NULL; list_vnp = list_vnp->next) {
14560     BulkEditorFeatList (entityID, list_vnp->data.ptrvalue);
14561   }
14562   feat_list_list = ValNodeFree (feat_list_list);
14563 
14564   for (list_vnp = desc_list_list; list_vnp != NULL; list_vnp = list_vnp->next) {
14565     BulkEditorDescrList (entityID, list_vnp->data.ptrvalue);
14566   }
14567   desc_list_list = ValNodeFree (desc_list_list);
14568 
14569 }
14570 
14571 
14572 static void EditCDStRNAOverlap (ValNodePtr item_list);
14573 
EditCDStRNAOverlapCallback(ValNodePtr vnp,Pointer userdata)14574 static void EditCDStRNAOverlapCallback (ValNodePtr vnp, Pointer userdata)
14575 {
14576   EditCDStRNAOverlap (vnp);
14577 }
14578 
14579 
ExtendPartialsToEndOrGapCallback(ValNodePtr list,Pointer userdata)14580 static void ExtendPartialsToEndOrGapCallback (ValNodePtr list, Pointer userdata)
14581 {
14582   ValNodePtr vnp, sep_list = NULL;
14583   LogInfoPtr lip;
14584   Uint2      entityID;
14585 
14586   if (Message (MSG_OKC, "Extend partial ends of features to gaps/end of sequence if within two nucleotides?") == ANS_CANCEL) {
14587     return;
14588   }
14589   WatchCursor();
14590   Update();
14591   lip = OpenLog ("Extended Features");
14592 
14593   FixExtendablePartials (list, userdata, lip);
14594 
14595   sep_list = GetViewedSeqEntryList ();
14596   for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
14597     entityID = ObjMgrGetEntityIDForChoice (vnp->data.ptrvalue);
14598     ObjMgrSetDirtyFlag (entityID, TRUE);
14599     ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
14600   }
14601   sep_list = ValNodeFree (sep_list);
14602 
14603   ArrowCursor();
14604   Update();
14605   CloseLog (lip);
14606   lip = FreeLog (lip);
14607 }
14608 
14609 
AddNonExtendableExceptionsCallback(ValNodePtr list,Pointer userdata)14610 static void AddNonExtendableExceptionsCallback (ValNodePtr list, Pointer userdata)
14611 {
14612   ValNodePtr vnp, sep_list = NULL;
14613   LogInfoPtr lip;
14614   Uint2      entityID;
14615 
14616   if (Message (MSG_OKC, "Add Non-extendable exception to non-extendable partial features?") == ANS_CANCEL) {
14617     return;
14618   }
14619   WatchCursor();
14620   Update();
14621   lip = OpenLog ("Added Exceptions to Features");
14622   FixBacterialNonExtendablePartials (list, userdata, lip);
14623 
14624   sep_list = GetViewedSeqEntryList ();
14625   for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
14626     entityID = ObjMgrGetEntityIDForChoice (vnp->data.ptrvalue);
14627     ObjMgrSetDirtyFlag (entityID, TRUE);
14628     ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
14629   }
14630   sep_list = ValNodeFree (sep_list);
14631 
14632   ArrowCursor();
14633   Update();
14634   CloseLog (lip);
14635   lip = FreeLog (lip);
14636 }
14637 
14638 
MarkOverlappingCDSCallback(ValNodePtr list,Pointer userdata)14639 static void MarkOverlappingCDSCallback (ValNodePtr list, Pointer userdata)
14640 {
14641   ValNodePtr vnp, sep_list = NULL;
14642   LogInfoPtr lip;
14643   Uint2      entityID;
14644 
14645   if (Message (MSG_OKC, "Add comment to overlapping coding regions?") == ANS_CANCEL) {
14646     return;
14647   }
14648   WatchCursor();
14649   Update();
14650   lip = OpenLog ("Added Comments to Overlapping Coding Regions");
14651   MarkOverlappingCDSs (list, userdata, lip);
14652 
14653   sep_list = GetViewedSeqEntryList ();
14654   for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
14655     entityID = ObjMgrGetEntityIDForChoice (vnp->data.ptrvalue);
14656     ObjMgrSetDirtyFlag (entityID, TRUE);
14657     ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
14658   }
14659   sep_list = ValNodeFree (sep_list);
14660 
14661   ArrowCursor();
14662   Update();
14663   CloseLog (lip);
14664   lip = FreeLog (lip);
14665 }
14666 
14667 
FixNonWGSSetsCallback(ValNodePtr list,Pointer userdata)14668 static void FixNonWGSSetsCallback (ValNodePtr list, Pointer userdata)
14669 {
14670   LogInfoPtr lip;
14671 
14672   if (Message (MSG_OKC, "Change non-WGS sets to GenBank?") == ANS_CANCEL) {
14673     return;
14674   }
14675   WatchCursor();
14676   Update();
14677   lip = OpenLog ("Changed Sets");
14678   FixNonWGSSets (list, userdata, lip);
14679 
14680   ArrowCursor();
14681   Update();
14682   CloseLog (lip);
14683   lip = FreeLog (lip);
14684 }
14685 
14686 
FixMismatchedCommentsCallback(ValNodePtr list,Pointer userdata)14687 static void FixMismatchedCommentsCallback (ValNodePtr list, Pointer userdata)
14688 {
14689   LogInfoPtr lip;
14690   SeqDescrPtr sdp;
14691 
14692   if (list == NULL || (sdp = (list->data.ptrvalue)) == NULL) {
14693     return;
14694   }
14695   if (Message (MSG_OKC, "Make comments match %s?", sdp->data.ptrvalue) == ANS_CANCEL) {
14696     return;
14697   }
14698   WatchCursor();
14699   Update();
14700   lip = OpenLog ("Changed Comments");
14701   FixMismatchedComments (list, userdata, lip);
14702 
14703   ArrowCursor();
14704   Update();
14705   CloseLog (lip);
14706   lip = FreeLog (lip);
14707 }
14708 
14709 
FixHumanHostsCallback(ValNodePtr list,Pointer userdata)14710 static void FixHumanHostsCallback (ValNodePtr list, Pointer userdata)
14711 {
14712   LogInfoPtr lip;
14713 
14714   if (list == NULL) {
14715     return;
14716   }
14717   if (Message (MSG_OKC, "Change 'human' host to 'Homo sapiens'") == ANS_CANCEL) {
14718     return;
14719   }
14720   WatchCursor();
14721   Update();
14722   lip = OpenLog ("Changed Hosts");
14723   FixHumanHosts (list, userdata, lip);
14724 
14725   ArrowCursor();
14726   Update();
14727   CloseLog (lip);
14728   lip = FreeLog (lip);
14729 }
14730 
14731 
FixOrderedLocationsCallback(ValNodePtr list,Pointer userdata)14732 static void FixOrderedLocationsCallback (ValNodePtr list, Pointer userdata)
14733 {
14734   LogInfoPtr lip;
14735 
14736   if (list == NULL) {
14737     return;
14738   }
14739   if (Message (MSG_OKC, "Change ordered locations to join?") == ANS_CANCEL) {
14740     return;
14741   }
14742   WatchCursor();
14743   Update();
14744   lip = OpenLog ("Changed Locations");
14745   FixOrderedLocations (list, userdata, lip);
14746 
14747   ArrowCursor();
14748   Update();
14749   CloseLog (lip);
14750   lip = FreeLog (lip);
14751 }
14752 
14753 
FixPseudoDiscrepanciesCallback(ValNodePtr list,Pointer userdata)14754 static void FixPseudoDiscrepanciesCallback (ValNodePtr list, Pointer userdata)
14755 {
14756   LogInfoPtr lip;
14757 
14758   if (list == NULL) {
14759     return;
14760   }
14761   if (Message (MSG_OKC, "Make overlapping genes and mRNAs pseudo?") == ANS_CANCEL) {
14762     return;
14763   }
14764   WatchCursor();
14765   Update();
14766   lip = OpenLog ("Set Pseudo");
14767   OncallerToolPseudoDiscrepanciesFix (list, userdata, lip);
14768 
14769   ArrowCursor();
14770   Update();
14771   CloseLog (lip);
14772   lip = FreeLog (lip);
14773 }
14774 
14775 
SetBioseqViewTargetByBioseq(BaseFormPtr bfp,BioseqPtr bsp)14776 extern void SetBioseqViewTargetByBioseq (BaseFormPtr bfp, BioseqPtr bsp)
14777 {
14778   Char       id_text [41];
14779 
14780   if (bsp != NULL && bfp != NULL)
14781   {
14782     SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_text, PRINTID_REPORT, sizeof (id_text));
14783     SetBioseqViewTarget (bfp, id_text);
14784   }
14785 }
14786 
14787 
GetFirstBioseqInSeqEntry(SeqEntryPtr sep)14788 NLM_EXTERN BioseqPtr GetFirstBioseqInSeqEntry (SeqEntryPtr sep)
14789 {
14790   BioseqPtr    bsp = NULL;
14791   BioseqSetPtr bssp;
14792 
14793   if (sep == NULL || sep->data.ptrvalue == NULL)
14794   {
14795     return NULL;
14796   }
14797   else if (IS_Bioseq (sep))
14798   {
14799     bsp = sep->data.ptrvalue;
14800   }
14801   else if (IS_Bioseq_set (sep))
14802   {
14803     bssp = (BioseqSetPtr) sep->data.ptrvalue;
14804     for (sep = bssp->seq_set; sep != NULL && bsp == NULL; sep = sep->next)
14805     {
14806       bsp = GetFirstBioseqInSeqEntry (sep);
14807     }
14808   }
14809   return bsp;
14810 }
14811 
14812 
GetBioseqForDescriptor(ObjValNodePtr ovp)14813 static BioseqPtr GetBioseqForDescriptor (ObjValNodePtr ovp)
14814 {
14815   BioseqPtr    bsp = NULL;
14816   BioseqSetPtr bssp;
14817   SeqEntryPtr  sep;
14818 
14819   if (ovp == NULL || ovp->idx.parentptr == NULL)
14820   {
14821     return NULL;
14822   }
14823   else if (ovp->idx.parenttype == OBJ_BIOSEQ) {
14824     bsp = (BioseqPtr) ovp->idx.parentptr;
14825   } else if (ovp->idx.parenttype == OBJ_BIOSEQSET) {
14826     bssp = (BioseqSetPtr) ovp->idx.parentptr;
14827     for (sep = bssp->seq_set; sep != NULL && bsp == NULL; sep = sep->next)
14828     {
14829       bsp = GetFirstBioseqInSeqEntry (sep);
14830     }
14831   }
14832   return bsp;
14833 }
14834 
14835 
GetBaseFormForEntityID(Uint2 entityID)14836 extern BaseFormPtr GetBaseFormForEntityID (Uint2 entityID)
14837 {
14838   ValNodePtr base_form_list, vnp;
14839   BaseFormPtr bfp = NULL;
14840 
14841   base_form_list = GetBaseFormList();
14842   vnp = base_form_list;
14843   while (vnp != NULL && bfp == NULL) {
14844     bfp = (BaseFormPtr) vnp->data.ptrvalue;
14845     if (bfp != NULL && bfp->input_entityID != entityID) {
14846       bfp = NULL;
14847     }
14848     vnp = vnp->next;
14849   }
14850   base_form_list = ValNodeFree (base_form_list);
14851   return bfp;
14852 }
14853 
ScrollToDiscrepancyItem(ValNodePtr vnp,Pointer userdata)14854 extern void ScrollToDiscrepancyItem (ValNodePtr vnp, Pointer userdata)
14855 {
14856   SeqFeatPtr    sfp, cds;
14857   BioseqPtr     bsp;
14858   SeqDescrPtr   sdp;
14859   ObjValNodePtr ovp;
14860   BaseFormPtr   bfp;
14861   Boolean       special_flag = FALSE;
14862   Uint1         data_choice;
14863 
14864   if (vnp == NULL)
14865   {
14866     return;
14867   }
14868 
14869   data_choice = vnp->choice;
14870   if (data_choice > OBJ_MAX) {
14871     special_flag = TRUE;
14872     data_choice -= OBJ_MAX;
14873   }
14874 
14875   if (data_choice == OBJ_SEQFEAT)
14876   {
14877     sfp = (SeqFeatPtr) vnp->data.ptrvalue;
14878     if (sfp != NULL)
14879     {
14880       if (sfp->idx.subtype == FEATDEF_PROT) {
14881         bsp = BioseqFindFromSeqLoc (sfp->location);
14882         if (bsp != NULL) {
14883           cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
14884           if (cds != NULL) {
14885             sfp = cds;
14886           }
14887         }
14888       }
14889 
14890       /* need to scroll to item */
14891       bsp = BioseqFindFromSeqLoc (sfp->location);
14892       bfp = GetBaseFormForEntityID (sfp->idx.entityID);
14893       if (bfp != NULL) {
14894         Select (bfp->form);
14895         SetBioseqViewTargetByBioseq (bfp, bsp);
14896         ObjMgrSelect (sfp->idx.entityID, sfp->idx.itemID, OBJ_SEQFEAT, 0, NULL);
14897       }
14898     }
14899   }
14900   else if (data_choice == OBJ_BIOSEQ)
14901   {
14902     bsp = (BioseqPtr) vnp->data.ptrvalue;
14903     bfp = GetBaseFormForEntityID (bsp->idx.entityID);
14904     if (bfp != NULL) {
14905       Select (bfp->form);
14906       SetBioseqViewTargetByBioseq (bfp, bsp);
14907     }
14908   }
14909   else if (data_choice == OBJ_SEQDESC)
14910   {
14911     sdp = (SeqDescrPtr) (vnp->data.ptrvalue);
14912     if (sdp != NULL && sdp->extended != 0)
14913     {
14914       ovp = (ObjValNodePtr) sdp;
14915       bsp = GetBioseqForDescriptor (ovp);
14916       bfp = GetBaseFormForEntityID (bsp->idx.entityID);
14917       if (bfp != NULL) {
14918         Select (bfp->form);
14919         SetBioseqViewTargetByBioseq (bfp, bsp);
14920         ObjMgrSelect (ovp->idx.entityID, ovp->idx.itemID, OBJ_SEQDESC, 0, NULL);
14921       }
14922     }
14923   }
14924 }
14925 
14926 static Uint2 GetEntityIDFromItem (ValNodePtr vnp);
14927 static void ApplyTagToCodingRegionsInEntityID (Uint2 entityID);
14928 
ApplyTagToCodingRegionsCallback(ValNodePtr item_list,Pointer userdata)14929 static void ApplyTagToCodingRegionsCallback (ValNodePtr item_list, Pointer userdata)
14930 {
14931   ValNodePtr vnp;
14932   ValNodePtr entityIDList = NULL;
14933   Uint2       entityID;
14934   SeqEntryPtr sep;
14935   ValNodePtr  cds_list;
14936   Boolean     found_any = FALSE;
14937 
14938   for (vnp = item_list; vnp != NULL; vnp = vnp->next)
14939   {
14940     entityID = GetEntityIDFromItem(vnp);
14941     if (!EntityIDAlreadyInList(entityID, entityIDList))
14942     {
14943       ValNodeAddInt (&entityIDList, 0, entityID);
14944     }
14945   }
14946   for (vnp = entityIDList; vnp != NULL; vnp = vnp->next)
14947   {
14948     sep = GetTopSeqEntryForEntityID (vnp->data.intvalue);
14949     cds_list = ListCodingRegionsContainedInSourceFeatures (sep);
14950     if (cds_list != NULL)
14951     {
14952       found_any = TRUE;
14953       cds_list = ValNodeFree (cds_list);
14954       ApplyTagToCodingRegionsInEntityID (vnp->data.intvalue);
14955     }
14956   }
14957   if (!found_any)
14958   {
14959     Message (MSG_ERROR, "No coding regions found in source features!  Try editing the definition lines.");
14960   }
14961   entityIDList = ValNodeFree (entityIDList);
14962 }
14963 
AddBulkEditing(ValNodePtr clickable_list)14964 static void AddBulkEditing (ValNodePtr clickable_list)
14965 {
14966   ClickableItemPtr cip;
14967   Uint1            subtype;
14968 
14969   while (clickable_list != NULL) {
14970     cip = (ClickableItemPtr) clickable_list->data.ptrvalue;
14971     if (cip->callback_func == NULL && cip->item_list != NULL) {
14972       if (cip->clickable_item_type == DISC_CDS_OVERLAP_TRNA) {
14973         cip->callback_func = EditCDStRNAOverlapCallback;
14974       } else if (cip->clickable_item_type == DISC_INCONSISTENT_BIOSRC_DEFLINE) {
14975         cip->callback_func = ApplyTagToCodingRegionsCallback;
14976       } else if (cip->clickable_item_type == DISC_PARTIAL_PROBLEMS) {
14977         cip->callback_func = ExtendPartialsToEndOrGapCallback;
14978       } else if (cip->clickable_item_type == DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_PROBLEMS) {
14979         cip->callback_func = AddNonExtendableExceptionsCallback;
14980       } else if (cip->clickable_item_type == DISC_OVERLAPPING_CDS) {
14981         cip->callback_func = MarkOverlappingCDSCallback;
14982       } else if (cip->clickable_item_type == DISC_NONWGS_SETS_PRESENT) {
14983         cip->callback_func = FixNonWGSSetsCallback;
14984       } else if (cip->clickable_item_type == DISC_MISMATCHED_COMMENTS) {
14985         cip->callback_func = FixMismatchedCommentsCallback;
14986       } else if (cip->clickable_item_type == DISC_HUMAN_HOST) {
14987         cip->callback_func = FixHumanHostsCallback;
14988       } else if (cip->clickable_item_type == ONCALLER_ORDERED_LOCATION) {
14989         cip->callback_func = FixOrderedLocationsCallback;
14990       } else if (cip->clickable_item_type == DISC_PSEUDO_MISMATCH) {
14991         cip->callback_func = FixPseudoDiscrepanciesCallback;
14992       } else {
14993         subtype = GetSubtypeForBulkEdit (cip->item_list);
14994         /* Note - using FEATDEF_rRNA to represent all editable RNA features */
14995         if (subtype == FEATDEF_CDS || subtype == FEATDEF_GENE || subtype == FEATDEF_rRNA) {
14996           cip->callback_func = BulkEditDiscrepancy;
14997         }
14998       }
14999     }
15000     AddBulkEditing (cip->subcategories);
15001     clickable_list = clickable_list->next;
15002   }
15003 }
15004 
15005 
15006 static Uint4 sOnCallerToolPriorities[] = {
15007 DISC_COUNT_NUCLEOTIDES,
15008 DISC_DUP_DEFLINE,
15009 DISC_MISSING_DEFLINES,
15010 TEST_TAXNAME_NOT_IN_DEFLINE,
15011 TEST_HAS_PROJECT_ID,
15012 ONCALLER_BIOPROJECT_ID,
15013 ONCALLER_DEFLINE_ON_SET,
15014 TEST_UNWANTED_SET_WRAPPER,
15015 TEST_COUNT_UNVERIFIED,
15016 DISC_SRC_QUAL_PROBLEM,
15017 DISC_FEATURE_COUNT,
15018 DISC_NO_ANNOTATION,
15019 DISC_FEATURE_MOLTYPE_MISMATCH,
15020 TEST_ORGANELLE_NOT_GENOMIC,
15021 DISC_INCONSISTENT_MOLTYPES,
15022 DISC_CHECK_AUTH_CAPS,
15023 ONCALLER_CONSORTIUM,
15024 DISC_UNPUB_PUB_WITHOUT_TITLE,
15025 DISC_TITLE_AUTHOR_CONFLICT,
15026 DISC_SUBMITBLOCK_CONFLICT,
15027 DISC_CITSUBAFFIL_CONFLICT,
15028 DISC_CHECK_AUTH_NAME,
15029 DISC_MISSING_AFFIL,
15030 DISC_USA_STATE,
15031 ONCALLER_CITSUB_AFFIL_DUP_TEXT,
15032 DISC_DUP_SRC_QUAL,
15033 DISC_MISSING_SRC_QUAL,
15034 DISC_DUP_SRC_QUAL_DATA,
15035 ONCALLER_DUPLICATE_PRIMER_SET,
15036 ONCALLER_MORE_NAMES_COLLECTED_BY,
15037 ONCALLER_MORE_OR_SPEC_NAMES_IDENTIFIED_BY,
15038 ONCALLER_SUSPECTED_ORG_IDENTIFIED,
15039 ONCALLER_SUSPECTED_ORG_COLLECTED,
15040 DISC_MISSING_VIRAL_QUALS,
15041 DISC_INFLUENZA_DATE_MISMATCH,
15042 DISC_HUMAN_HOST,
15043 DISC_SPECVOUCHER_TAXNAME_MISMATCH,
15044 DISC_BIOMATERIAL_TAXNAME_MISMATCH,
15045 DISC_CULTURE_TAXNAME_MISMATCH,
15046 DISC_STRAIN_TAXNAME_MISMATCH,
15047 DISC_BACTERIA_SHOULD_NOT_HAVE_ISOLATE,
15048 DISC_BACTERIA_MISSING_STRAIN,
15049 ONCALLER_STRAIN_TAXNAME_CONFLICT,
15050 TEST_SP_NOT_UNCULTURED,
15051 DISC_REQUIRED_CLONE,
15052 TEST_UNNECESSARY_ENVIRONMENTAL,
15053 TEST_AMPLIFIED_PRIMERS_NO_ENVIRONMENTAL_SAMPLE,
15054 ONCALLER_MULTISRC,
15055 ONCALLER_COUNTRY_COLON,
15056 END_COLON_IN_COUNTRY,
15057 DUP_DISC_ATCC_CULTURE_CONFLICT,
15058 DUP_DISC_CBS_CULTURE_CONFLICT,
15059 ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH,
15060 ONCALLER_MULTIPLE_CULTURE_COLLECTION,
15061 DISC_TRINOMIAL_SHOULD_HAVE_QUALIFIER,
15062 ONCALLER_CHECK_AUTHORITY,
15063 DISC_MAP_CHROMOSOME_CONFLICT,
15064 DISC_METAGENOMIC,
15065 DISC_METAGENOME_SOURCE,
15066 DISC_RETROVIRIDAE_DNA,
15067 NON_RETROVIRIDAE_PROVIRAL,
15068 ONCALLER_HIV_RNA_INCONSISTENT,
15069 RNA_PROVIRAL,
15070 TEST_BAD_MRNA_QUAL,
15071 DISC_MITOCHONDRION_REQUIRED,
15072 TEST_UNWANTED_SPACER,
15073 TEST_SMALL_GENOME_SET_PROBLEM,
15074 ONCALLER_SUPERFLUOUS_GENE,
15075 ONCALLER_GENE_MISSING,
15076 DISC_GENE_PARTIAL_CONFLICT,
15077 DISC_BAD_GENE_STRAND,
15078 TEST_UNNECESSARY_VIRUS_GENE,
15079 DISC_NON_GENE_LOCUS_TAG,
15080 DISC_RBS_WITHOUT_GENE,
15081 ONCALLER_ORDERED_LOCATION,
15082 MULTIPLE_CDS_ON_MRNA,
15083 DISC_CDS_WITHOUT_MRNA,
15084 DISC_mRNA_ON_WRONG_SEQUENCE_TYPE,
15085 DISC_BACTERIA_SHOULD_NOT_HAVE_MRNA,
15086 TEST_MRNA_OVERLAPPING_PSEUDO_GENE,
15087 TEST_EXON_ON_MRNA,
15088 DISC_CDS_HAS_NEW_EXCEPTION,
15089 DISC_SHORT_INTRON,
15090 DISC_EXON_INTRON_CONFLICT,
15091 DISC_PSEUDO_MISMATCH,
15092 DISC_RNA_NO_PRODUCT,
15093 DISC_BADLEN_TRNA,
15094 DISC_MICROSATELLITE_REPEAT_TYPE,
15095 DISC_SHORT_RRNA,
15096 DISC_POSSIBLE_LINKER,
15097 DISC_HAPLOTYPE_MISMATCH,
15098 DISC_FLATFILE_FIND_ONCALLER,
15099 DISC_CDS_PRODUCT_FIND,
15100 DISC_SUSPICIOUS_NOTE_TEXT,
15101 DISC_CHECK_RNA_PRODUCTS_AND_COMMENTS,
15102 DISC_INTERNAL_TRANSCRIBED_SPACER_RRNA,
15103 ONCALLER_COMMENT_PRESENT,
15104 DISC_SUSPECT_PRODUCT_NAME,
15105 UNCULTURED_NOTES_ONCALLER
15106 };
15107 
15108 static const Uint4 kNumOnCallerToolPriority = sizeof (sOnCallerToolPriorities) / sizeof (Uint4);
15109 
GetOnCallerToolPriority(Uint4 clickable_item_type)15110 static Uint4 GetOnCallerToolPriority (Uint4 clickable_item_type)
15111 {
15112   Uint4 priority = kNumOnCallerToolPriority + clickable_item_type;
15113   Uint4 i;
15114 
15115   for (i = 0; i < kNumOnCallerToolPriority; i++) {
15116     if (sOnCallerToolPriorities[i] == clickable_item_type) {
15117       priority = i;
15118       break;
15119     }
15120   }
15121   return priority;
15122 }
15123 
15124 
SortVnpByOnCallerToolPriority(VoidPtr ptr1,VoidPtr ptr2)15125 static int LIBCALLBACK SortVnpByOnCallerToolPriority (VoidPtr ptr1, VoidPtr ptr2)
15126 
15127 {
15128   ValNodePtr  vnp1;
15129   ValNodePtr  vnp2;
15130   ClickableItemPtr cip1, cip2;
15131   Uint4            priority1, priority2;
15132   int rval = 0;
15133 
15134   if (ptr1 == NULL || ptr2 == NULL) return 0;
15135   vnp1 = *((ValNodePtr PNTR) ptr1);
15136   vnp2 = *((ValNodePtr PNTR) ptr2);
15137   if (vnp1 == NULL || vnp2 == NULL) return 0;
15138   if (vnp1->data.ptrvalue == NULL || vnp2->data.ptrvalue == NULL) return 0;
15139 
15140   cip1 = vnp1->data.ptrvalue;
15141   cip2 = vnp2->data.ptrvalue;
15142 
15143   priority1 = GetOnCallerToolPriority (cip1->clickable_item_type);
15144   priority2 = GetOnCallerToolPriority (cip2->clickable_item_type);
15145 
15146   if (priority1 < priority2) {
15147     rval = -1;
15148   } else if (priority1 == priority2) {
15149     rval = 0;
15150   } else {
15151     rval = 1;
15152   }
15153 
15154   return rval;
15155 }
15156 
15157 
CreateTopLevelCategory(ValNodePtr orig,CharPtr cat_name)15158 static ClickableItemPtr CreateTopLevelCategory (ValNodePtr orig, CharPtr cat_name)
15159 {
15160   ClickableItemPtr cip, cat_cip = NULL;
15161 
15162   if (orig == NULL || (cip = (ClickableItemPtr)orig->data.ptrvalue) == NULL) {
15163     return NULL;
15164   }
15165 
15166   cat_cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
15167   MemSet (cat_cip, 0, sizeof (ClickableItemData));
15168   cat_cip->clickable_item_type = DISC_CATEGORY_HEADER;
15169   cat_cip->description = StringSave (cat_name);
15170   cat_cip->expanded = TRUE;
15171   ValNodeAddPointer (&(cat_cip->subcategories), 0, cip);
15172   orig->data.ptrvalue = cat_cip;
15173 
15174   return cat_cip;
15175 }
15176 
15177 
ReorderOnCallerResults(ValNodePtr PNTR p_clickable_list)15178 static void ReorderOnCallerResults (ValNodePtr PNTR p_clickable_list)
15179 {
15180   ClickableItemPtr cip_mol_type = NULL, cip_cit_sub = NULL, cip_src = NULL, sub_typo;
15181   ClickableItemPtr cip_feat = NULL, cip_suspect_text = NULL;
15182   ValNodePtr vnp, v_prev = NULL, v_next, subcate;
15183   ClickableItemPtr cip;
15184   Int4 typo_item_cnt;
15185   CharPtr typo_item_fmt = "%d product names contain typos";
15186 
15187   if (p_clickable_list == NULL || *p_clickable_list == NULL) {
15188     return;
15189   }
15190 
15191   /* first, sort */
15192   *p_clickable_list = ValNodeSort (*p_clickable_list, SortVnpByOnCallerToolPriority);
15193 
15194   /* now accumulate results into groups */
15195   for (vnp = *p_clickable_list; vnp != NULL; vnp = v_next) {
15196     v_next = vnp->next;
15197     cip = (vnp->data.ptrvalue);
15198     switch (cip->clickable_item_type) {
15199       case DISC_FEATURE_MOLTYPE_MISMATCH:
15200       case TEST_ORGANELLE_NOT_GENOMIC:
15201       case DISC_INCONSISTENT_MOLTYPES:
15202         if (cip_mol_type == NULL) {
15203           cip_mol_type = CreateTopLevelCategory (vnp, "Molecule type tests");
15204           v_prev = vnp;
15205         } else {
15206           ValNodeAddPointer (&(cip_mol_type->subcategories), 0, cip);
15207           v_prev->next = vnp->next;
15208           vnp->next = NULL;
15209           vnp = ValNodeFree (vnp);
15210         }
15211         break;
15212       case DISC_CHECK_AUTH_CAPS:
15213       case ONCALLER_CONSORTIUM:
15214       case DISC_UNPUB_PUB_WITHOUT_TITLE:
15215       case DISC_TITLE_AUTHOR_CONFLICT:
15216       case DISC_SUBMITBLOCK_CONFLICT:
15217       case DISC_CITSUBAFFIL_CONFLICT:
15218       case DISC_CHECK_AUTH_NAME:
15219       case DISC_MISSING_AFFIL:
15220       case DISC_USA_STATE:
15221       case ONCALLER_CITSUB_AFFIL_DUP_TEXT:
15222         if (cip_cit_sub == NULL) {
15223           cip_cit_sub = CreateTopLevelCategory (vnp, "Cit-sub type tests");
15224           v_prev = vnp;
15225         } else {
15226           ValNodeAddPointer (&(cip_cit_sub->subcategories), 0, cip);
15227           v_prev->next = vnp->next;
15228           vnp->next = NULL;
15229           vnp = ValNodeFree (vnp);
15230         }
15231         break;
15232       case DISC_DUP_SRC_QUAL:
15233       case DISC_MISSING_SRC_QUAL:
15234       case DISC_DUP_SRC_QUAL_DATA:
15235       case DISC_MISSING_VIRAL_QUALS:
15236       case DISC_INFLUENZA_DATE_MISMATCH:
15237       case DISC_HUMAN_HOST:
15238       case DISC_SPECVOUCHER_TAXNAME_MISMATCH:
15239       case DISC_BIOMATERIAL_TAXNAME_MISMATCH:
15240       case DISC_CULTURE_TAXNAME_MISMATCH:
15241       case DISC_STRAIN_TAXNAME_MISMATCH:
15242       case DISC_BACTERIA_SHOULD_NOT_HAVE_ISOLATE:
15243       case DISC_BACTERIA_MISSING_STRAIN:
15244       case ONCALLER_STRAIN_TAXNAME_CONFLICT:
15245       case TEST_SP_NOT_UNCULTURED:
15246       case DISC_REQUIRED_CLONE:
15247       case TEST_UNNECESSARY_ENVIRONMENTAL:
15248       case TEST_AMPLIFIED_PRIMERS_NO_ENVIRONMENTAL_SAMPLE:
15249       case ONCALLER_MULTISRC:
15250       case ONCALLER_COUNTRY_COLON:
15251       case END_COLON_IN_COUNTRY:
15252       case DUP_DISC_ATCC_CULTURE_CONFLICT:
15253       case DUP_DISC_CBS_CULTURE_CONFLICT:
15254       case ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH:
15255       case ONCALLER_MULTIPLE_CULTURE_COLLECTION:
15256       case DISC_TRINOMIAL_SHOULD_HAVE_QUALIFIER:
15257       case ONCALLER_CHECK_AUTHORITY:
15258       case DISC_MAP_CHROMOSOME_CONFLICT:
15259       case DISC_METAGENOMIC:
15260       case DISC_METAGENOME_SOURCE:
15261       case DISC_RETROVIRIDAE_DNA:
15262       case NON_RETROVIRIDAE_PROVIRAL:
15263       case ONCALLER_HIV_RNA_INCONSISTENT:
15264       case RNA_PROVIRAL:
15265       case TEST_BAD_MRNA_QUAL:
15266       case DISC_MITOCHONDRION_REQUIRED:
15267       case TEST_UNWANTED_SPACER:
15268       case TEST_SMALL_GENOME_SET_PROBLEM:
15269       case ONCALLER_DUPLICATE_PRIMER_SET:
15270       case ONCALLER_MORE_NAMES_COLLECTED_BY:
15271       case ONCALLER_MORE_OR_SPEC_NAMES_IDENTIFIED_BY:
15272       case ONCALLER_SUSPECTED_ORG_IDENTIFIED:
15273       case ONCALLER_SUSPECTED_ORG_COLLECTED:
15274         if (cip_src == NULL) {
15275           cip_src = CreateTopLevelCategory (vnp, "Source tests");
15276           v_prev = vnp;
15277         } else {
15278           ValNodeAddPointer (&(cip_src->subcategories), 0, cip);
15279           v_prev->next = vnp->next;
15280           vnp->next = NULL;
15281           vnp = ValNodeFree (vnp);
15282         }
15283         break;
15284       case ONCALLER_SUPERFLUOUS_GENE:
15285       case ONCALLER_GENE_MISSING:
15286       case DISC_GENE_PARTIAL_CONFLICT:
15287       case DISC_BAD_GENE_STRAND:
15288       case TEST_UNNECESSARY_VIRUS_GENE:
15289       case DISC_NON_GENE_LOCUS_TAG:
15290       case DISC_RBS_WITHOUT_GENE:
15291       case ONCALLER_ORDERED_LOCATION:
15292       case MULTIPLE_CDS_ON_MRNA:
15293       case DISC_CDS_WITHOUT_MRNA:
15294       case DISC_mRNA_ON_WRONG_SEQUENCE_TYPE:
15295       case DISC_BACTERIA_SHOULD_NOT_HAVE_MRNA:
15296       case TEST_MRNA_OVERLAPPING_PSEUDO_GENE:
15297       case TEST_EXON_ON_MRNA:
15298       case DISC_CDS_HAS_NEW_EXCEPTION:
15299       case DISC_SHORT_INTRON:
15300       case DISC_EXON_INTRON_CONFLICT:
15301       case DISC_PSEUDO_MISMATCH:
15302       case DISC_RNA_NO_PRODUCT:
15303       case DISC_BADLEN_TRNA:
15304       case DISC_MICROSATELLITE_REPEAT_TYPE:
15305       case DISC_SHORT_RRNA:
15306         if (cip_feat == NULL) {
15307           cip_feat = CreateTopLevelCategory (vnp, "Feature tests");
15308           v_prev = vnp;
15309         } else {
15310           ValNodeAddPointer (&(cip_feat->subcategories), 0, cip);
15311           v_prev->next = vnp->next;
15312           vnp->next = NULL;
15313           vnp = ValNodeFree (vnp);
15314         }
15315         break;
15316       case DISC_FLATFILE_FIND_ONCALLER:
15317       case DISC_FLATFILE_FIND_ONCALLER_FIXABLE:
15318       case DISC_FLATFILE_FIND_ONCALLER_UNFIXABLE:
15319       case DISC_CDS_PRODUCT_FIND:
15320       case DISC_SUSPICIOUS_NOTE_TEXT:
15321       case DISC_CHECK_RNA_PRODUCTS_AND_COMMENTS:
15322       case DISC_INTERNAL_TRANSCRIBED_SPACER_RRNA:
15323       case ONCALLER_COMMENT_PRESENT:
15324       case DISC_SUSPECT_PRODUCT_NAME:
15325       case UNCULTURED_NOTES_ONCALLER:
15326         if (DISC_SUSPECT_PRODUCT_NAME == cip->clickable_item_type) {
15327            sub_typo = NULL;
15328            for (subcate = cip->subcategories; subcate != NULL; subcate = subcate->next) {
15329               if ( !StringCmp(((ClickableItemPtr)(subcate->data.ptrvalue))->description, "Typo") ) {
15330                   sub_typo = subcate->data.ptrvalue;
15331                   subcate->next = NULL;
15332                    break;
15333               }
15334            }
15335            if (sub_typo != NULL) {
15336               vnp->data.ptrvalue = cip = sub_typo;
15337               typo_item_cnt = 0;
15338               for (subcate = cip->subcategories; subcate != NULL; subcate = subcate->next) {
15339                    typo_item_cnt +=
15340                           ValNodeLen(((ClickableItemPtr)(subcate->data.ptrvalue))->item_list);
15341               }
15342               cip->description = NULL;
15343               cip->description = (CharPtr) MemNew (StringLen(typo_item_fmt) + 5);
15344               sprintf(cip->description, typo_item_fmt, typo_item_cnt);
15345            }
15346            else  {
15347               if (v_prev != NULL) {
15348                 v_prev->next = vnp->next;
15349               }
15350               vnp->next = NULL;
15351               vnp = ValNodeFree (vnp);
15352               break;
15353            }
15354         }
15355         if (cip_suspect_text == NULL) {
15356           cip_suspect_text = CreateTopLevelCategory (vnp, "Suspect text tests");
15357           v_prev = vnp;
15358         } else {
15359           ValNodeAddPointer (&(cip_suspect_text->subcategories), 0, cip);
15360           v_prev->next = vnp->next;
15361           vnp->next = NULL;
15362           vnp = ValNodeFree (vnp);
15363         }
15364         break;
15365       default:
15366         v_prev = vnp;
15367         break;
15368     }
15369   }
15370   SetDiscrepancyLevels (*p_clickable_list, 0);
15371 }
15372 
15373 
RelabelDiscrepancyItems(ValNodePtr list)15374 static void RelabelDiscrepancyItems (ValNodePtr list)
15375 {
15376   ValNodePtr vnp;
15377   ClickableItemPtr cip;
15378   CharPtr new_desc, test_name, fmt = "%s (%s)";
15379 
15380   for (vnp = list; vnp != NULL; vnp = vnp->next) {
15381     cip = (ClickableItemPtr) vnp->data.ptrvalue;
15382     if (cip != NULL) {
15383       test_name = GetDiscrepancyTestSettingName ((DiscrepancyType) cip->clickable_item_type);
15384       if (test_name != NULL) {
15385         new_desc = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (cip->description) + StringLen (test_name)));
15386         sprintf (new_desc, fmt, cip->description, test_name);
15387         cip->description = MemFree (cip->description);
15388         cip->description = new_desc;
15389       }
15390       RelabelDiscrepancyItems (cip->subcategories);
15391     }
15392   }
15393 }
15394 
15395 
RecheckDiscrepancy(DiscrepancyReportFormPtr drfp)15396 static void RecheckDiscrepancy (DiscrepancyReportFormPtr drfp)
15397 {
15398   ValNodePtr               sep_list, vnp;
15399   Uint2                    entityID;
15400   DiscReportOutputConfigData   oc;
15401 
15402   // dummy DiscReportOutputConfigPtr
15403   MemSet (&oc, 0, sizeof (DiscReportOutputConfigData));
15404   oc.add_output_tag = TRUE;
15405   oc.add_extra_output_tag = TRUE;
15406 
15407   if (drfp != NULL)
15408   {
15409     WatchCursor();
15410     Update();
15411     drfp->clickable_list_data = FreeClickableList (drfp->clickable_list_data);
15412 
15413     sep_list = GetViewedSeqEntryList ();
15414     for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
15415       entityID = ObjMgrGetEntityIDForChoice ((SeqEntryPtr)(vnp->data.ptrvalue));
15416       SeqMgrClearFeatureIndexes (entityID, NULL);
15417       SeqMgrIndexFeatures (entityID, NULL);
15418     }
15419     AddListToOutputConfig(sep_list, &oc);
15420 
15421     drfp->clickable_list_data = CollectDiscrepancies (drfp->dcp, sep_list, CheckTaxNamesAgainstTaxDatabase);
15422 
15423     /* reorder as necessary */
15424     if (drfp->reorder_results_proc != NULL) {
15425       (drfp->reorder_results_proc) (&(drfp->clickable_list_data));
15426     }
15427     if (drfp->relabel_results_proc != NULL) {
15428       (drfp->relabel_results_proc) (drfp->clickable_list_data);
15429     }
15430 
15431     /* add bulk editing where appropriate */
15432     AddBulkEditing (drfp->clickable_list_data);
15433 
15434     if (drfp->report_type == eReportTypeMegaReport) {
15435       // add FATAL tag;
15436       AddListOutputTags(drfp->clickable_list_data, &oc);
15437     }
15438 
15439     PointerToDialog (drfp->clickable_list_dlg, drfp->clickable_list_data);
15440     ArrowCursor();
15441     Update();
15442   }
15443 }
15444 
RecheckDiscrepancyProc(ButtoN b)15445 static void RecheckDiscrepancyProc (ButtoN b)
15446 {
15447   DiscrepancyReportFormPtr drfp;
15448 
15449   drfp = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15450   RecheckDiscrepancy (drfp);
15451 }
15452 
15453 
RecheckDiscrepancyWindow(WindoW w)15454 static void RecheckDiscrepancyWindow (WindoW w)
15455 {
15456   DiscrepancyReportFormPtr drfp;
15457 
15458   drfp = (DiscrepancyReportFormPtr) GetObjectExtra (w);
15459   RecheckDiscrepancy (drfp);
15460 }
15461 
15462 
AddNewEntityDiscrepancyProc(ButtoN b,Uint2 new_entityID)15463 static void AddNewEntityDiscrepancyProc (ButtoN b, Uint2 new_entityID )
15464 {
15465   DiscrepancyReportFormPtr drfp;
15466   ValNodePtr               sep_list, vnp;
15467   Uint2                    entityID;
15468   Boolean                  found = FALSE;
15469   SeqEntryPtr              sep;
15470 
15471   drfp = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15472   if (drfp != NULL)
15473   {
15474     WatchCursor();
15475     Update();
15476     drfp->clickable_list_data = FreeClickableList (drfp->clickable_list_data);
15477 
15478     sep_list = GetViewedSeqEntryList ();
15479     for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
15480       entityID = ObjMgrGetEntityIDForChoice (vnp->data.ptrvalue);
15481       SeqMgrClearFeatureIndexes (entityID, NULL);
15482       SeqMgrIndexFeatures (entityID, NULL);
15483       if (entityID == new_entityID) {
15484         found = TRUE;
15485       }
15486     }
15487     if (!found) {
15488       sep = GetTopSeqEntryForEntityID (new_entityID);
15489       if (sep != NULL) {
15490         ValNodeAddPointer (&sep_list, 0, GetTopSeqEntryForEntityID (new_entityID));
15491         SeqMgrClearFeatureIndexes (new_entityID, NULL);
15492         SeqMgrIndexFeatures (new_entityID, NULL);
15493       }
15494     }
15495 
15496     drfp->clickable_list_data = CollectDiscrepancies (drfp->dcp, sep_list, CheckTaxNamesAgainstTaxDatabase);
15497     sep_list = ValNodeFree (sep_list);
15498 
15499     /* reorder as necessary */
15500     if (drfp->reorder_results_proc != NULL) {
15501       (drfp->reorder_results_proc) (&(drfp->clickable_list_data));
15502     }
15503     if (drfp->relabel_results_proc != NULL) {
15504       (drfp->relabel_results_proc) (drfp->clickable_list_data);
15505     }
15506 
15507     /* add bulk editing where appropriate */
15508     AddBulkEditing (drfp->clickable_list_data);
15509 
15510     PointerToDialog (drfp->clickable_list_dlg, drfp->clickable_list_data);
15511     ArrowCursor();
15512     Update();
15513   }
15514 }
15515 
15516 
15517 extern void
WriteClickableListReport(FILE * fp,ValNodePtr discrepancy_list,Boolean show_all,Boolean use_feature_table_fmt)15518 WriteClickableListReport
15519 (FILE       *fp,
15520  ValNodePtr discrepancy_list,
15521  Boolean    show_all,
15522  Boolean    use_feature_table_fmt)
15523 {
15524   ClickableItemPtr       dip;
15525   ValNodePtr               vnp;
15526   Int4                     num_chosen;
15527 
15528   if (fp == NULL || discrepancy_list == NULL)
15529   {
15530     return;
15531   }
15532   for (vnp = discrepancy_list; vnp != NULL; vnp = vnp->next)
15533   {
15534     dip = (ClickableItemPtr) vnp->data.ptrvalue;
15535     if (dip != NULL)
15536     {
15537       if (dip->expanded && dip->subcategories != NULL)
15538       {
15539         num_chosen = CountChosenDiscrepancies (dip->subcategories, show_all | dip->chosen);
15540         if (num_chosen > 0)
15541         {
15542           if (dip->chosen || show_all)
15543           {
15544             fprintf (fp, "%s\n", dip->description);
15545           }
15546           WriteClickableListReport (fp, dip->subcategories, show_all | dip->chosen, use_feature_table_fmt);
15547         }
15548       }
15549       else if (dip->chosen || show_all)
15550       {
15551         WriteDiscrepancy (fp, dip, use_feature_table_fmt);
15552       }
15553     }
15554   }
15555 }
15556 
DiscrepancyReportExportProc(ForM f,CharPtr filename)15557 static Boolean DiscrepancyReportExportProc (ForM f, CharPtr filename)
15558 
15559 {
15560   FILE           *fp;
15561   Char           path [PATH_MAX];
15562   DiscrepancyReportFormPtr drfp;
15563   Int4                     num_disc = 0;
15564   Boolean                  show_all = FALSE;
15565 
15566   drfp = (DiscrepancyReportFormPtr) GetObjectExtra (f);
15567   if (drfp == NULL)
15568   {
15569     return FALSE;
15570   }
15571 
15572   num_disc = CountChosenDiscrepancies (drfp->clickable_list_data, FALSE);
15573 
15574   if (num_disc == 0)
15575   {
15576     if (ANS_CANCEL == Message (MSG_OKC, "No discrepancies selected!  Export all?"))
15577     {
15578       return FALSE;
15579     }
15580     else
15581     {
15582       show_all = TRUE;
15583     }
15584   }
15585 
15586   path [0] = '\0';
15587   StringNCpy_0 (path, filename, sizeof (path));
15588   if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
15589 #ifdef WIN_MAC
15590     fp = FileOpen (path, "r");
15591     if (fp != NULL) {
15592       FileClose (fp);
15593     } else {
15594       FileCreate (path, "TEXT", "ttxt");
15595     }
15596 #endif
15597     fp = FileOpen (path, "w");
15598     if (fp != NULL) {
15599       WriteClickableListReport (fp, drfp->clickable_list_data, show_all,
15600                               (Boolean)(drfp->dcp != NULL && drfp->dcp->use_feature_table_format));
15601       FileClose (fp);
15602       return TRUE;
15603     }
15604   }
15605   return FALSE;
15606 }
15607 
15608 
GenerateDiscrepancyReport(ButtoN b)15609 static void GenerateDiscrepancyReport (ButtoN b)
15610 {
15611   DiscrepancyReportFormPtr drfp;
15612   Char                     path [PATH_MAX];
15613 
15614   drfp = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15615   if (drfp == NULL)
15616   {
15617     return;
15618   }
15619 
15620   TmpNam (path);
15621   if (DiscrepancyReportExportProc (drfp->form, path))
15622   {
15623     LaunchGeneralTextViewer (path, "Discrepancy Report");
15624   }
15625   FileRemove (path);
15626 }
15627 
15628 
ReactivateDiscrepancyReport(EDiscrepancyReportType report_type)15629 static void ReactivateDiscrepancyReport (EDiscrepancyReportType report_type)
15630 {
15631   DiscrepancyReportFormPtr drfp;
15632   WindoW                   w;
15633 
15634   w = GetWindowForReportType (report_type);
15635   if (w == NULL)
15636   {
15637     CreateReportWindow (report_type);
15638   }
15639 
15640   drfp = (DiscrepancyReportFormPtr) GetObjectExtra (w);
15641   if (drfp == NULL)
15642   {
15643     Remove (w);
15644     ClearWindowForReportType (w);
15645     CreateReportWindow (report_type);
15646     w = GetWindowForReportType (report_type);
15647   }
15648 
15649   /* populate discrepancy lists */
15650   if (drfp != NULL) {
15651     RecheckDiscrepancyProc (drfp->recheck_btn);
15652   }
15653   Show (w);
15654   Select (w);
15655 }
15656 
15657 
15658 
EditReportConfigBtn(EDiscrepancyReportType report_type)15659 static void EditReportConfigBtn (EDiscrepancyReportType report_type)
15660 {
15661   DiscrepancyReportFormPtr drfp;
15662   WindoW                   w;
15663 
15664   w = GetWindowForReportType (report_type);
15665 
15666   drfp = (DiscrepancyReportFormPtr) GetObjectExtra (w);
15667   if (drfp == NULL) return;
15668 
15669   if (EditDiscrepancyConfig (drfp->dcp, report_type))
15670   {
15671     RecheckDiscrepancyProc (drfp->recheck_btn);
15672   }
15673 }
15674 
15675 
EditDiscrepancyConfigBtn(ButtoN b)15676 static void EditDiscrepancyConfigBtn (ButtoN b)
15677 {
15678   EditReportConfigBtn (eReportTypeDiscrepancy);
15679 }
15680 
15681 
EditOnCallerConfigBtn(ButtoN b)15682 static void EditOnCallerConfigBtn (ButtoN b)
15683 {
15684   EditReportConfigBtn (eReportTypeOnCaller);
15685 }
15686 
15687 
EditMegaReportConfigBtn(ButtoN b)15688 static void EditMegaReportConfigBtn (ButtoN b)
15689 {
15690   EditReportConfigBtn (eReportTypeMegaReport);
15691 }
15692 
15693 
GetReportEditButtonProc(EDiscrepancyReportType report_type)15694 static Nlm_BtnActnProc GetReportEditButtonProc (EDiscrepancyReportType report_type)
15695 {
15696   Nlm_BtnActnProc proc = NULL;
15697 
15698   switch (report_type) {
15699     case eReportTypeDiscrepancy:
15700       proc = EditDiscrepancyConfigBtn;
15701       break;
15702     case eReportTypeOnCaller:
15703       proc = EditOnCallerConfigBtn;
15704       break;
15705     case eReportTypeMegaReport:
15706       proc = EditMegaReportConfigBtn;
15707       break;
15708     default:
15709       break;
15710   }
15711   return proc;
15712 }
15713 
15714 
15715 #ifndef WIN_MAC
15716 extern void CreateStdValidatorFormMenus (WindoW w);
15717 #endif
15718 
15719 
GetReportName(EDiscrepancyReportType report_type)15720 static CharPtr GetReportName (EDiscrepancyReportType report_type)
15721 {
15722   CharPtr report_name = "";
15723 
15724   switch (report_type) {
15725     case eReportTypeDiscrepancy:
15726       report_name = "Discrepancy Report";
15727       break;
15728     case eReportTypeOnCaller:
15729       report_name = "On Caller Tool";
15730       break;
15731     case eReportTypeMegaReport:
15732       report_name = "Mega Report";
15733       break;
15734     default:
15735       break;
15736   }
15737   return report_name;
15738 }
15739 
15740 
AdjustConfigForReportType(EDiscrepancyReportType report_type,DiscrepancyConfigPtr dcp)15741 static void AdjustConfigForReportType (EDiscrepancyReportType report_type, DiscrepancyConfigPtr dcp)
15742 {
15743   Int4 i;
15744 
15745   if (dcp == NULL) {
15746     return;
15747   }
15748 
15749   for (i = 0; i < MAX_DISC_TYPE; i++) {
15750     if (!IsTestTypeAppropriateForReportType (i, report_type)) {
15751       dcp->conf_list[i] = FALSE;
15752     }
15753   }
15754 
15755 }
15756 
15757 
ExpandAllDiscReportItems(ButtoN b)15758 static void ExpandAllDiscReportItems (ButtoN b)
15759 {
15760   DiscrepancyReportFormPtr d;
15761 
15762   d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15763   if (d == NULL) {
15764     return;
15765   }
15766 
15767   ExpandClickableItemList (d->clickable_list_data);
15768 
15769   PointerToDialog (d->clickable_list_dlg, d->clickable_list_data);
15770 }
15771 
15772 
ContractAllDiscReportItems(ButtoN b)15773 static void ContractAllDiscReportItems (ButtoN b)
15774 {
15775   DiscrepancyReportFormPtr d;
15776 
15777   d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15778   if (d == NULL) {
15779     return;
15780   }
15781   ContractClickableItemList (d->clickable_list_data);
15782 
15783   PointerToDialog (d->clickable_list_dlg, d->clickable_list_data);
15784 }
15785 
15786 
ToggleDiscrepancyReportNames(ButtoN b)15787 static void ToggleDiscrepancyReportNames (ButtoN b)
15788 {
15789   DiscrepancyReportFormPtr d;
15790 
15791   d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15792   if (d == NULL) {
15793     return;
15794   }
15795 
15796   if (d->relabel_results_proc == NULL) {
15797     d->relabel_results_proc = RelabelDiscrepancyItems;
15798     SetTitle (d->show_names, "Hide Test Names");
15799   } else {
15800     d->relabel_results_proc = NULL;
15801      SetTitle (d->show_names, "Show Test Names");
15802   }
15803   RecheckDiscrepancyProc (b);
15804 }
15805 
15806 
UnmarkAllBtn(ButtoN b)15807 static void UnmarkAllBtn (ButtoN b)
15808 {
15809   DiscrepancyReportFormPtr d;
15810 
15811   d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15812   if (d == NULL) {
15813     return;
15814   }
15815   ChooseCategories (d->clickable_list_data, FALSE);
15816 
15817   PointerToDialog (d->clickable_list_dlg, d->clickable_list_data);
15818 }
15819 
15820 
FixMarkedDiscrepanciesBtn(ButtoN b)15821 static void FixMarkedDiscrepanciesBtn (ButtoN b)
15822 {
15823   DiscrepancyReportFormPtr d;
15824   ValNodePtr vnp, sep_list;
15825   Uint2      entityID;
15826   LogInfoPtr lip = NULL;
15827 
15828   d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15829   if (d == NULL) {
15830     return;
15831   }
15832   WatchCursor();
15833   Update();
15834   if (d->log_name != NULL) {
15835     lip = OpenLog (d->log_name);
15836   }
15837   AutofixDiscrepancies (d->clickable_list_data, FALSE, lip);
15838   CloseLog (lip);
15839   lip = FreeLog (lip);
15840 
15841   sep_list = GetViewedSeqEntryList ();
15842   for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
15843     entityID = ObjMgrGetEntityIDForChoice (vnp->data.ptrvalue);
15844     ObjMgrSetDirtyFlag (entityID, TRUE);
15845     ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
15846   }
15847   d->clickable_list_data = FreeClickableList (d->clickable_list_data);
15848   d->clickable_list_data = CollectDiscrepancies (d->dcp, sep_list, CheckTaxNamesAgainstTaxDatabase);
15849   sep_list = ValNodeFree (sep_list);
15850 
15851   /* reorder as necessary */
15852   if (d->reorder_results_proc != NULL) {
15853     (d->reorder_results_proc) (&(d->clickable_list_data));
15854   }
15855   if (d->relabel_results_proc != NULL) {
15856     (d->relabel_results_proc) (d->clickable_list_data);
15857   }
15858 
15859   /* add bulk editing where appropriate */
15860   AddBulkEditing (d->clickable_list_data);
15861 
15862   PointerToDialog (d->clickable_list_dlg, d->clickable_list_data);
15863 
15864   ArrowCursor();
15865   Update();
15866 
15867 }
15868 
15869 
MarkFixableDiscrepancies(ButtoN b)15870 static void MarkFixableDiscrepancies (ButtoN b)
15871 {
15872   DiscrepancyReportFormPtr d;
15873 
15874   d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15875   if (d == NULL) {
15876     return;
15877   }
15878   ChooseFixableDiscrepancies (d->clickable_list_data);
15879   PointerToDialog (d->clickable_list_dlg, d->clickable_list_data);
15880 }
15881 
15882 
15883 /* Sequester by test */
ReportSequesterButton(ButtoN b)15884 static void ReportSequesterButton (ButtoN b)
15885 {
15886   ClickableItemData cid;
15887   Uint2          entityID;
15888   Int4              num_disc;
15889   ValNodePtr        sep_list;
15890 
15891   DiscrepancyReportFormPtr d;
15892 
15893   d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
15894   if (d == NULL) {
15895     return;
15896   }
15897 
15898   sep_list = GetViewedSeqEntryList ();
15899   if (sep_list == NULL) {
15900     return;
15901   } else if (sep_list->next != NULL) {
15902     Message (MSG_ERROR, "Can't sequester when viewing more than one record");
15903     return;
15904   } else {
15905     entityID = ObjMgrGetEntityIDForChoice (sep_list->data.ptrvalue);
15906   }
15907   sep_list = ValNodeFree (sep_list);
15908 
15909 
15910   num_disc = CountChosenDiscrepancies (d->clickable_list_data, FALSE);
15911 
15912   if (num_disc == 0)
15913   {
15914     Message (MSG_ERROR, "No discrepancies selected!");
15915     return;
15916   }
15917 
15918   MemSet (&cid, 0, sizeof (ClickableItemData));
15919   cid.chosen = FALSE;
15920   cid.item_list = NULL;
15921   cid.subcategories = d->clickable_list_data;
15922 
15923   if (SequesterClickableItem (entityID, &cid)) {
15924     SetDoReportAfterUnsequester (d->report_type);
15925   }
15926 }
15927 
15928 
CreateReportWindow(EDiscrepancyReportType report_type)15929 extern void CreateReportWindow (EDiscrepancyReportType report_type)
15930 {
15931   DiscrepancyReportFormPtr drfp;
15932   GrouP                    h;
15933   ButtoN                   b;
15934   GrouP                    c;
15935   GrouP                    c1;
15936   WindoW                   w;
15937   OMUserDataPtr            omudp;
15938 
15939   if (GetWindowForReportType(report_type) != NULL)
15940   {
15941     ReactivateDiscrepancyReport (report_type);
15942     return;
15943   }
15944 
15945   drfp = (DiscrepancyReportFormPtr) MemNew (sizeof (DiscrepancyReportFormData));
15946   if (drfp == NULL)
15947   {
15948     return;
15949   }
15950 
15951   w = FixedWindow (-50, -33, -10, -10, GetReportName (report_type), StdCloseWindowProc);
15952   SetObjectExtra (w, drfp, CleanupDiscrepancyReportForm);
15953   drfp->form = (ForM) w;
15954   drfp->formmessage = ClickableListFormMessage;
15955   drfp->exportform = DiscrepancyReportExportProc;
15956 
15957   /* read in config file */
15958   drfp->dcp = ReadDiscrepancyConfigEx(GetReportConfigName (report_type));
15959   drfp->report_type = report_type;
15960 
15961   /* adjust for report type */
15962   AdjustConfigForReportType (report_type, drfp->dcp);
15963 
15964   /* Discrepancy Report and MegaReport use log file for autofix */
15965   if (report_type == eReportTypeDiscrepancy || report_type == eReportTypeMegaReport) {
15966     drfp->log_name = StringSave ("Autofix Changes");
15967   }
15968 
15969   /* On-caller Tool uses special order */
15970   if (report_type == eReportTypeOnCaller) {
15971     drfp->reorder_results_proc = ReorderOnCallerResults;
15972   }
15973 
15974   /* register to receive update messages */
15975   drfp->userkey = OMGetNextUserKey ();
15976   drfp->procid = 0;
15977   drfp->proctype = OMPROC_EDIT;
15978   omudp = ObjMgrAddUserData (0, drfp->procid, drfp->proctype, drfp->userkey);
15979   if (omudp != NULL) {
15980     omudp->userdata.ptrvalue = (Pointer) drfp;
15981     omudp->messagefunc = ClickableListFormMsgFunc;
15982   }
15983 
15984 
15985 #ifndef WIN_MAC
15986   CreateStdValidatorFormMenus (w);
15987 #endif
15988 
15989   h = HiddenGroup (w, -1, 0, NULL);
15990   SetGroupSpacing (h, 10, 10);
15991 
15992   drfp->clickable_list_dlg = CreateClickableListDialog (h, "Discrepancies", "Affected Items",
15993                                                     ScrollToDiscrepancyItem, EditDiscrepancyItem, NULL,
15994                                                     GetDiscrepancyItemText);
15995 
15996   c1 = HiddenGroup (h, 3, 0, NULL);
15997   SetGroupSpacing (c1, 10, 10);
15998   b = PushButton (c1, "Expand All", ExpandAllDiscReportItems);
15999   SetObjectExtra (b, drfp, NULL);
16000   b = PushButton (c1, "Contract All", ContractAllDiscReportItems);
16001   SetObjectExtra (b, drfp, NULL);
16002   drfp->show_names = PushButton (c1, "Show Test Names", ToggleDiscrepancyReportNames);
16003   SetObjectExtra (drfp->show_names, drfp, NULL);
16004 
16005   c = HiddenGroup (h, 8, 0, NULL);
16006   SetGroupSpacing (c, 10, 10);
16007   b = PushButton (c, "Generate Report", GenerateDiscrepancyReport);
16008   SetObjectExtra (b, drfp, NULL);
16009   drfp->recheck_btn = PushButton (c, "Recheck", RecheckDiscrepancyProc);
16010   SetObjectExtra (drfp->recheck_btn, drfp, NULL);
16011   if (report_type == eReportTypeOnCaller) {
16012     drfp->add_entity_proc = AddNewEntityDiscrepancyProc;
16013   } else {
16014     drfp->add_entity_proc = NULL;
16015   }
16016   b = PushButton (c, "Mark Fixable", MarkFixableDiscrepancies);
16017   SetObjectExtra (b, drfp, NULL);
16018 
16019   b = PushButton (c, "Fix Marked", FixMarkedDiscrepanciesBtn);
16020   SetObjectExtra (b, drfp, NULL);
16021 
16022   b = PushButton (c, "Unmark All", UnmarkAllBtn);
16023   SetObjectExtra (b, drfp, NULL);
16024 
16025   b = PushButton (c, "Configure", GetReportEditButtonProc (report_type));
16026   SetObjectExtra (b, drfp, NULL);
16027 
16028   b = PushButton (c, "Sequester", ReportSequesterButton);
16029   SetObjectExtra (b, drfp, NULL);
16030 
16031   PushButton (c, "Dismiss", StdCancelButtonProc);
16032 
16033   AlignObjects (ALIGN_CENTER, (HANDLE) drfp->clickable_list_dlg, (HANDLE) c1, (HANDLE) c, NULL);
16034 
16035   RealizeWindow (w);
16036 
16037   /* populate discrepancy lists */
16038   RecheckDiscrepancyProc (drfp->recheck_btn);
16039   Show (w);
16040   SetWindowForReportType (w, report_type);
16041 }
16042 
16043 
RefreshAllReportWindows(Pointer data)16044 NLM_EXTERN void RefreshAllReportWindows (Pointer data)
16045 {
16046   Uint1 i;
16047   WindoW w;
16048 
16049   for (i = eReportTypeDiscrepancy; i < eReportType_End; i++) {
16050     w = GetWindowForReportType (i);
16051     if (w != NULL) {
16052       RecheckDiscrepancyWindow (w);
16053     }
16054   }
16055 }
16056 
16057 
16058 typedef struct sucform
16059 {
16060   CLICKABLE_LIST_FORM_BLOCK
16061 
16062   Boolean reverse;
16063   Boolean byblock;
16064   Boolean showsequence;
16065   Boolean is_registered;
16066 } SUCFormData, PNTR SUCFormPtr;
16067 
16068 
16069 static void UnregisterSuc (SUCFormPtr sfp);
16070 
SUCFormMsgFunc(OMMsgStructPtr ommsp)16071 static Int2 LIBCALLBACK SUCFormMsgFunc (OMMsgStructPtr ommsp)
16072 {
16073   WindoW         currentport,
16074                  temport;
16075   OMUserDataPtr  omudp;
16076   SUCFormPtr     sfp = NULL;
16077 
16078   omudp = (OMUserDataPtr)(ommsp->omuserdata);
16079   if (omudp == NULL) return OM_MSG_RET_ERROR;
16080   sfp = (SUCFormPtr) omudp->userdata.ptrvalue;
16081   if (sfp == NULL) return OM_MSG_RET_ERROR;
16082 
16083   currentport = ParentWindow (sfp->form);
16084   temport = SavePort (currentport);
16085   UseWindow (currentport);
16086   switch (ommsp->message)
16087   {
16088       case OM_MSG_UPDATE:
16089           break;
16090       case OM_MSG_DESELECT:
16091           break;
16092 
16093       case OM_MSG_SELECT:
16094           break;
16095       case OM_MSG_DEL:
16096           sfp->clickable_list_data = FreeClickableList (sfp->clickable_list_data);
16097           PointerToDialog (sfp->clickable_list_dlg, NULL);
16098           UnregisterSuc(sfp);
16099           break;
16100       case OM_MSG_HIDE:
16101           break;
16102       case OM_MSG_SHOW:
16103           break;
16104       case OM_MSG_FLUSH:
16105           sfp->clickable_list_data = FreeClickableList (sfp->clickable_list_data);
16106           PointerToDialog (sfp->clickable_list_dlg, NULL);
16107           UnregisterSuc(sfp);
16108           break;
16109       default:
16110           break;
16111   }
16112   RestorePort (temport);
16113   UseWindow (temport);
16114   return OM_MSG_RET_OK;
16115 }
16116 
16117 
RegisterSuc(SUCFormPtr sfp,Uint2 entityID)16118 static void RegisterSuc (SUCFormPtr sfp, Uint2 entityID)
16119 {
16120   OMUserDataPtr omudp;
16121 
16122   if (sfp == NULL || sfp->is_registered) {
16123     return;
16124   }
16125 
16126   /* register to receive update messages */
16127   sfp->input_entityID = entityID;
16128   sfp->userkey = OMGetNextUserKey ();
16129   sfp->procid = 0;
16130   sfp->proctype = OMPROC_EDIT;
16131   omudp = ObjMgrAddUserData (sfp->input_entityID, sfp->procid, sfp->proctype, sfp->userkey);
16132   if (omudp != NULL) {
16133     omudp->userdata.ptrvalue = (Pointer) sfp;
16134     omudp->messagefunc = SUCFormMsgFunc;
16135   }
16136   sfp->is_registered = TRUE;
16137 }
16138 
16139 
UnregisterSuc(SUCFormPtr sfp)16140 static void UnregisterSuc (SUCFormPtr sfp)
16141 {
16142   ObjMgrFreeUserData (sfp->input_entityID, sfp->procid, sfp->proctype, sfp->userkey);
16143   sfp->is_registered = FALSE;
16144 }
16145 
16146 
ReSUCProc(ButtoN b)16147 static void ReSUCProc (ButtoN b)
16148 {
16149   SUCFormPtr sfp;
16150   SeqEntryPtr sep;
16151   sfp = (SUCFormPtr) GetObjectExtra (b);
16152   if (sfp != NULL)
16153   {
16154     sep = GetTopSeqEntryForEntityID (sfp->input_entityID);
16155     RegisterSuc(sfp, sfp->input_entityID);
16156     WatchCursor();
16157     Update();
16158     sfp->clickable_list_data = FreeClickableList (sfp->clickable_list_data);
16159     sfp->clickable_list_data = GetSUCCommonList (sep, sfp->reverse, sfp->byblock, sfp->showsequence, TRUE);
16160     if (sfp->byblock) {
16161       sfp->clickable_list_data = CategorizeSUCBlocks (sfp->clickable_list_data);
16162     }
16163     AddBulkEditing (sfp->clickable_list_data);
16164     PointerToDialog (sfp->clickable_list_dlg, sfp->clickable_list_data);
16165     ArrowCursor();
16166     Update();
16167   }
16168 }
16169 
SetClickableItemExpanded(ValNodePtr vnp,Boolean expand)16170 static void SetClickableItemExpanded (ValNodePtr vnp, Boolean expand)
16171 {
16172   ClickableItemPtr cip;
16173 
16174   while (vnp != NULL) {
16175     cip = vnp->data.ptrvalue;
16176     if (cip != NULL) {
16177       cip->expanded = expand;
16178       SetClickableItemExpanded (cip->subcategories, expand);
16179     }
16180     vnp = vnp->next;
16181   }
16182 }
16183 
SUCExpand(ButtoN b,Boolean expand)16184 static void SUCExpand (ButtoN b, Boolean expand)
16185 {
16186   SUCFormPtr       sfp;
16187 
16188   sfp = (SUCFormPtr) GetObjectExtra (b);
16189   if (sfp != NULL)
16190   {
16191     SetClickableItemExpanded (sfp->clickable_list_data, expand);
16192     PointerToDialog (sfp->clickable_list_dlg, sfp->clickable_list_data);
16193   }
16194 }
16195 
SUCExpandAll(ButtoN b)16196 static void SUCExpandAll (ButtoN b)
16197 {
16198   SUCExpand (b, TRUE);
16199 }
16200 
SUCCollapseAll(ButtoN b)16201 static void SUCCollapseAll (ButtoN b)
16202 {
16203   SUCExpand (b, FALSE);
16204 }
16205 
16206 
SUCFormMessage(ForM f,Int2 mssg)16207 static void SUCFormMessage (ForM f, Int2 mssg)
16208 
16209 {
16210   SUCFormPtr    sfp;
16211 
16212   sfp = (SUCFormPtr) GetObjectExtra (f);
16213   if (sfp != NULL) {
16214     switch (mssg) {
16215       case VIB_MSG_EXPORT :
16216         if (sfp->exportform != NULL) {
16217           (sfp->exportform) (f, NULL);
16218         }
16219         break;
16220       case VIB_MSG_PRINT :
16221         break;
16222       case VIB_MSG_CLOSE :
16223         Remove (f);
16224         break;
16225       case VIB_MSG_CUT :
16226       case VIB_MSG_COPY :
16227         SendMessageToDialog (sfp->clickable_list_dlg, VIB_MSG_COPY);
16228         break;
16229       case VIB_MSG_PASTE :
16230         break;
16231       case VIB_MSG_DELETE :
16232         sfp->clickable_list_data = FreeClickableList (sfp->clickable_list_data);
16233         PointerToDialog (sfp->clickable_list_dlg, NULL);
16234         UnregisterSuc(sfp);
16235         break;
16236       default :
16237         if (sfp->appmessage != NULL) {
16238           sfp->appmessage (f, mssg);
16239         }
16240         break;
16241     }
16242   }
16243 }
16244 
16245 
NewSUC(ValNodePtr suc_list,Uint2 entityID,Boolean reverse,Boolean byblock,Boolean showsequence)16246 extern void NewSUC (ValNodePtr suc_list, Uint2 entityID, Boolean reverse, Boolean byblock, Boolean showsequence)
16247 {
16248   SUCFormPtr    sfp;
16249   GrouP         h;
16250   GrouP         c;
16251   WindoW        w;
16252   ButtoN        b;
16253 
16254   sfp = (SUCFormPtr) MemNew (sizeof (SUCFormData));
16255   if (sfp == NULL)
16256   {
16257     return;
16258   }
16259 
16260   w = FixedWindow (-50, -33, -10, -10, "SUC", StdCloseWindowProc);
16261   SetObjectExtra (w, sfp, CleanupClickableListForm);
16262   sfp->form = (ForM) w;
16263   sfp->formmessage = SUCFormMessage;
16264   sfp->exportform = DiscrepancyReportExportProc;
16265 
16266   /* register to receive update messages */
16267   sfp->input_entityID = entityID;
16268   RegisterSuc(sfp, sfp->input_entityID);
16269 
16270 #ifndef WIN_MAC
16271   CreateStdValidatorFormMenus (w);
16272 #endif
16273 
16274   /* set up parameters for re-SUC */
16275   sfp->reverse = reverse;
16276   sfp->byblock = byblock;
16277   sfp->showsequence = showsequence;
16278 
16279   h = HiddenGroup (w, -1, 0, NULL);
16280   SetGroupSpacing (h, 10, 10);
16281 
16282   sfp->clickable_list_dlg = CreateClickableListDialogEx (h, "Text", "Affected Items", NULL, NULL,
16283                                                          ScrollToDiscrepancyItem, EditDiscrepancyItem, NULL,
16284                                                          GetDiscrepancyItemText,
16285                                                          stdCharWidth * 55,
16286                                                          stdCharWidth * 55,
16287                                                          FALSE, TRUE);
16288   if (byblock) {
16289     suc_list = CategorizeSUCBlocks (suc_list);
16290     SetClickableItemExpanded (suc_list, FALSE);
16291   }
16292   AddBulkEditing (suc_list);
16293 
16294   sfp->clickable_list_data = suc_list;
16295   PointerToDialog (sfp->clickable_list_dlg, sfp->clickable_list_data);
16296 
16297 
16298   c = HiddenGroup (h, 4, 0, NULL);
16299   SetGroupSpacing (c, 10, 10);
16300   sfp->recheck_btn = PushButton (c, "Recheck", ReSUCProc);
16301   SetObjectExtra (sfp->recheck_btn, sfp, NULL);
16302 
16303   b = PushButton (c, "Expand All", SUCExpandAll);
16304   SetObjectExtra (b, sfp, NULL);
16305   b = PushButton (c, "Collapse All", SUCCollapseAll);
16306   SetObjectExtra (b, sfp, NULL);
16307 
16308   PushButton (c, "Dismiss", StdCancelButtonProc);
16309 
16310   AlignObjects (ALIGN_CENTER, (HANDLE) sfp->clickable_list_dlg, (HANDLE) c, NULL);
16311 
16312   RealizeWindow (w);
16313 
16314   Show (w);
16315 }
16316 
16317 
ConvertLocalToGeneralCallback(BioseqPtr bsp,Pointer userdata)16318 static void ConvertLocalToGeneralCallback (BioseqPtr bsp, Pointer userdata)
16319 {
16320   SeqIdPtr    sip, sip_new;
16321   ObjectIdPtr oip;
16322   CharPtr     db_end;
16323   DbtagPtr    dbtag;
16324   Boolean     found = TRUE;
16325 
16326   if (bsp == NULL) {
16327     return;
16328   }
16329 
16330   while (found) {
16331     found = FALSE;
16332     for (sip = bsp->id; sip != NULL && !found; sip = sip->next) {
16333       if (sip->choice == SEQID_LOCAL) {
16334         oip = (ObjectIdPtr) sip->data.ptrvalue;
16335         if (oip->str) {
16336           db_end = StringChr (oip->str, ':');
16337             if (db_end != NULL && !StringHasNoText (db_end + 1)) {
16338             dbtag = DbtagNew();
16339             dbtag->tag = ObjectIdNew();
16340             dbtag->tag->str = StringSave (db_end + 1);
16341             *db_end = 0;
16342             dbtag->db = StringSave (oip->str);
16343             sip_new = ValNodeNew(NULL);
16344             sip_new->choice = SEQID_GENERAL;
16345             sip_new->data.ptrvalue = dbtag;
16346             BioseqReplaceID (bsp, sip_new);
16347             sip_new = SeqIdFree (sip_new);
16348             found = TRUE;
16349           }
16350         }
16351       }
16352     }
16353   }
16354 }
16355 
ConvertLocalToGeneral(IteM i)16356 extern void ConvertLocalToGeneral(IteM i)
16357 {
16358   BaseFormPtr       bfp;
16359   SeqEntryPtr       sep;
16360 
16361 #ifdef WIN_MAC
16362   bfp = currentFormDataPtr;
16363 #else
16364   bfp = GetObjectExtra (i);
16365 #endif
16366   if (bfp == NULL) return;
16367   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
16368   if (sep == NULL) return;
16369   WatchCursor ();
16370   Update ();
16371   VisitBioseqsInSep (sep, NULL, ConvertLocalToGeneralCallback);
16372   ArrowCursor ();
16373   Update ();
16374   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
16375   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
16376 }
16377 
16378 
SetFeatureID(SeqFeatPtr sfp,Int4 id)16379 static void SetFeatureID (SeqFeatPtr sfp, Int4 id)
16380 {
16381   SeqFeatXrefPtr    xref;
16382   ObjectIdPtr       oip;
16383 
16384   if (sfp == NULL) return;
16385 
16386   for (xref = sfp->xref; xref != NULL && xref->id.choice != 3; xref = xref->next) continue;
16387   if (xref != NULL) {
16388     oip = (ObjectIdPtr) xref->id.value.ptrvalue;
16389     if (oip != NULL) {
16390       if (oip->str != NULL) {
16391         oip->str = MemFree (oip->str);
16392       }
16393       oip->id = id;
16394     }
16395   } else {
16396     xref = SeqFeatXrefNew ();
16397     if (xref != NULL) {
16398       oip = ObjectIdNew ();
16399       if (oip != NULL) {
16400         oip->id = id;
16401         xref->id.choice = 3;
16402         xref->id.value.ptrvalue = (Pointer) oip;
16403         xref->next = sfp->xref;
16404         sfp->xref = xref;
16405       }
16406     }
16407   }
16408 }
16409 
SetCDSProductName(SeqFeatPtr cds,CharPtr product_name)16410 static void SetCDSProductName (SeqFeatPtr cds, CharPtr product_name)
16411 {
16412   BioseqPtr         prot_bsp;
16413   SeqFeatPtr        prot_feat;
16414   SeqMgrFeatContext context;
16415   Boolean           partial3, partial5;
16416   SeqEntryPtr       prot_sep;
16417   ProtRefPtr        prp;
16418 
16419   if (cds == NULL || cds->data.choice != SEQFEAT_CDREGION
16420       || cds->product == NULL) return;
16421 
16422   prot_bsp = BioseqFindFromSeqLoc (cds->product);
16423   if (prot_bsp == NULL) return;
16424 
16425   CheckSeqLocForPartial (cds->location, &partial5, &partial3);
16426 
16427   prot_feat = SeqMgrGetNextFeature (prot_bsp, NULL, SEQFEAT_PROT, FEATDEF_PROT, &context);
16428   if (prot_feat == NULL) {
16429     prot_sep = SeqMgrGetSeqEntryForData (prot_bsp);
16430     prot_feat = CreateNewFeature (prot_sep, NULL, SEQFEAT_PROT, NULL);
16431     prp = ProtRefNew ();
16432     ValNodeAddPointer (&(prp->name), 0, StringSave (product_name));
16433     prot_feat->data.value.ptrvalue = prp;
16434     prot_feat->location = SeqLocFree (prot_feat->location);
16435     prot_feat->location = CreateWholeInterval (prot_sep);
16436     SetSeqLocPartial (prot_feat->location, partial5, partial3);
16437     prot_feat->partial = (partial5 || partial3);
16438   } else {
16439     prp = prot_feat->data.value.ptrvalue;
16440     prp->name = ValNodeFreeData (prp->name);
16441     ValNodeAddPointer (&(prp->name), 0, StringSave (product_name));
16442   }
16443 }
16444 
16445 
GetmRNAProductName(SeqFeatPtr sfp)16446 static CharPtr GetmRNAProductName (SeqFeatPtr sfp)
16447 {
16448   RnaRefPtr rrp;
16449   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return NULL;
16450 
16451   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
16452   if (rrp != NULL && rrp->type == RNA_TYPE_mRNA && rrp->ext.choice == 1) {
16453     return rrp->ext.value.ptrvalue;
16454   } else {
16455     return NULL;
16456   }
16457 }
16458 
16459 
MakeCDSmRNAPairsCallback(BioseqPtr bsp,Pointer userdata)16460 static void MakeCDSmRNAPairsCallback (BioseqPtr bsp, Pointer userdata)
16461 {
16462   SeqMgrFeatContext context1, context2;
16463   SeqFeatPtr        cds, mRNA, first_mRNA, new_cds;
16464   Int2              loc_compare;
16465   SeqEntryPtr       sep, top_sep;
16466   ObjectIdPtr       oip_cds, oip_mrna;
16467   ValNodePtr        pair_list = NULL, vnp;
16468 
16469   if (bsp == NULL || ISA_aa (bsp->mol)) return;
16470 
16471   sep = SeqMgrGetSeqEntryForData (bsp);
16472   if (sep == NULL) return;
16473 
16474   for (cds = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, FEATDEF_CDS, &context1);
16475        cds != NULL;
16476        cds = SeqMgrGetNextFeature (bsp, cds, SEQFEAT_CDREGION, FEATDEF_CDS, &context1)) {
16477     first_mRNA = NULL;
16478 
16479     for (mRNA = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_RNA, FEATDEF_mRNA, &context2);
16480          mRNA != NULL;
16481          mRNA = SeqMgrGetNextFeature (bsp, mRNA, SEQFEAT_RNA, FEATDEF_mRNA, &context2)) {
16482       if (context2.left > context1.right) {
16483         /* out of range */
16484         break;
16485       }
16486       if (StringNCmp (context2.label, context1.label, StringLen (context1.label)) != 0) {
16487         /* need root product name to match */
16488         continue;
16489       }
16490       loc_compare = SeqLocCompare (cds->location, mRNA->location);
16491       if (loc_compare != SLC_A_IN_B && loc_compare != SLC_A_EQ_B) {
16492         /* CDS must be equal to or inside mRNA */
16493         continue;
16494       }
16495 
16496       if (first_mRNA == NULL) {
16497         first_mRNA = mRNA;
16498         new_cds = cds;
16499       } else {
16500         new_cds = (SeqFeatPtr) AsnIoMemCopy (cds, (AsnReadFunc) SeqFeatAsnRead, (AsnWriteFunc) SeqFeatAsnWrite);
16501         new_cds->product = SeqLocFree (new_cds->product);
16502         new_cds->xref = SeqFeatXrefFree (new_cds->xref);
16503         SeqFeatIdFree(&new_cds->id);
16504         CreateNewFeature (sep, NULL, SEQFEAT_CDREGION, new_cds);
16505         RetranslateOneCDS (new_cds, cds->idx.entityID, FALSE, FALSE);
16506       }
16507       ValNodeAddPointer (&pair_list, SEQFEAT_RNA, mRNA);
16508       ValNodeAddPointer (&pair_list, SEQFEAT_CDREGION, new_cds);
16509     }
16510   }
16511   top_sep = GetTopSeqEntryForEntityID (bsp->idx.entityID);
16512   SeqMgrIndexFeatures (bsp->idx.entityID, NULL);
16513   AssignFeatureIDs (top_sep);
16514   vnp = pair_list;
16515   while (vnp != NULL) {
16516     mRNA = vnp->data.ptrvalue;
16517     vnp = vnp->next;
16518     if (vnp != NULL) {
16519       new_cds = vnp->data.ptrvalue;
16520       SetCDSProductName (new_cds, GetmRNAProductName(mRNA));
16521       oip_mrna = (ObjectIdPtr) mRNA->id.value.ptrvalue;
16522       oip_cds = (ObjectIdPtr) new_cds->id.value.ptrvalue;
16523       if (oip_mrna != NULL && oip_cds != NULL
16524           && oip_mrna->id > 0 && oip_cds->id > 0) {
16525         /* add xref to cds to point to mRNA */
16526         SetFeatureID (new_cds, oip_mrna->id);
16527         /* add xref to mrna to point to cds */
16528         SetFeatureID (mRNA, oip_cds->id);
16529       }
16530       vnp = vnp->next;
16531     }
16532   }
16533   pair_list = ValNodeFree (pair_list);
16534 }
16535 
16536 
MakeCDSmRNAPairs(IteM i)16537 extern void MakeCDSmRNAPairs (IteM i)
16538 {
16539   BaseFormPtr       bfp;
16540   SeqEntryPtr       sep;
16541 
16542 #ifdef WIN_MAC
16543   bfp = currentFormDataPtr;
16544 #else
16545   bfp = GetObjectExtra (i);
16546 #endif
16547   if (bfp == NULL) return;
16548   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
16549   if (sep == NULL) return;
16550   WatchCursor ();
16551   Update ();
16552   VisitBioseqsInSep (sep, NULL, MakeCDSmRNAPairsCallback);
16553   ArrowCursor ();
16554   Update ();
16555   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
16556   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
16557 }
16558 
16559 
ApplyNameRNACallback(BioseqPtr bsp,Pointer userdata)16560 static void ApplyNameRNACallback (BioseqPtr bsp, Pointer userdata)
16561 {
16562   CharPtr    rnaName = (CharPtr) userdata;
16563   RnaRefPtr  rrp;
16564   SeqFeatPtr sfp;
16565   SeqEntryPtr sep;
16566 
16567   if (bsp == NULL || ISA_aa (bsp->mol) || StringHasNoText (rnaName)) {
16568     return;
16569   }
16570   sep = SeqMgrGetSeqEntryForData (bsp);
16571   if (sep == NULL) return;
16572 
16573   rrp = RnaRefNew ();
16574   rrp->type = RNA_TYPE_rRNA;
16575   rrp->ext.choice = 1;
16576   rrp->ext.value.ptrvalue = StringSave (rnaName);
16577   sfp = SeqFeatNew ();
16578   sfp->data.choice = SEQFEAT_RNA;
16579   sfp->data.value.ptrvalue = rrp;
16580   sfp->location = CreateWholeInterval (sep);
16581   SetSeqLocPartial (sfp->location, TRUE, TRUE);
16582   sfp->partial = TRUE;
16583   CreateNewFeature (sep, NULL, SEQFEAT_RNA, sfp);
16584 }
16585 
16586 
ApplyNamedRNABaseForm(BaseFormPtr bfp,CharPtr rnaName)16587 NLM_EXTERN void ApplyNamedRNABaseForm (BaseFormPtr bfp, CharPtr rnaName)
16588 {
16589   SeqEntryPtr       sep;
16590 
16591   if (bfp == NULL) return;
16592   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
16593   if (sep == NULL) return;
16594   WatchCursor ();
16595   Update ();
16596   VisitBioseqsInSep (sep, rnaName, ApplyNameRNACallback);
16597   ArrowCursor ();
16598   Update ();
16599   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
16600   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
16601 }
16602 
16603 
ApplyNamedRNA(IteM i,CharPtr rnaName)16604 static void ApplyNamedRNA (IteM i, CharPtr rnaName)
16605 {
16606   BaseFormPtr       bfp;
16607 
16608 #ifdef WIN_MAC
16609   bfp = currentFormDataPtr;
16610 #else
16611   bfp = GetObjectExtra (i);
16612 #endif
16613 
16614   ApplyNamedRNABaseForm (bfp, rnaName);
16615 }
16616 
16617 
Apply16SRNA(IteM i)16618 extern void Apply16SRNA (IteM i)
16619 {
16620   ApplyNamedRNA (i, "16S ribosomal RNA");
16621 }
16622 
16623 
Apply23SRNA(IteM i)16624 extern void Apply23SRNA (IteM i)
16625 {
16626   ApplyNamedRNA (i, "23S ribosomal RNA");
16627 }
16628 
16629 
Apply18SRNA(IteM i)16630 extern void Apply18SRNA (IteM i)
16631 {
16632   ApplyNamedRNA (i, "18S ribosomal RNA");
16633 }
16634 
16635 
Apply28SRNA(IteM i)16636 extern void Apply28SRNA (IteM i)
16637 {
16638   ApplyNamedRNA (i, "28S ribosomal RNA");
16639 }
16640 
16641 
Apply26SRNA(IteM i)16642 extern void Apply26SRNA (IteM i)
16643 {
16644   ApplyNamedRNA (i, "26S ribosomal RNA");
16645 }
16646 
16647 
Apply12SRNA(IteM i)16648 extern void Apply12SRNA (IteM i)
16649 {
16650   ApplyNamedRNA (i, "12S ribosomal RNA");
16651 }
16652 
16653 
ApplySmallRNA(IteM i)16654 extern void ApplySmallRNA (IteM i)
16655 {
16656   ApplyNamedRNA (i, "small subunit ribosomal RNA");
16657 }
16658 
16659 
ApplyLargeRNA(IteM i)16660 extern void ApplyLargeRNA (IteM i)
16661 {
16662   ApplyNamedRNA (i, "large subunit ribosomal RNA");
16663 }
16664 
16665 
16666 typedef struct rnaits {
16667   FORM_MESSAGE_BLOCK
16668   ButtoN       partial_5;
16669   ButtoN       partial_3;
16670   DialoG       rna_list;
16671   ButtoN       leave_dlg_up;
16672   ButtoN       accept;
16673   /* for alignment coordinates */
16674   ButtoN       use_aln;
16675   PopuP        this_aln;
16676   GrouP        gap_handling;
16677 
16678   BaseFormPtr       bfp;
16679   TaglistCallback   callbacks[3];
16680   Uint2             interval_types[3];
16681   Uint2             interval_widths[3];
16682   EnumFieldAssocPtr alists[3];
16683 
16684   ValNodePtr        prev_list;
16685   /* for alignment coordinates */
16686   SeqAlignPtr       salp_list;
16687   SeqAlignPtr       chosen_salp;
16688 
16689   /* for propagation */
16690   ValNodePtr        feature_list;
16691 } RNAITSData, PNTR RNAITSPtr;
16692 
16693 typedef enum {
16694   eRNA_ITS_INVALID = 0,
16695   eRNA_ITS_18S,
16696   eRNA_ITS_18S_SMALL,
16697   eRNA_ITS_SMALL,
16698   eRNA_ITS_ITS1,
16699   eRNA_ITS_58S,
16700   eRNA_ITS_ITS2,
16701   eRNA_ITS_28S,
16702   eRNA_ITS_28S_LARGE,
16703   eRNA_ITS_LARGE,
16704   eRNA_ITS_26S,
16705   eRNA_ITS_26S_LARGE,
16706   eRNA_ITS_25S,
16707   eRNA_ITS_25S_LARGE
16708 } ERNA_ITS_type;
16709 
ENUM_ALIST(rna_its_alist)16710 static ENUM_ALIST(rna_its_alist)
16711 {" ",                                 eRNA_ITS_INVALID},
16712 {"18S ribosomal RNA",                 eRNA_ITS_18S},
16713 {"18S small subunit ribosomal RNA",   eRNA_ITS_18S_SMALL},
16714 {"small subunit ribosomal RNA",       eRNA_ITS_SMALL},
16715 
16716 {"internal transcribed spacer 1",     eRNA_ITS_ITS1},
16717 
16718 {"5.8S ribosomal RNA",                eRNA_ITS_58S},
16719 
16720 {"internal transcribed spacer 2",     eRNA_ITS_ITS2},
16721 
16722 {"28S ribosomal RNA",                 eRNA_ITS_28S},
16723 {"28S large subunit ribosomal RNA",   eRNA_ITS_28S_LARGE},
16724 {"large subunit ribosomal RNA",       eRNA_ITS_LARGE},
16725 {"26S ribosomal RNA",                 eRNA_ITS_26S},
16726 {"26S large subunit ribosomal RNA",   eRNA_ITS_26S_LARGE},
16727 {"25S ribosomal RNA",                 eRNA_ITS_25S},
16728 {"25S large subunit ribosomal RNA",   eRNA_ITS_25S_LARGE},
16729 END_ENUM_ALIST
16730 
16731 static ENUM_ALIST(rna_its_popup_alist)
16732 {" ",                                 eRNA_ITS_INVALID},
16733 {"18S rRNA",                          eRNA_ITS_18S},
16734 {"small subunit",                     eRNA_ITS_SMALL},
16735 {"ITS1",                              eRNA_ITS_ITS1},
16736 {"5.8S rRNA",                         eRNA_ITS_58S},
16737 {"ITS2",                              eRNA_ITS_ITS2},
16738 {"28S rRNA",                          eRNA_ITS_28S},
16739 {"26S rRNA",                          eRNA_ITS_26S},
16740 {"25S rRNA",                          eRNA_ITS_25S},
16741 {"large subunit rRNA",                eRNA_ITS_LARGE},
16742 {"18S small subunit rRNA",            eRNA_ITS_18S_SMALL},
16743 {"28S large subunit rRNA",            eRNA_ITS_28S_LARGE},
16744 {"26S large subunit rRNA",            eRNA_ITS_26S_LARGE},
16745 {"25S large subunit rRNA",            eRNA_ITS_25S_LARGE},
16746 END_ENUM_ALIST
16747 
16748 static CharPtr RNANameFromRNAType (ERNA_ITS_type rna_type)
16749 {
16750   EnumFieldAssocPtr eap = rna_its_alist;
16751   while (eap != NULL && eap->name != NULL && eap->value != rna_type)
16752   {
16753     eap++;
16754   }
16755   return eap->name;
16756 }
16757 
16758 typedef struct rna_its_item {
16759   ERNA_ITS_type rna_type;
16760   Int4          left;
16761   Int4          right;
16762 } RNA_ITS_ItemData, PNTR RNA_ITS_ItemPtr;
16763 
MarkRNAITSDiffs(ValNodePtr vnp_new,ValNodePtr vnp_old)16764 static void MarkRNAITSDiffs (ValNodePtr vnp_new, ValNodePtr vnp_old)
16765 {
16766   RNA_ITS_ItemPtr rip_new, rip_old;
16767   while (vnp_new != NULL) {
16768     if (vnp_old == NULL) {
16769       vnp_new->choice = 1;
16770     } else {
16771       rip_new = vnp_new->data.ptrvalue;
16772       rip_old = vnp_old->data.ptrvalue;
16773       if (rip_old == NULL && rip_new == NULL) {
16774         /* no change */
16775       } else if (rip_old == NULL || rip_new == NULL) {
16776         vnp_new->choice = 1;
16777       } else if (rip_new->rna_type != rip_old->rna_type
16778                  || rip_new->left != rip_old->left
16779                  || rip_new->right != rip_old->right) {
16780         vnp_new->choice = 1;
16781       }
16782       vnp_old = vnp_old->next;
16783     }
16784     vnp_new = vnp_new->next;
16785   }
16786 }
16787 
TagListStringToRNAITSItem(CharPtr line)16788 static RNA_ITS_ItemPtr TagListStringToRNAITSItem (CharPtr line)
16789 {
16790   RNA_ITS_ItemPtr rip;
16791   CharPtr         txt;
16792   Int4            tmp;
16793 
16794   rip = (RNA_ITS_ItemPtr) MemNew (sizeof (RNA_ITS_ItemData));
16795 
16796   /* get interval values */
16797   txt = ExtractTagListColumn (line, 1);
16798   if (StringHasNoText (txt)) {
16799     rip->left = -1;
16800   } else {
16801     StrToLong (txt, &rip->left);
16802   }
16803   txt = MemFree (txt);
16804   txt = ExtractTagListColumn (line, 2);
16805   if (StringHasNoText (txt)) {
16806     rip->right = -1;
16807   } else {
16808     StrToLong (txt, &rip->right);
16809   }
16810   txt = MemFree (txt);
16811 
16812   txt = ExtractTagListColumn (line, 0);
16813   if (StringHasNoText (txt)) {
16814     rip->rna_type = eRNA_ITS_INVALID;
16815   } else {
16816     StrToLong (txt, &tmp);
16817     rip->rna_type = (ERNA_ITS_type) tmp;
16818   }
16819   txt = MemFree (txt);
16820 
16821   return rip;
16822 }
16823 
RNAITSItemToTagListString(RNA_ITS_ItemPtr rip)16824 static CharPtr RNAITSItemToTagListString (RNA_ITS_ItemPtr rip)
16825 {
16826   Char new_line[100];
16827   Char left_str[15];
16828   Char right_str[15];
16829 
16830   if (rip == NULL) return NULL;
16831   if (rip->left > -1) {
16832     sprintf (left_str, "%d", rip->left);
16833   } else {
16834     sprintf (left_str, "%s", "");
16835   }
16836   if (rip->right > -1) {
16837     sprintf (right_str, "%d", rip->right);
16838   } else {
16839     sprintf (right_str, "%s", "");
16840   }
16841   sprintf (new_line, "%d\t%s\t%s\n", rip->rna_type, left_str, right_str);
16842   return StringSave (new_line);
16843 }
16844 
NextRNAITSChoice(ERNA_ITS_type rna_type)16845 static ERNA_ITS_type NextRNAITSChoice (ERNA_ITS_type rna_type)
16846 {
16847   ERNA_ITS_type next_type = eRNA_ITS_INVALID;
16848 
16849   switch (rna_type) {
16850     case eRNA_ITS_INVALID:
16851       next_type = eRNA_ITS_INVALID;
16852       break;
16853     case eRNA_ITS_18S:
16854     case eRNA_ITS_18S_SMALL:
16855     case eRNA_ITS_SMALL:
16856       next_type = eRNA_ITS_ITS1;
16857       break;
16858     case eRNA_ITS_ITS1:
16859       next_type = eRNA_ITS_58S;
16860       break;
16861     case eRNA_ITS_58S:
16862       next_type = eRNA_ITS_ITS2;
16863       break;
16864     case eRNA_ITS_ITS2:
16865       next_type = eRNA_ITS_28S;
16866       break;
16867     case eRNA_ITS_28S:
16868     case eRNA_ITS_28S_LARGE:
16869     case eRNA_ITS_LARGE:
16870     case eRNA_ITS_26S:
16871     case eRNA_ITS_26S_LARGE:
16872     case eRNA_ITS_25S:
16873     case eRNA_ITS_25S_LARGE:
16874       next_type = eRNA_ITS_INVALID;
16875       break;
16876   }
16877   return next_type;
16878 }
16879 
OkNextRNAITSChoice(ERNA_ITS_type rna_type,ERNA_ITS_type next_rna_type)16880 static Boolean OkNextRNAITSChoice (ERNA_ITS_type rna_type, ERNA_ITS_type next_rna_type)
16881 {
16882   Boolean is_ok = FALSE;
16883 
16884   switch (rna_type) {
16885     case eRNA_ITS_INVALID:
16886       is_ok = (next_rna_type == eRNA_ITS_INVALID);
16887       break;
16888     case eRNA_ITS_18S:
16889     case eRNA_ITS_18S_SMALL:
16890     case eRNA_ITS_SMALL:
16891       is_ok = (next_rna_type == eRNA_ITS_ITS1);
16892       break;
16893     case eRNA_ITS_ITS1:
16894       is_ok = (next_rna_type == eRNA_ITS_58S);
16895       break;
16896     case eRNA_ITS_58S:
16897       is_ok = (next_rna_type == eRNA_ITS_ITS2);
16898       break;
16899     case eRNA_ITS_ITS2:
16900       if (next_rna_type == eRNA_ITS_28S
16901           || next_rna_type == eRNA_ITS_28S_LARGE
16902           || next_rna_type == eRNA_ITS_LARGE
16903           || next_rna_type == eRNA_ITS_26S
16904           || next_rna_type == eRNA_ITS_26S_LARGE
16905           || next_rna_type == eRNA_ITS_25S
16906           || next_rna_type == eRNA_ITS_25S_LARGE) {
16907         is_ok = TRUE;
16908       } else {
16909         is_ok = FALSE;
16910       }
16911       break;
16912     case eRNA_ITS_28S:
16913     case eRNA_ITS_28S_LARGE:
16914     case eRNA_ITS_LARGE:
16915     case eRNA_ITS_26S:
16916     case eRNA_ITS_26S_LARGE:
16917     case eRNA_ITS_25S:
16918     case eRNA_ITS_25S_LARGE:
16919       is_ok = (next_rna_type == eRNA_ITS_INVALID);
16920       break;
16921   }
16922   return is_ok;
16923 }
16924 
TagListToRNAITSList(DialoG d)16925 static Pointer TagListToRNAITSList (DialoG d)
16926 {
16927   TagListPtr  tlp;
16928   ValNodePtr  rip_list = NULL, vnp;
16929   RNA_ITS_ItemPtr rip;
16930 
16931   tlp = (TagListPtr) GetObjectExtra (d);
16932   if (tlp == NULL) return NULL;
16933   vnp = tlp->vnp;
16934   while (vnp != NULL) {
16935     rip = TagListStringToRNAITSItem (vnp->data.ptrvalue);
16936     if (rip != NULL) {
16937       ValNodeAddPointer (&rip_list, 0, rip);
16938     }
16939     vnp = vnp->next;
16940   }
16941   return (Pointer) rip_list;
16942 }
16943 
RNAITSListToTagList(DialoG d,Pointer data)16944 static void RNAITSListToTagList (DialoG d, Pointer data)
16945 {
16946   TagListPtr  tlp;
16947   ValNodePtr  rip_list, vnp;
16948   RNA_ITS_ItemPtr rip;
16949 
16950   tlp = (TagListPtr) GetObjectExtra (d);
16951   if (tlp == NULL) return;
16952   rip_list = (ValNodePtr) data;
16953   tlp->vnp = ValNodeFreeData (tlp->vnp);
16954   vnp = rip_list;
16955   while (vnp != NULL) {
16956     rip = (vnp->data.ptrvalue);
16957     if (rip != NULL) {
16958       ValNodeAddPointer (&tlp->vnp, 0, RNAITSItemToTagListString (rip));
16959     }
16960     vnp = vnp->next;
16961   }
16962   SendMessageToDialog (d, VIB_MSG_REDRAW);
16963 }
16964 
RNA_ITS_ChoiceCallback(Pointer userdata)16965 static void RNA_ITS_ChoiceCallback (Pointer userdata)
16966 {
16967   RNAITSPtr   rp;
16968   TagListPtr  tlp;
16969   ValNodePtr  vnp, prev_vnp;
16970   RNA_ITS_ItemPtr rip, rip_prev = NULL;
16971   Boolean         any_changes = FALSE, any_changes_this;
16972 
16973   rp = (RNAITSPtr) userdata;
16974   if (rp == NULL) return;
16975 
16976   tlp = (TagListPtr) GetObjectExtra (rp->rna_list);
16977   if (tlp == NULL) {
16978     return;
16979   }
16980 
16981   for (vnp = tlp->vnp, prev_vnp = NULL;
16982        vnp != NULL;
16983        prev_vnp = vnp, vnp = vnp->next) {
16984     rip = TagListStringToRNAITSItem (vnp->data.ptrvalue);
16985     if (rip_prev == NULL) {
16986       if (rip->left == -1) {
16987         any_changes = TRUE;
16988         rip->left = 1;
16989         vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
16990         vnp->data.ptrvalue = RNAITSItemToTagListString (rip);
16991       }
16992     } else {
16993       any_changes_this = FALSE;
16994       if (!OkNextRNAITSChoice(rip_prev->rna_type, rip->rna_type)) {
16995         /* fix type for this line */
16996         any_changes_this = TRUE;
16997         rip->rna_type = NextRNAITSChoice (rip_prev->rna_type);
16998       }
16999       /* fix interval for this line */
17000       if (rip->left == -1 && rip_prev->right != -1) {
17001         any_changes_this = TRUE;
17002         rip->left = rip_prev->right + 1;
17003       }
17004       if (any_changes_this) {
17005         vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
17006         vnp->data.ptrvalue = RNAITSItemToTagListString (rip);
17007         any_changes = TRUE;
17008       }
17009       /* fix interval for previous line */
17010       if (rip_prev->right == -1 && rip->left > 0) {
17011         any_changes = TRUE;
17012         rip_prev->right = rip->left - 1;
17013         prev_vnp->data.ptrvalue = MemFree (prev_vnp->data.ptrvalue);
17014         prev_vnp->data.ptrvalue = RNAITSItemToTagListString (rip_prev);
17015       }
17016     }
17017     rip_prev = MemFree (rip_prev);
17018     rip_prev = rip;
17019   }
17020   /* fill out the chain */
17021   while (rip_prev != NULL && NextRNAITSChoice(rip_prev->rna_type) != eRNA_ITS_INVALID) {
17022     rip = (RNA_ITS_ItemPtr) MemNew (sizeof (RNA_ITS_ItemData));
17023     rip->rna_type = NextRNAITSChoice(rip_prev->rna_type);
17024     if (rip_prev->right > -1) {
17025       rip->left = rip_prev->right + 1;
17026     } else {
17027       rip->left = -1;
17028     }
17029     rip->right = -1;
17030     ValNodeAddPointer (&tlp->vnp, 0, RNAITSItemToTagListString (rip));
17031     any_changes = TRUE;
17032     rip_prev = MemFree (rip_prev);
17033     rip_prev = rip;
17034   }
17035   rip_prev = MemFree (rip_prev);
17036   if (any_changes) {
17037     SendMessageToDialog (rp->rna_list, VIB_MSG_REDRAW);
17038   }
17039   rp->prev_list = ValNodeFreeData (rp->prev_list);
17040   rp->prev_list = TagListToRNAITSList (rp->rna_list);
17041 }
17042 
RNA_ITS_IntervalCallback(Pointer data)17043 extern void RNA_ITS_IntervalCallback (Pointer data)
17044 {
17045   RNAITSPtr   rp;
17046   TagListPtr  tlp;
17047   ValNodePtr  vnp, prev_vnp, new_list;
17048   RNA_ITS_ItemPtr rip, rip_prev = NULL;
17049   Boolean         any_changes = FALSE;
17050 
17051   rp = (RNAITSPtr) data;
17052   if (rp == NULL) return;
17053 
17054   tlp = (TagListPtr) GetObjectExtra (rp->rna_list);
17055   if (tlp == NULL) {
17056     return;
17057   }
17058   new_list = TagListToRNAITSList (rp->rna_list);
17059   MarkRNAITSDiffs (new_list, rp->prev_list);
17060   for (vnp = new_list, prev_vnp = NULL;
17061        vnp != NULL;
17062        prev_vnp = vnp, vnp = vnp->next) {
17063     rip = vnp->data.ptrvalue;
17064     if (rip_prev == NULL) {
17065       if (rip->left == -1) {
17066         rip->left = 0;
17067         any_changes = TRUE;
17068       }
17069     } else {
17070       /* fix interval for this line */
17071       if (rip->left == -1 && rip_prev->right != -1) {
17072         any_changes = TRUE;
17073         rip->left = rip_prev->right + 1;
17074       }
17075       /* fix interval for previous line */
17076       if (rip_prev->right == -1 && rip->left > 0) {
17077         any_changes = TRUE;
17078         rip_prev->right = rip->left - 1;
17079       }
17080       if (vnp->choice == 1) {
17081         if (rip->left != -1 && rip_prev->right != rip->left - 1) {
17082           any_changes = TRUE;
17083           rip_prev->right = rip->left - 1;
17084         }
17085       } else if (prev_vnp->choice == 1) {
17086         if (rip_prev->right != -1 && rip->left != rip_prev->right + 1) {
17087           any_changes = TRUE;
17088           rip->left = rip_prev->right + 1;
17089         }
17090       }
17091     }
17092     rip_prev = rip;
17093   }
17094   if (any_changes) {
17095     RNAITSListToTagList (rp->rna_list, new_list);
17096     SendMessageToDialog (rp->rna_list, VIB_MSG_REDRAW);
17097   }
17098   new_list = ValNodeFreeData (new_list);
17099   rp->prev_list = ValNodeFreeData (rp->prev_list);
17100   rp->prev_list = TagListToRNAITSList (rp->rna_list);
17101 }
17102 
GetAlnRowForBsp(BioseqPtr bsp,SeqAlignPtr salp)17103 static Int4 GetAlnRowForBsp (BioseqPtr bsp, SeqAlignPtr salp)
17104 {
17105   Int4     aln_row;
17106   SeqIdPtr sip;
17107 
17108   if (bsp == NULL || salp == NULL)
17109   {
17110     return 0;
17111   }
17112 
17113   for (aln_row = 1; aln_row <= salp->dim; aln_row++)
17114   {
17115     sip = AlnMgr2GetNthSeqIdPtr(salp, aln_row);
17116     if (SeqIdIn (sip, bsp->id))
17117     {
17118       return aln_row;
17119     }
17120   }
17121   return 0;
17122 }
17123 
ChooseEndpoint(Int4 bsp_len,Int4 pos,Boolean is_left,SeqAlignPtr salp,Int4 aln_row)17124 static Int4 ChooseEndpoint (Int4 bsp_len, Int4 pos, Boolean is_left, SeqAlignPtr salp, Int4 aln_row)
17125 {
17126   Int4 tmp;
17127   Int4 aln_len;
17128 
17129   aln_len = SeqAlignLength (salp);
17130   if (pos < 0) {
17131     if (is_left) {
17132       pos = 0;
17133     } else {
17134       pos = bsp_len - 1;
17135     }
17136   } else if (salp == NULL) {
17137     if (pos > bsp_len - 1) {
17138       if (is_left) {
17139         pos = -1;
17140       } else {
17141         pos = bsp_len - 1;
17142       }
17143     }
17144   } else if (salp != NULL) {
17145     tmp = AlnMgr2MapSeqAlignToBioseq (salp, pos, aln_row);
17146     if (is_left) {
17147       while (tmp < 0 && pos < aln_len) {
17148         pos++;
17149         tmp = AlnMgr2MapSeqAlignToBioseq (salp, pos, aln_row);
17150       }
17151       if (tmp < 0) {
17152         pos = -1;
17153       } else {
17154         pos = tmp;
17155       }
17156     } else {
17157       while (tmp < 0 && pos > -1) {
17158         pos--;
17159         tmp = AlnMgr2MapSeqAlignToBioseq (salp, pos, aln_row);
17160       }
17161       if (tmp < 0) {
17162         pos = -1;
17163       } else {
17164         pos = tmp;
17165       }
17166     }
17167   }
17168   return pos;
17169 }
17170 
17171 
s_IsInvalidRNAChainElement(ValNodePtr vnp)17172 static Boolean s_IsInvalidRNAChainElement(ValNodePtr vnp)
17173 {
17174     RNA_ITS_ItemPtr    rip;
17175     if (vnp == NULL || (rip = (RNA_ITS_ItemPtr)vnp->data.ptrvalue) == NULL
17176         || rip->rna_type == eRNA_ITS_INVALID) {
17177       return TRUE;
17178     } else {
17179       return FALSE;
17180     }
17181 }
17182 
17183 
MakeRNA_ITSChainForBioseq(BioseqPtr bsp,Pointer userdata)17184 static void MakeRNA_ITSChainForBioseq (BioseqPtr bsp, Pointer userdata)
17185 {
17186   RNAITSPtr          rp;
17187   ValNodePtr         vnp;
17188   RNA_ITS_ItemPtr    rip;
17189   Int4               last_untranslated_right = 0, this_left, this_right;
17190   RnaRefPtr          rrp;
17191   SeqFeatPtr         sfp;
17192   SeqEntryPtr        sep;
17193   Boolean            partial5, partial3 = FALSE;
17194   Int4               aln_row = -1;
17195 
17196   if (bsp == NULL || ISA_aa (bsp->mol) || userdata == NULL) return;
17197   rp = (RNAITSPtr) userdata;
17198 
17199   sep = SeqMgrGetSeqEntryForData (bsp);
17200   if (sep == NULL) return;
17201 
17202   if (rp->chosen_salp != NULL) {
17203     aln_row = GetAlnRowForBsp (bsp, rp->chosen_salp);
17204     if (aln_row < 1) {
17205       return;
17206     }
17207   }
17208 
17209   partial5 = GetStatus (rp->partial_5);
17210   last_untranslated_right = 0;
17211   for (vnp = rp->prev_list; vnp != NULL; vnp = vnp->next) {
17212     rip = vnp->data.ptrvalue;
17213 
17214     /* stop if we are at the end of the chain */
17215     if (s_IsInvalidRNAChainElement(vnp)) {
17216       break;
17217     }
17218 
17219     if (rip->left < 0) {
17220       this_left = last_untranslated_right + 1;
17221     } else {
17222       this_left = rip->left - 1;
17223     }
17224 
17225     this_left = ChooseEndpoint (bsp->length, this_left, TRUE, rp->chosen_salp, aln_row);
17226 
17227     if (rip->right < 0) {
17228       if (rp->chosen_salp == NULL) {
17229         this_right = bsp->length - 1;
17230       } else {
17231         this_right = AlnMgr2GetAlnLength (rp->chosen_salp, TRUE) - 1;
17232       }
17233     } else {
17234       this_right = rip->right - 1;
17235     }
17236     last_untranslated_right = this_right;
17237     this_right = ChooseEndpoint (bsp->length, this_right, FALSE, rp->chosen_salp, aln_row);
17238 
17239     /* if using alignment coordinates and left is not yet available, continue */
17240     if (this_right < 0 && this_left > -1 && rp->chosen_salp != NULL) {
17241       continue;
17242     }
17243 
17244     /* stop if the chain extends past the length of this Bioseq */
17245     if (this_left > bsp->length - 1 || this_left < 0 || this_right < 0 || this_right <= this_left) {
17246       break;
17247     }
17248 
17249     rrp = RnaRefNew ();
17250     if (rip->rna_type == eRNA_ITS_ITS1 || rip->rna_type == eRNA_ITS_ITS2) {
17251       rrp->type = RNA_TYPE_misc_RNA;
17252     } else {
17253       rrp->type = RNA_TYPE_rRNA;
17254     }
17255     sfp = SeqFeatNew ();
17256     sfp->data.choice = SEQFEAT_RNA;
17257     sfp->data.value.ptrvalue = rrp;
17258     SetRNAProductString (sfp, NULL, RNANameFromRNAType(rip->rna_type), ExistingTextOption_replace_old);
17259 
17260     /* if last endpoint not set, use end of sequence.
17261      * if last endpoint past end of sequence, use end of sequence.
17262      */
17263     sfp->location = SeqLocIntNew (this_left, this_right, Seq_strand_plus,
17264                                   SeqIdDup (SeqIdFindBest (bsp->id, 0)));
17265     if ((s_IsInvalidRNAChainElement(vnp->next) || this_right == bsp->length - 1) && GetStatus (rp->partial_3)) {
17266       partial3 = TRUE;
17267     }
17268     SetSeqLocPartial (sfp->location, partial5, partial3);
17269     sfp->partial = partial5 || partial3;
17270     CreateNewFeature (sep, NULL, SEQFEAT_RNA, sfp);
17271     ValNodeAddPointer (&(rp->feature_list), OBJ_SEQFEAT, sfp);
17272     partial5 = FALSE;
17273   }
17274 }
17275 
17276 /* This function will propagate the RNA features pointed to by feature_list
17277  * from aln_row in salp to the other rows in salp.
17278 */
PropagateRNAList(ValNodePtr feature_list,Int4 aln_row,SeqAlignPtr salp,Boolean split_at_gaps)17279 static void PropagateRNAList (ValNodePtr feature_list, Int4 aln_row, SeqAlignPtr salp, Boolean split_at_gaps)
17280 {
17281   ValNodePtr seq_for_prop = NULL, vnp;
17282   Int4       i;
17283   SeqIdPtr   sip;
17284   Boolean    warned_about_master = FALSE;
17285 
17286   if (feature_list == NULL || aln_row < 1 || salp == NULL) return;
17287 
17288   /* get list of sequences to propagate to */
17289   for (i = 1; i <= salp->dim; i++) {
17290     if (i != aln_row) {
17291       ValNodeAddPointer (&seq_for_prop, 0, AlnMgr2GetNthSeqIdPtr(salp, i));
17292     }
17293   }
17294 
17295   /* propagate each feature */
17296   for (vnp = feature_list; vnp != NULL; vnp = vnp->next) {
17297     PropagateOneFeat (vnp->data.ptrvalue, split_at_gaps, FALSE, FALSE, FALSE, FALSE, seq_for_prop, &warned_about_master);
17298   }
17299 
17300   /* free sequence IDs in seq_for_prop */
17301   for (vnp = seq_for_prop; vnp != NULL; vnp = vnp->next) {
17302     sip = (SeqIdPtr) vnp->data.ptrvalue;
17303     sip = SeqIdFree (sip);
17304   }
17305   seq_for_prop = ValNodeFree (seq_for_prop);
17306 
17307 }
17308 
17309 
MakeRNA_ITSChain(ButtoN b)17310 static void MakeRNA_ITSChain (ButtoN b)
17311 {
17312   RNAITSPtr          rp;
17313   SeqEntryPtr        sep;
17314   BioseqPtr          bsp;
17315   Boolean            apply_to_all = FALSE, propagate = FALSE;
17316   SeqAlignPtr        next_salp, propagate_salp = NULL;
17317   Int4               salp_index, aln_row = -1;
17318   Boolean            split_at_gaps = FALSE;
17319 
17320   rp = (RNAITSPtr) GetObjectExtra (b);
17321   if (rp == NULL) return;
17322   sep = GetTopSeqEntryForEntityID (rp->input_entityID);
17323   rp->prev_list = ValNodeFreeData (rp->prev_list);
17324   rp->prev_list = DialogToPointer (rp->rna_list);
17325 
17326   bsp = GetBioseqViewTarget (rp->bfp);
17327   if (GetStatus (rp->use_aln)) {
17328     apply_to_all = TRUE;
17329     if (bsp != NULL && Message (MSG_YN, "Apply to all Bioseqs?") == ANS_NO) {
17330       apply_to_all = FALSE;
17331     }
17332   } else if (bsp == NULL) {
17333     if (Message (MSG_OKC, "You are not viewing a single Bioseq.  Apply to all Bioseqs?") == ANS_CANCEL) {
17334       return;
17335     } else {
17336       apply_to_all = TRUE;
17337     }
17338   } else {
17339     propagate_salp = rp->salp_list;
17340     while (aln_row < 0 && propagate_salp != NULL) {
17341       aln_row = GetAlnRowForBsp (bsp, propagate_salp);
17342       if (aln_row < 0) {
17343         propagate_salp = propagate_salp->next;
17344       }
17345     }
17346     if (aln_row > 0  && propagate_salp != NULL && Message (MSG_YN, "Propagate to other sequences?") == ANS_YES) {
17347       propagate = TRUE;
17348     }
17349   }
17350 
17351   rp->chosen_salp = NULL;
17352   next_salp = NULL;
17353   if (GetStatus (rp->use_aln)) {
17354     rp->chosen_salp = rp->salp_list;
17355     if (rp->this_aln != NULL) {
17356       salp_index = GetValue (rp->this_aln);
17357       while (salp_index > 1 && rp->chosen_salp != NULL) {
17358         rp->chosen_salp = rp->chosen_salp->next;
17359         salp_index--;
17360       }
17361       if (salp_index > 1) {
17362         rp->chosen_salp = NULL;
17363       }
17364     }
17365 
17366     /* if choosing only one sequence, make sure it's in alignment */
17367     if (bsp != NULL && !apply_to_all && GetAlnRowForBsp (bsp, rp->chosen_salp) < 1) {
17368       Message (MSG_ERROR, "This sequence is not in the alignment!");
17369       return;
17370     }
17371 
17372     /* temporarily break alignment chain */
17373     if (rp->chosen_salp != NULL) {
17374       next_salp = rp->chosen_salp->next;
17375       rp->chosen_salp->next = NULL;
17376     }
17377   }
17378 
17379 
17380   WatchCursor ();
17381   Update ();
17382 
17383   /* rp->feature list will contain a list of all the features created */
17384   rp->feature_list = NULL;
17385   if (apply_to_all) {
17386     VisitBioseqsInSep (sep, rp, MakeRNA_ITSChainForBioseq);
17387   } else {
17388     MakeRNA_ITSChainForBioseq (bsp, rp);
17389     if (propagate) {
17390       if (GetValue (rp->gap_handling) == 2) {
17391         split_at_gaps = TRUE;
17392       }
17393       PropagateRNAList (rp->feature_list, aln_row, propagate_salp, split_at_gaps);
17394     }
17395   }
17396   rp->feature_list = ValNodeFree (rp->feature_list);
17397 
17398 
17399   /* restore alignment chain if it was broken */
17400   if (rp->chosen_salp != NULL) {
17401     rp->chosen_salp->next = next_salp;
17402   }
17403 
17404   ArrowCursor ();
17405   Update ();
17406   ObjMgrSetDirtyFlag (rp->input_entityID, TRUE);
17407   ObjMgrSendMsg (OM_MSG_UPDATE, rp->input_entityID, 0, 0);
17408   if (!GetStatus (rp->leave_dlg_up)) {
17409     Remove (rp->form);
17410   }
17411 }
17412 
CleanupRNA_ITS(GraphiC g,VoidPtr data)17413 static void CleanupRNA_ITS (GraphiC g, VoidPtr data)
17414 
17415 {
17416   RNAITSPtr          rp;
17417   SeqAlignPtr        salp;
17418 
17419   rp = (RNAITSPtr) data;
17420   if (rp != NULL) {
17421     ValNodeFree (rp->prev_list);
17422     /* free the alignment list we created for alignment coordinates */
17423     while (rp->salp_list != NULL) {
17424       salp = rp->salp_list->next;
17425       rp->salp_list->next = NULL;
17426       rp->salp_list = SeqAlignFree (rp->salp_list);
17427       rp->salp_list = salp;
17428     }
17429     ObjMgrFreeUserData (rp->input_entityID, rp->procid, rp->proctype, rp->userkey);
17430   }
17431   StdCleanupFormProc (g, data);
17432 }
17433 
RNAITSFormMsgFunc(OMMsgStructPtr ommsp)17434 static Int2 LIBCALLBACK RNAITSFormMsgFunc (OMMsgStructPtr ommsp)
17435 {
17436   WindoW         currentport,
17437                  temport;
17438   OMUserDataPtr  omudp;
17439   RNAITSPtr      rp = NULL;
17440 
17441   omudp = (OMUserDataPtr)(ommsp->omuserdata);
17442   if (omudp == NULL) return OM_MSG_RET_ERROR;
17443   rp = (RNAITSPtr) omudp->userdata.ptrvalue;
17444   if (rp == NULL) return OM_MSG_RET_ERROR;
17445 
17446   currentport = ParentWindow (rp->form);
17447   temport = SavePort (currentport);
17448   UseWindow (currentport);
17449   Select (rp->form);
17450   switch (ommsp->message)
17451   {
17452       case OM_MSG_UPDATE:
17453           break;
17454       case OM_MSG_DESELECT:
17455           break;
17456 
17457       case OM_MSG_SELECT:
17458           break;
17459       case OM_MSG_DEL:
17460           Remove (rp->form);
17461           break;
17462       case OM_MSG_HIDE:
17463           break;
17464       case OM_MSG_SHOW:
17465           break;
17466       case OM_MSG_FLUSH:
17467           Remove (rp->form);
17468           break;
17469       default:
17470           break;
17471   }
17472   RestorePort (temport);
17473   UseWindow (temport);
17474   return OM_MSG_RET_OK;
17475 }
17476 
UseAlnCallback(ButtoN b)17477 static void UseAlnCallback (ButtoN b)
17478 {
17479   RNAITSPtr      rp = NULL;
17480 
17481   rp = (RNAITSPtr) GetObjectExtra (b);
17482   if (rp == NULL) return;
17483   if (rp->use_aln != NULL && rp->this_aln != NULL) {
17484     if (GetStatus (rp->use_aln)) {
17485       Enable (rp->this_aln);
17486     } else {
17487       Disable (rp->this_aln);
17488     }
17489   }
17490 }
17491 
ApplyRNA_ITS(IteM i)17492 extern void ApplyRNA_ITS (IteM i)
17493 {
17494   GrouP              c;
17495   RNAITSPtr          rp;
17496   GrouP              h, g, aln_group = NULL;
17497   WindoW             w;
17498   BaseFormPtr        bfp;
17499   OMUserDataPtr      omudp;
17500   SeqEntryPtr        sep;
17501   SeqAlignPtr        salp;
17502   Char               str[31];
17503 
17504 #ifdef WIN_MAC
17505   bfp = currentFormDataPtr;
17506 #else
17507   bfp = GetObjectExtra (i);
17508 #endif
17509   if (bfp == NULL) return;
17510 
17511   /* Create a new window, and a struct */
17512   /* to pass around the data in.       */
17513 
17514   rp = (RNAITSPtr) MemNew (sizeof (RNAITSData));
17515   if (rp == NULL)
17516     return;
17517 
17518   w = FixedWindow (-50, -33, -10, -10, "Apply RNA-ITS",
17519 		   StdCloseWindowProc);
17520   SetObjectExtra (w, rp, CleanupRNA_ITS);
17521   rp->form = (ForM) w;
17522   rp->input_entityID = bfp->input_entityID;
17523   rp->bfp = bfp;
17524 
17525   /* register to receive update messages */
17526   rp->userkey = OMGetNextUserKey ();
17527   rp->procid = 0;
17528   rp->proctype = OMPROC_EDIT;
17529   omudp = ObjMgrAddUserData (rp->input_entityID, rp->procid, rp->proctype, rp->userkey);
17530   if (omudp != NULL) {
17531     omudp->userdata.ptrvalue = (Pointer) rp;
17532     omudp->messagefunc = RNAITSFormMsgFunc;
17533   }
17534 
17535 
17536   h = HiddenGroup (w, -1, 0, NULL);
17537   SetGroupSpacing (h, 10, 10);
17538 
17539   g = HiddenGroup (h, 2, 0, NULL);
17540   SetGroupSpacing (g, 10, 10);
17541   rp->partial_5 = CheckBox (g, "5' Partial", NULL);
17542   rp->partial_3 = CheckBox (g, "3' Partial", NULL);
17543   SetStatus (rp->partial_5, TRUE);
17544   SetStatus (rp->partial_3, TRUE);
17545 
17546   /* if there are alignments, allow the user to specify alignment coordinates */
17547   sep = GetTopSeqEntryForEntityID (rp->input_entityID);
17548   VisitAnnotsInSep (sep, &(rp->salp_list), GetAlignmentsInSeqEntryCallback);
17549   if (rp->salp_list == NULL) {
17550     rp->use_aln = NULL;
17551     rp->this_aln = NULL;
17552   } else {
17553     aln_group = HiddenGroup (h, 2, 0, NULL);
17554     rp->use_aln = CheckBox (aln_group, "Use alignment coordinates", UseAlnCallback);
17555     SetObjectExtra (rp->use_aln, rp, NULL);
17556     if (rp->salp_list->next != NULL) {
17557       rp->this_aln = PopupList (aln_group, TRUE, NULL);
17558       salp = rp->salp_list;
17559       while (salp != NULL)
17560       {
17561         CreateSeqAlignLabel (salp, str, sizeof (str) - 1);
17562         PopupItem (rp->this_aln, str);
17563         salp = salp->next;
17564       }
17565       SetValue (rp->this_aln, 1);
17566       Disable (rp->this_aln);
17567     } else {
17568       rp->this_aln = NULL;
17569     }
17570   }
17571 
17572 
17573   /* set up callbacks */
17574   rp->callbacks[0] = RNA_ITS_ChoiceCallback;
17575   rp->callbacks[1] = RNA_ITS_IntervalCallback;
17576   rp->callbacks[2] = RNA_ITS_IntervalCallback;
17577 
17578   /* set up inteval types */
17579   rp->interval_types[0] = TAGLIST_POPUP;
17580   rp->interval_types[1] = TAGLIST_TEXT;
17581   rp->interval_types[2] = TAGLIST_TEXT;
17582 
17583   /* set up interval widths */
17584   rp->interval_widths[0] = 0;
17585   rp->interval_widths[1] = 5;
17586   rp->interval_widths[2] = 5;
17587 
17588   /* set up alist for RNA type */
17589   rp->alists[0] = rna_its_popup_alist;
17590   rp->alists[1] = NULL;
17591   rp->alists[2] = NULL;
17592 
17593   rp->rna_list = CreateTagListDialogExEx (h, 4, 3, 2,
17594                                           rp->interval_types, rp->interval_widths, rp->alists,
17595                                           TRUE, FALSE, RNAITSListToTagList, TagListToRNAITSList,
17596                                           rp->callbacks, rp, FALSE);
17597 
17598   rp->prev_list = NULL;
17599 
17600   /* control for handling alignment coordinates over gaps */
17601   rp->gap_handling = HiddenGroup (h, 2, 0, NULL);
17602   RadioButton (rp->gap_handling, "Extend over gaps");
17603   RadioButton (rp->gap_handling, "Split at gaps");
17604   SetValue (rp->gap_handling, 1);
17605 
17606   /* Add Accept and Cancel buttons */
17607 
17608   c = HiddenGroup (h, 3, 0, NULL);
17609   rp->accept = DefaultButton (c, "Accept", MakeRNA_ITSChain);
17610   SetObjectExtra (rp->accept, rp, NULL);
17611   PushButton (c, "Cancel", StdCancelButtonProc);
17612   rp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
17613 
17614   /* Line things up nicely */
17615 
17616   AlignObjects (ALIGN_CENTER, (HANDLE) g,
17617                               (HANDLE) rp->rna_list,
17618                               (HANDLE) rp->gap_handling,
17619                               (HANDLE) c, NULL);
17620 
17621 
17622   /* Display the window now */
17623 
17624   RealizeWindow (w);
17625   Show (w);
17626   Select (w);
17627   Select (rp->accept);
17628   Update ();
17629 }
17630 
17631 
17632 /* CDS-mRNA Link Tool */
17633 typedef struct cdsmrnalinktool {
17634   FORM_MESSAGE_BLOCK
17635   GrouP edit_grp;
17636   GrouP report_grp;
17637   DoC left_doc;
17638   DoC right_doc;
17639   DoC report_doc;
17640   DoC report_title_doc;
17641 
17642   BaseFormPtr       bfp;
17643   SeqFeatPtr        selected_cds;
17644   ValNodePtr        cds_list;
17645   ValNodePtr        mrna_list;
17646   Int2       lineheight;
17647 
17648   Nlm_ParData cdsParFmt;
17649   Nlm_ParData mrnaParFmt;
17650   Nlm_ParData reportParFmt;
17651   Nlm_ColData cdsColFmt [2];
17652   Nlm_ColData mrnaColFmt [3];
17653   Nlm_ColData reportColFmt [4];
17654 } CDSmRNALinkToolData, PNTR CDSmRNALinkToolPtr;
17655 
CleanupCDSmRNALinkTool(GraphiC g,VoidPtr data)17656 static void CleanupCDSmRNALinkTool (GraphiC g, VoidPtr data)
17657 
17658 {
17659   CDSmRNALinkToolPtr          tp;
17660 
17661   tp = (CDSmRNALinkToolPtr) data;
17662   if (tp != NULL) {
17663     ObjMgrFreeUserData (tp->input_entityID, tp->procid, tp->proctype, tp->userkey);
17664   }
17665   StdCleanupFormProc (g, data);
17666 }
17667 
CDSmRNALinkToolFormMsgFunc(OMMsgStructPtr ommsp)17668 static Int2 LIBCALLBACK CDSmRNALinkToolFormMsgFunc (OMMsgStructPtr ommsp)
17669 {
17670   OMUserDataPtr  omudp;
17671   CDSmRNALinkToolPtr      tp = NULL;
17672 
17673   omudp = (OMUserDataPtr)(ommsp->omuserdata);
17674   if (omudp == NULL) return OM_MSG_RET_ERROR;
17675   tp = (CDSmRNALinkToolPtr) omudp->userdata.ptrvalue;
17676   if (tp == NULL) return OM_MSG_RET_ERROR;
17677 
17678   switch (ommsp->message)
17679   {
17680       case OM_MSG_UPDATE:
17681           break;
17682       case OM_MSG_DESELECT:
17683           break;
17684 
17685       case OM_MSG_SELECT:
17686           break;
17687       case OM_MSG_DEL:
17688           Remove (tp->form);
17689           break;
17690       case OM_MSG_HIDE:
17691           break;
17692       case OM_MSG_SHOW:
17693           break;
17694       case OM_MSG_FLUSH:
17695           Remove (tp->form);
17696           break;
17697       default:
17698           break;
17699   }
17700   return OM_MSG_RET_OK;
17701 }
17702 
GetLinkedFeatureList(SeqFeatPtr sfp)17703 static ValNodePtr GetLinkedFeatureList (SeqFeatPtr sfp)
17704 {
17705   Char            buf [32];
17706   ObjectIdPtr     oip;
17707   SeqFeatPtr      link_sfp;
17708   CharPtr         str = NULL;
17709   SeqFeatXrefPtr  xref;
17710   ValNodePtr      link_list = NULL;
17711 
17712   for (xref = sfp->xref; xref != NULL; xref = xref->next) {
17713     if (xref->id.choice != 3) continue;
17714     oip = (ObjectIdPtr) xref->id.value.ptrvalue;
17715     if (oip != NULL) {
17716       if (StringDoesHaveText (oip->str)) {
17717         str = oip->str;
17718       } else {
17719         sprintf (buf, "%ld", (long) oip->id);
17720         str = buf;
17721       }
17722       link_sfp = SeqMgrGetFeatureByFeatID (sfp->idx.entityID, NULL, str, NULL, NULL);
17723       if (link_sfp != NULL) {
17724         ValNodeAddPointer (&link_list, OBJ_SEQFEAT, link_sfp);
17725       }
17726     }
17727   }
17728 
17729   return link_list;
17730 }
17731 
SortVnpByLinkStatus(VoidPtr ptr1,VoidPtr ptr2)17732 static int LIBCALLBACK SortVnpByLinkStatus (VoidPtr ptr1, VoidPtr ptr2)
17733 
17734 {
17735   ValNodePtr  vnp1;
17736   ValNodePtr  vnp2;
17737   SeqFeatPtr  cds1, cds2;
17738   ValNodePtr  link1, link2;
17739   Int4        rval = 0;
17740   SeqMgrFeatContext fcontext1, fcontext2;
17741 
17742   if (ptr1 == NULL || ptr2 == NULL) return 0;
17743   vnp1 = *((ValNodePtr PNTR) ptr1);
17744   vnp2 = *((ValNodePtr PNTR) ptr2);
17745   if (vnp1 == NULL || vnp2 == NULL) return 0;
17746   if (vnp1->data.ptrvalue == NULL || vnp2->data.ptrvalue == NULL) return 0;
17747 
17748   cds1 = vnp1->data.ptrvalue;
17749   cds2 = vnp2->data.ptrvalue;
17750 
17751   link1 = GetLinkedFeatureList (cds1);
17752   link2 = GetLinkedFeatureList (cds2);
17753 
17754   if (link1 != NULL && link2 == NULL) {
17755     rval = 1;
17756   } else if (link1 == NULL && link2 != NULL) {
17757     rval = -1;
17758   } else {
17759     SeqMgrGetDesiredFeature (cds1->idx.entityID, NULL, cds1->idx.itemID, 0, cds1, &fcontext1);
17760     SeqMgrGetDesiredFeature (cds2->idx.entityID, NULL, cds2->idx.itemID, 0, cds2, &fcontext2);
17761     if (fcontext1.left > fcontext2.left) {
17762       rval = 1;
17763     } else if (fcontext1.left < fcontext2.left) {
17764       rval = -1;
17765     } else if (fcontext1.itemID > fcontext2.itemID) {
17766       rval = 1;
17767     } else if (fcontext2.itemID < fcontext2.itemID) {
17768       rval = -1;
17769     } else {
17770       rval = 0;
17771     }
17772   }
17773   link1 = ValNodeFree (link1);
17774   link2 = ValNodeFree (link2);
17775 
17776   return rval;
17777 }
17778 
SortVnpBymRNAPos(VoidPtr ptr1,VoidPtr ptr2)17779 static int LIBCALLBACK SortVnpBymRNAPos (VoidPtr ptr1, VoidPtr ptr2)
17780 
17781 {
17782   ValNodePtr  vnp1;
17783   ValNodePtr  vnp2;
17784   SeqFeatPtr  mrna1, mrna2;
17785   Int4        rval = 0;
17786 
17787   if (ptr1 == NULL || ptr2 == NULL) return 0;
17788   vnp1 = *((ValNodePtr PNTR) ptr1);
17789   vnp2 = *((ValNodePtr PNTR) ptr2);
17790   if (vnp1 == NULL || vnp2 == NULL) return 0;
17791   if (vnp1->data.ptrvalue == NULL || vnp2->data.ptrvalue == NULL) return 0;
17792 
17793   mrna1 = vnp1->data.ptrvalue;
17794   mrna2 = vnp2->data.ptrvalue;
17795 
17796   if (vnp1->choice > 0 && vnp2->choice == 0) {
17797     rval = -1;
17798   } else if (vnp1->choice == 0 && vnp2->choice > 0) {
17799     rval = 1;
17800   } else {
17801     rval = SortVnpByLinkStatus (ptr1, ptr2);
17802   }
17803 
17804   return rval;
17805 }
17806 
GetLinkLabel(SeqFeatPtr sfp)17807 static CharPtr GetLinkLabel (SeqFeatPtr sfp)
17808 {
17809   CharPtr location, label;
17810   SeqMgrFeatContext context;
17811 
17812   if (sfp == NULL) return NULL;
17813 
17814   sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL, sfp->idx.itemID, 0, sfp, &context);
17815   location = SeqLocPrintUseBestID (sfp->location);
17816 
17817   label = (CharPtr) MemNew (sizeof (Char) * (StringLen (context.label) + StringLen (location) + 3));
17818   sprintf (label, "%s\t%s\n", context.label, location);
17819   return label;
17820 }
17821 
PopulateLinkReportDoc(CDSmRNALinkToolPtr tp)17822 static void PopulateLinkReportDoc (CDSmRNALinkToolPtr tp)
17823 {
17824   CharPtr cds_desc, mrna_desc, whole_line, tmp_desc;
17825   ValNodePtr vnp, vnp_m, mrnas;
17826   CharPtr    cp;
17827   CharPtr    no_mrna = "\t\n";
17828   Int4       col_width;
17829   RecT       r;
17830 
17831   if (tp == NULL) return;
17832 
17833   Reset (tp->report_doc);
17834   Reset (tp->report_title_doc);
17835   ObjectRect (tp->report_doc, &r);
17836   InsetRect (&r, 4, 4);
17837 
17838   col_width = (r.right - r.left) / 4;
17839   tp->reportColFmt[0].pixWidth = col_width;
17840   tp->reportColFmt[1].pixWidth = col_width;
17841   tp->reportColFmt[2].pixWidth = col_width;
17842   tp->reportColFmt[3].pixWidth = col_width;
17843 
17844   AppendText (tp->report_title_doc, "CDS product\tCDS location\tLinked mRNA product\tLinked mRNA Location\n",
17845               &(tp->reportParFmt), tp->reportColFmt, programFont);
17846 
17847   tp->cds_list = ValNodeSort (tp->cds_list, SortVnpByLinkStatus);
17848 
17849   for (vnp = tp->cds_list; vnp != NULL; vnp = vnp->next) {
17850     cds_desc = GetLinkLabel(vnp->data.ptrvalue);
17851     /* replace carriage return with tab */
17852     cp = StringChr (cds_desc, '\n');
17853     if (cp != NULL) {
17854       *cp = '\t';
17855     }
17856     mrnas = GetLinkedFeatureList (vnp->data.ptrvalue);
17857     if (mrnas == NULL) {
17858       whole_line = (CharPtr) MemNew (sizeof (Char) * (StringLen (cds_desc) + StringLen (no_mrna) + 1));
17859       sprintf (whole_line, "%s%s", cds_desc, no_mrna);
17860       AppendText (tp->report_doc, whole_line, &(tp->reportParFmt), tp->reportColFmt, programFont);
17861       whole_line = MemFree (whole_line);
17862     } else {
17863       tmp_desc = cds_desc;
17864       for (vnp_m = mrnas; vnp_m != NULL; vnp_m = vnp_m->next) {
17865         mrna_desc = GetLinkLabel(vnp_m->data.ptrvalue);
17866         whole_line = (CharPtr) MemNew (sizeof (Char) * (StringLen (cds_desc) + StringLen (mrna_desc) + 1));
17867         sprintf (whole_line, "%s%s", tmp_desc, mrna_desc);
17868         AppendText (tp->report_doc, whole_line, &(tp->reportParFmt), tp->reportColFmt, programFont);
17869         whole_line = MemFree (whole_line);
17870         mrna_desc = MemFree (mrna_desc);
17871         tmp_desc = "\t\t";
17872       }
17873     }
17874     cds_desc = MemFree (cds_desc);
17875   }
17876   InvalRect (&r);
17877   ObjectRect (tp->report_title_doc, &r);
17878   InvalRect (&r);
17879 }
17880 
PopulateLinkLeftDoc(CDSmRNALinkToolPtr tp)17881 static void PopulateLinkLeftDoc (CDSmRNALinkToolPtr tp)
17882 {
17883   RecT       r;
17884   ValNodePtr vnp;
17885   CharPtr    desc;
17886   Int4       col_width;
17887   Int2       i = 1, item_num = 0;
17888   Int4       startsAt;
17889 
17890   if (tp == NULL) return;
17891 
17892   /* first, reorder the coding regions so that coding regions with links
17893    * appear last.
17894    */
17895   tp->cds_list = ValNodeSort (tp->cds_list, SortVnpByLinkStatus);
17896 
17897   ObjectRect (tp->left_doc, &r);
17898   InsetRect (&r, 4, 4);
17899 
17900   col_width = (r.right - r.left) / 2;
17901   tp->cdsColFmt[0].pixWidth = col_width;
17902   tp->cdsColFmt[1].pixWidth = col_width;
17903 
17904   Reset (tp->left_doc);
17905 
17906   for (vnp = tp->cds_list, i = 1; vnp != NULL; vnp = vnp->next, i++) {
17907 
17908     desc = GetLinkLabel(vnp->data.ptrvalue);
17909     AppendText (tp->left_doc, desc, &(tp->cdsParFmt), tp->cdsColFmt, programFont);
17910     desc = MemFree (desc);
17911     if (vnp->data.ptrvalue == tp->selected_cds) {
17912       item_num = i;
17913     }
17914   }
17915 
17916   GetItemParams4 (tp->left_doc, item_num, &startsAt, NULL, NULL, NULL, NULL);
17917   SetScrlParams4 (tp->left_doc, startsAt);
17918 
17919   InvalRect (&r);
17920 }
17921 
PopulateLinkRightDoc(CDSmRNALinkToolPtr tp)17922 static void PopulateLinkRightDoc (CDSmRNALinkToolPtr tp)
17923 {
17924   RecT       r;
17925   ValNodePtr vnp;
17926   CharPtr    desc, tmp_desc;
17927   Uint1      old_choice;
17928   Int4       col_width;
17929 
17930   if (tp == NULL) return;
17931 
17932   Reset (tp->right_doc);
17933   ObjectRect (tp->right_doc, &r);
17934   InsetRect (&r, 4, 4);
17935   col_width = (r.right - r.left - tp->lineheight) / 2;
17936   tp->mrnaColFmt[0].pixWidth = tp->lineheight;
17937   tp->mrnaColFmt[1].pixWidth = col_width;
17938   tp->mrnaColFmt[2].pixWidth = col_width;
17939 
17940   for (vnp = tp->mrna_list; vnp != NULL; vnp = vnp->next) {
17941     old_choice = vnp->choice;
17942     vnp->choice = OBJ_SEQFEAT;
17943     desc = GetLinkLabel(vnp->data.ptrvalue);
17944     tmp_desc = (CharPtr) MemNew (sizeof (Char) * (StringLen (desc) + 2));
17945     sprintf (tmp_desc, "\t%s", desc);
17946     AppendText (tp->right_doc, tmp_desc, &(tp->mrnaParFmt), tp->mrnaColFmt, programFont);
17947     desc = MemFree (desc);
17948     tmp_desc = MemFree (tmp_desc);
17949     vnp->choice = old_choice;
17950   }
17951   InvalRect (&r);
17952 }
17953 
17954 
PopulateLinkTool(CDSmRNALinkToolPtr tp)17955 static void PopulateLinkTool (CDSmRNALinkToolPtr tp)
17956 {
17957   if (tp == NULL) return;
17958 
17959   /* first, reorder the coding regions so that coding regions with links
17960    * appear last.
17961    */
17962   tp->cds_list = ValNodeSort (tp->cds_list, SortVnpByLinkStatus);
17963 
17964   ResetClip();
17965   if (tp->selected_cds == NULL) {
17966     PopulateLinkReportDoc (tp);
17967     Show (tp->report_grp);
17968     Hide (tp->edit_grp);
17969   } else {
17970     PopulateLinkLeftDoc (tp);
17971     PopulateLinkRightDoc (tp);
17972     Show (tp->edit_grp);
17973     Hide (tp->report_grp);
17974   }
17975   Update ();
17976 }
17977 
RefreshLinkBtn(ButtoN b)17978 static void RefreshLinkBtn (ButtoN b)
17979 {
17980   PopulateLinkTool ((CDSmRNALinkToolPtr)GetObjectExtra (b));
17981 }
17982 
HighlightSelectedCDS(DoC doc,Int2 item,Int2 row,Int2 col)17983 static Boolean HighlightSelectedCDS (DoC doc, Int2 item, Int2 row, Int2 col)
17984 {
17985   CDSmRNALinkToolPtr tp;
17986   ValNodePtr         vnp;
17987   Int4               cds_num;
17988 
17989   tp = (CDSmRNALinkToolPtr) GetObjectExtra (doc);
17990   if (tp == NULL) return FALSE;
17991 
17992   for (vnp = tp->cds_list, cds_num = 1; vnp != NULL && cds_num != item; vnp = vnp->next, cds_num++)
17993   {
17994   }
17995   if (vnp != NULL && cds_num == item && vnp->data.ptrvalue == tp->selected_cds)
17996   {
17997     return TRUE;
17998   }
17999   else
18000   {
18001     return FALSE;
18002   }
18003 }
18004 
CDSFromLinkDocItem(CDSmRNALinkToolPtr tp,Int2 item)18005 static SeqFeatPtr CDSFromLinkDocItem (CDSmRNALinkToolPtr tp, Int2 item)
18006 {
18007   ValNodePtr vnp, link_list;
18008   Int4       cds_num = 1;
18009   SeqFeatPtr cds = NULL;
18010 
18011   if (item == 0 || tp == NULL) return NULL;
18012 
18013   vnp = tp->cds_list;
18014   while (vnp != NULL && cds_num < item) {
18015     if (tp->selected_cds == NULL) {
18016       /* we're showing the report view */
18017       link_list = GetLinkedFeatureList (vnp->data.ptrvalue);
18018       if (link_list != NULL && link_list->next != NULL) {
18019         cds_num += ValNodeLen (link_list->next);
18020       }
18021       link_list = ValNodeFree (link_list);
18022     }
18023     if (cds_num < item) {
18024       vnp = vnp->next;
18025       cds_num++;
18026     }
18027   }
18028   if (vnp != NULL) {
18029     cds = vnp->data.ptrvalue;
18030   }
18031   return cds;
18032 }
18033 
18034 
GrayLinkedCDS(DoC doc,Int2 item,Int2 row,Int2 col)18035 static Boolean GrayLinkedCDS (DoC doc, Int2 item, Int2 row, Int2 col)
18036 {
18037   CDSmRNALinkToolPtr tp;
18038   SeqFeatPtr         cds;
18039   ValNodePtr         link_list;
18040   Boolean            rval = FALSE;
18041 
18042   tp = (CDSmRNALinkToolPtr) GetObjectExtra (doc);
18043   if (tp == NULL) return FALSE;
18044 
18045   cds = CDSFromLinkDocItem (tp, item);
18046   if (cds != NULL && cds != tp->selected_cds)
18047   {
18048     link_list = GetLinkedFeatureList (cds);
18049     if (link_list != NULL) {
18050       rval = TRUE;
18051     }
18052     link_list = ValNodeFree (link_list);
18053   }
18054 
18055   return rval;
18056 }
18057 
GrayLinkedmRNA(DoC doc,Int2 item,Int2 row,Int2 col)18058 static Boolean GrayLinkedmRNA (DoC doc, Int2 item, Int2 row, Int2 col)
18059 {
18060   CDSmRNALinkToolPtr tp;
18061   ValNodePtr         vnp, link_list;
18062   Int4               num;
18063   Boolean            rval = FALSE, is_checked = FALSE;
18064 
18065   tp = (CDSmRNALinkToolPtr) GetObjectExtra (doc);
18066   if (tp == NULL) return FALSE;
18067 
18068   for (vnp = tp->mrna_list, num = 1; vnp != NULL && num != item; vnp = vnp->next, num++)
18069   {
18070   }
18071   if (vnp != NULL && num == item)
18072   {
18073     if (vnp->choice > 0) {
18074       is_checked = TRUE;
18075     }
18076     link_list = GetLinkedFeatureList (vnp->data.ptrvalue);
18077     if (link_list != NULL) {
18078       if (is_checked) {
18079         if (tp->selected_cds != NULL) {
18080           vnp = link_list;
18081           while (vnp != NULL && !rval) {
18082             if (vnp->data.ptrvalue != tp->selected_cds) {
18083               rval = TRUE;
18084             }
18085             vnp = vnp->next;
18086           }
18087         }
18088       } else {
18089         rval = TRUE;
18090       }
18091     }
18092     link_list = ValNodeFree (link_list);
18093   }
18094 
18095   return rval;
18096 }
18097 
DrawmRNA(DoC d,RectPtr r,Int2 item,Int2 firstLine)18098 static void DrawmRNA (DoC d, RectPtr r, Int2 item, Int2 firstLine)
18099 
18100 {
18101   CDSmRNALinkToolPtr tp;
18102   RecT         rct;
18103   RecT         doc_rect;
18104   Int4         mrna_num;
18105   ValNodePtr   vnp;
18106 
18107   tp = (CDSmRNALinkToolPtr) GetObjectExtra (d);
18108 
18109   if (tp == NULL || tp->selected_cds == NULL || r == NULL
18110       || item < 1
18111       || firstLine != 0)
18112   {
18113     return;
18114   }
18115 
18116   for (vnp = tp->mrna_list, mrna_num = 1; vnp != NULL && mrna_num != item; vnp = vnp->next, mrna_num++) {};
18117   if (vnp == NULL || mrna_num != item)
18118   {
18119     /* don't draw box for empty mRNA field */
18120     return;
18121   }
18122   rct = *r;
18123   rct.left ++;
18124   rct.right = rct.left + tp->lineheight;
18125   rct.bottom = rct.top + (rct.right - rct.left);
18126 
18127   /* make sure we don't draw a box where we aren't drawing text */
18128   ObjectRect (tp->right_doc, &doc_rect);
18129   InsetRect (&doc_rect, 4, 4);
18130   if (rct.bottom > doc_rect.bottom)
18131   {
18132     return;
18133   }
18134 
18135   FrameRect (&rct);
18136 
18137   if (vnp->choice > 0) {
18138     MoveTo (rct.left, rct.top);
18139     LineTo (rct.right - 1, rct.bottom - 1);
18140     MoveTo (rct.left, rct.bottom - 1);
18141     LineTo (rct.right - 1, rct.top);
18142   }
18143 }
18144 
DrawCDSDivide(DoC d,RectPtr r,Int2 item,Int2 firstLine)18145 static void DrawCDSDivide (DoC d, RectPtr r, Int2 item, Int2 firstLine)
18146 
18147 {
18148   CDSmRNALinkToolPtr tp;
18149   SeqFeatPtr   this_cds, prev_cds;
18150   ValNodePtr   this_link, prev_link;
18151 
18152   tp = (CDSmRNALinkToolPtr) GetObjectExtra (d);
18153 
18154   if (tp == NULL || r == NULL
18155       || item < 2
18156       || firstLine != 0)
18157   {
18158     return;
18159   }
18160 
18161   this_cds = CDSFromLinkDocItem (tp, item);
18162   prev_cds = CDSFromLinkDocItem (tp, item - 1);
18163 
18164   this_link = GetLinkedFeatureList (this_cds);
18165   if (this_link == NULL) return;
18166   prev_link = GetLinkedFeatureList (prev_cds);
18167   if (prev_link == NULL) {
18168     /* draw line */
18169     MoveTo (r->left, r->top);
18170     LineTo (r->right, r->top);
18171   }
18172   this_link = ValNodeFree (this_link);
18173   prev_link = ValNodeFree (prev_link);
18174 
18175 }
18176 
ReleasemRNA(DoC d,PoinT pt)18177 static void ReleasemRNA (DoC d, PoinT pt)
18178 
18179 {
18180   Int2            col;
18181   CDSmRNALinkToolPtr tp;
18182   Int2            item;
18183   RecT            rct;
18184   Int2            row;
18185   Int4            mrna_num;
18186   ValNodePtr      vnp, vnp_l;
18187   SeqEntryPtr     sep;
18188   SeqFeatPtr      mrna;
18189   ValNodePtr      link_list;
18190   SeqFeatPtr      linked_to_other = NULL, cds_link_to_other = NULL;
18191   Boolean         linked_to_selected = FALSE;
18192   SeqMgrFeatContext fcontext;
18193 
18194   tp = (CDSmRNALinkToolPtr) GetObjectExtra (d);
18195   if (tp == NULL || tp->selected_cds == NULL) return;
18196 
18197   MapDocPoint (d, pt, &item, &row, &col, &rct);
18198   rct.left += 1;
18199   rct.right = rct.left + tp->lineheight;
18200   rct.bottom = rct.top + (rct.right - rct.left);
18201   if (row != 1 || col != 1 || !PtInRect (pt, &rct)) {
18202     /* didn't click on a box */
18203     return;
18204   }
18205 
18206   for (vnp = tp->mrna_list, mrna_num = 1;
18207        vnp != NULL && mrna_num != item;
18208        vnp = vnp->next, mrna_num++)
18209   {
18210   }
18211   if (vnp == NULL || mrna_num != item) {
18212     /* clicked beyond end of list */
18213     return;
18214   }
18215 
18216   /* check to see if this mRNA is already linked to this CDS -
18217    * always want to let the user uncheck and break the link
18218    */
18219   mrna = vnp->data.ptrvalue;
18220 
18221   link_list = GetLinkedFeatureList (tp->selected_cds);
18222   for (vnp_l = link_list;
18223        vnp_l != NULL && !linked_to_selected;
18224        vnp_l = vnp_l->next) {
18225     if (vnp_l->data.ptrvalue == mrna) {
18226       linked_to_selected = TRUE;
18227     } else {
18228       cds_link_to_other = vnp_l->data.ptrvalue;
18229     }
18230   }
18231   link_list = ValNodeFree (link_list);
18232 
18233   if (!linked_to_selected) {
18234     if (cds_link_to_other != NULL) {
18235       Message (MSG_ERROR, "This CDS is already linked to an mRNA - you must unlink the other mRNA before you can link to this mRNA.");
18236       return;
18237     } else {
18238       link_list = GetLinkedFeatureList (mrna);
18239       for (vnp_l = link_list;
18240            vnp_l != NULL && linked_to_other == NULL;
18241            vnp_l = vnp_l->next) {
18242         if (vnp_l->data.ptrvalue != tp->selected_cds) {
18243           linked_to_other = vnp_l->data.ptrvalue;
18244         }
18245       }
18246       link_list = ValNodeFree (link_list);
18247       if (linked_to_other != NULL) {
18248         linked_to_other = SeqMgrGetDesiredFeature (linked_to_other->idx.entityID,
18249                                                    NULL,
18250                                                    linked_to_other->idx.itemID,
18251                                                    0,
18252                                                    linked_to_other,
18253                                                    &fcontext);
18254         Message (MSG_ERROR, "This mRNA is linked to another CDS (%s).  You must unlink it before you can link it to this CDS.", fcontext.label);
18255         return;
18256       }
18257     }
18258   }
18259 
18260   sep = GetTopSeqEntryForEntityID (tp->selected_cds->idx.entityID);
18261   AssignFeatureIDs (sep);
18262   if (vnp->choice > 0) {
18263     vnp->choice = 0;
18264     /* remove this link */
18265     RemoveFeatureLink (tp->selected_cds, mrna);
18266     RemoveFeatureLink (mrna, tp->selected_cds);
18267   } else {
18268     vnp->choice = OBJ_SEQFEAT;
18269     /* add this link */
18270     LinkTwoFeatures (tp->selected_cds, mrna);
18271     LinkTwoFeatures (mrna, tp->selected_cds);
18272   }
18273   MapDocPoint (d, pt, &item, &row, &col, &rct);
18274   InsetRect (&rct, -1, -1);
18275   InvalRect (&rct);
18276   ObjMgrSetDirtyFlag (tp->selected_cds->idx.entityID, TRUE);
18277   ObjMgrSendMsg (OM_MSG_UPDATE, tp->selected_cds->idx.entityID, 0, 0);
18278   Update ();
18279 }
18280 
18281 
ReleaseCDS(DoC d,PoinT pt)18282 static void ReleaseCDS (DoC d, PoinT pt)
18283 
18284 {
18285   Int2            col;
18286   CDSmRNALinkToolPtr tp;
18287   Int2            item;
18288   RecT            rct;
18289   Int2            row;
18290   ValNodePtr      vnp, vnp_m, linked_mrnas;
18291   Boolean         found;
18292   Boolean         was_selected = FALSE;
18293   SeqFeatPtr      cds;
18294 
18295   tp = (CDSmRNALinkToolPtr) GetObjectExtra (d);
18296   if (tp == NULL) return;
18297 
18298   if (tp->selected_cds != NULL) {
18299     was_selected = TRUE;
18300   }
18301 
18302   MapDocPoint (d, pt, &item, &row, &col, &rct);
18303   cds = CDSFromLinkDocItem (tp, item);
18304 
18305   if (cds == NULL || cds == tp->selected_cds) {
18306     tp->selected_cds = NULL;
18307   } else {
18308     tp->selected_cds = cds;
18309   }
18310 
18311   if (tp->selected_cds != NULL) {
18312     /* need to label mRNAs - those already linked to CDS should be
18313      * listed at the end, those not linked should be unchecked.
18314      */
18315     linked_mrnas = GetLinkedFeatureList (tp->selected_cds);
18316 
18317     for (vnp = tp->mrna_list; vnp != NULL; vnp = vnp->next) {
18318       for (vnp_m = linked_mrnas, found = FALSE; vnp_m != NULL && !found; vnp_m = vnp_m->next) {
18319         if (vnp_m->data.ptrvalue == vnp->data.ptrvalue) {
18320           found = TRUE;
18321         }
18322       }
18323       if (found) {
18324         vnp->choice = OBJ_SEQFEAT;
18325       } else {
18326         vnp->choice = 0;
18327       }
18328     }
18329     linked_mrnas = ValNodeFree (linked_mrnas);
18330 
18331     tp->mrna_list = ValNodeSort (tp->mrna_list, SortVnpBymRNAPos);
18332 
18333   }
18334 
18335   if (tp->selected_cds == NULL || !was_selected) {
18336     PopulateLinkTool (tp);
18337   } else {
18338     ResetClip();
18339     ObjectRect (tp->left_doc, &rct);
18340     InvalRect (&rct);
18341 
18342     PopulateLinkRightDoc (tp);
18343     Show (tp->edit_grp);
18344     Hide (tp->report_grp);
18345     Update ();
18346   }
18347 }
18348 
CollectCDSCallback(SeqFeatPtr sfp,Pointer data)18349 static void CollectCDSCallback (SeqFeatPtr sfp, Pointer data)
18350 {
18351   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION || data == NULL) return;
18352   ValNodeAddPointer (data, OBJ_SEQFEAT, sfp);
18353 }
18354 
CollectmRNACallback(SeqFeatPtr sfp,Pointer data)18355 static void CollectmRNACallback (SeqFeatPtr sfp, Pointer data)
18356 {
18357   if (sfp == NULL || sfp->idx.subtype != FEATDEF_mRNA || data == NULL) return;
18358   ValNodeAddPointer (data, OBJ_SEQFEAT, sfp);
18359 }
18360 
FormatLinkColumn(Nlm_ColPtr col)18361 static void FormatLinkColumn (Nlm_ColPtr col)
18362 {
18363   if (col == NULL) return;
18364 
18365   col->pixWidth    = 0;
18366   col->pixInset    = 0;
18367   col->charWidth   = 10;
18368   col->charInset   = 0;
18369   col->font        = NULL;
18370   col->just        = 'l';
18371   col->wrap        = TRUE;
18372   col->bar         = FALSE;
18373   col->underline   = FALSE;
18374   col->left        = FALSE;
18375   col->last        = FALSE;
18376 }
18377 
CDSmRNALinkTool(IteM i)18378 extern void CDSmRNALinkTool (IteM i)
18379 {
18380   CDSmRNALinkToolPtr tp;
18381   GrouP              h, k, button_grp;
18382   ButtoN             b;
18383   WindoW             w;
18384   BaseFormPtr        bfp;
18385   OMUserDataPtr      omudp;
18386   SeqEntryPtr        sep;
18387   Int4               col_num;
18388 
18389 #ifdef WIN_MAC
18390   bfp = currentFormDataPtr;
18391 #else
18392   bfp = GetObjectExtra (i);
18393 #endif
18394   if (bfp == NULL) return;
18395 
18396   /* Create a new window, and a struct */
18397   /* to pass around the data in.       */
18398 
18399   tp = (CDSmRNALinkToolPtr) MemNew (sizeof (CDSmRNALinkToolData));
18400   if (tp == NULL)
18401     return;
18402 
18403   w = FixedWindow (-50, -33, -10, -10, "CDS mRNA Link Tool",
18404 		   StdCloseWindowProc);
18405   SetObjectExtra (w, tp, CleanupCDSmRNALinkTool);
18406   tp->form = (ForM) w;
18407   tp->input_entityID = bfp->input_entityID;
18408   tp->bfp = bfp;
18409 
18410   /* register to receive update messages */
18411   tp->userkey = OMGetNextUserKey ();
18412   tp->procid = 0;
18413   tp->proctype = OMPROC_EDIT;
18414   omudp = ObjMgrAddUserData (tp->input_entityID, tp->procid, tp->proctype, tp->userkey);
18415   if (omudp != NULL) {
18416     omudp->userdata.ptrvalue = (Pointer) tp;
18417     omudp->messagefunc = CDSmRNALinkToolFormMsgFunc;
18418   }
18419 
18420   tp->cdsParFmt.openSpace    = FALSE;
18421   tp->cdsParFmt.keepWithNext = FALSE;
18422   tp->cdsParFmt.keepTogether = FALSE;
18423   tp->cdsParFmt.newPage      = FALSE;
18424   tp->cdsParFmt.tabStops     = FALSE;
18425   tp->cdsParFmt.minLines     = 0;
18426   tp->cdsParFmt.minHeight    = 0;
18427 
18428   tp->mrnaParFmt.openSpace    = FALSE;
18429   tp->mrnaParFmt.keepWithNext = FALSE;
18430   tp->mrnaParFmt.keepTogether = FALSE;
18431   tp->mrnaParFmt.newPage      = FALSE;
18432   tp->mrnaParFmt.tabStops     = FALSE;
18433   tp->mrnaParFmt.minLines     = 0;
18434   tp->mrnaParFmt.minHeight    = 0;
18435 
18436   tp->reportParFmt.openSpace    = FALSE;
18437   tp->reportParFmt.keepWithNext = FALSE;
18438   tp->reportParFmt.keepTogether = FALSE;
18439   tp->reportParFmt.newPage      = FALSE;
18440   tp->reportParFmt.tabStops     = FALSE;
18441   tp->reportParFmt.minLines     = 0;
18442   tp->reportParFmt.minHeight    = 0;
18443 
18444   for (col_num = 0; col_num < 2; col_num++) {
18445     FormatLinkColumn (tp->cdsColFmt + col_num);
18446     FormatLinkColumn (tp->mrnaColFmt + col_num);
18447     FormatLinkColumn (tp->reportColFmt + col_num);
18448     FormatLinkColumn (tp->reportColFmt + col_num + 2);
18449   }
18450   FormatLinkColumn (tp->mrnaColFmt + 2);
18451   tp->cdsColFmt[1].last       = TRUE;
18452   tp->mrnaColFmt[2].last      = TRUE;
18453   tp->reportColFmt[3].last    = TRUE;
18454 
18455   SelectFont (programFont);
18456   tp->lineheight = LineHeight ();
18457 
18458   h = HiddenGroup (w, -1, 0, NULL);
18459   SetGroupSpacing (h, 10, 10);
18460 
18461   k = HiddenGroup (w, 0, 0, NULL);
18462   tp->edit_grp = HiddenGroup (k, 2, 0, NULL);
18463   StaticPrompt (tp->edit_grp, "CDS", 0, dialogTextHeight, programFont, 'c');
18464   StaticPrompt (tp->edit_grp, "mRNA", 0, dialogTextHeight, programFont, 'c');
18465   tp->left_doc = DocumentPanel (tp->edit_grp, stdCharWidth * 30 + 5, tp->lineheight * 40);
18466   SetObjectExtra (tp->left_doc, tp, NULL);
18467   SetDocProcs (tp->left_doc, NULL, NULL, ReleaseCDS, NULL);
18468   SetDocShade (tp->left_doc, NULL, GrayLinkedCDS, HighlightSelectedCDS, NULL);
18469 
18470   tp->right_doc = DocumentPanel (tp->edit_grp, stdCharWidth * 30 + 5 + tp->lineheight, tp->lineheight * 40);
18471   SetObjectExtra (tp->right_doc, tp, NULL);
18472   SetDocProcs (tp->right_doc, NULL, NULL, ReleasemRNA, NULL);
18473   SetDocShade (tp->right_doc, DrawmRNA, GrayLinkedmRNA, NULL, NULL);
18474 
18475   tp->report_grp = HiddenGroup (k, 0, 2, NULL);
18476   tp->report_title_doc = DocumentPanel (tp->report_grp, stdCharWidth * 60 + 10, tp->lineheight);
18477   tp->report_doc = DocumentPanel (tp->report_grp, stdCharWidth * 60 + 10, tp->lineheight * 40);
18478   SetObjectExtra (tp->report_doc, tp, NULL);
18479   SetDocProcs (tp->report_doc, NULL, NULL, ReleaseCDS, NULL);
18480   SetDocShade (tp->report_doc, DrawCDSDivide, GrayLinkedCDS, NULL, NULL);
18481 
18482   AlignObjects (ALIGN_CENTER, (HANDLE) tp->edit_grp, (HANDLE) tp->report_grp, NULL);
18483 
18484   button_grp = HiddenGroup (w, 2, 0, NULL);
18485   b = PushButton (button_grp, "Refresh", RefreshLinkBtn);
18486   SetObjectExtra (b, tp, NULL);
18487   PushButton (button_grp, "Dismiss", StdCancelButtonProc);
18488 
18489   AlignObjects (ALIGN_CENTER, (HANDLE) k, (HANDLE) button_grp, NULL);
18490 
18491   sep = GetTopSeqEntryForEntityID (tp->input_entityID);
18492   /* collect CDSs */
18493   VisitFeaturesInSep (sep, &(tp->cds_list), CollectCDSCallback);
18494   /* collect mRNAs */
18495   VisitFeaturesInSep (sep, &(tp->mrna_list), CollectmRNACallback);
18496 
18497   PopulateLinkTool (tp);
18498   /* Display the window now */
18499 
18500   RealizeWindow (w);
18501   Show (w);
18502   Select (w);
18503   Update ();
18504 }
18505 
18506 
18507 typedef struct setqual {
18508   SourceQualDescPtr qual;
18509   CharPtr           val;
18510 } SetQualData, PNTR SetQualPtr;
18511 
SetQualOnSourceDescWhenSourceFeatPresentCallback(BioseqPtr bsp,Pointer userdata)18512 static void SetQualOnSourceDescWhenSourceFeatPresentCallback (BioseqPtr bsp, Pointer userdata)
18513 {
18514   SetQualPtr        sqp;
18515   SeqMgrDescContext dcontext;
18516   SeqMgrFeatContext fcontext;
18517   SeqFeatPtr        sfp;
18518   SeqDescrPtr       sdp;
18519   BioSourcePtr      biop;
18520   OrgModPtr         mod;
18521   SubSourcePtr      ssp;
18522 
18523   if (bsp == NULL || userdata == NULL) return;
18524   sqp = (SetQualPtr) userdata;
18525   if (sqp->qual == NULL) return;
18526 
18527   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
18528   if (sdp == NULL) return;
18529   biop = (BioSourcePtr) sdp->data.ptrvalue;
18530   if (biop == NULL) return;
18531 
18532   sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_BIOSRC, 0, &fcontext);
18533   if (sfp == NULL) return;
18534 
18535   if (sqp->qual->isOrgMod)
18536   {
18537     if (biop->org == NULL)
18538     {
18539       biop->org = OrgRefNew();
18540     }
18541     if (biop->org->orgname == NULL)
18542     {
18543       biop->org->orgname = OrgNameNew();
18544     }
18545     mod = biop->org->orgname->mod;
18546     while (mod != NULL && mod->subtype != sqp->qual->subtype)
18547     {
18548       mod = mod->next;
18549     }
18550     if (mod == NULL)
18551     {
18552       mod = OrgModNew ();
18553       mod->subtype = sqp->qual->subtype;
18554       mod->next = biop->org->orgname->mod;
18555       biop->org->orgname->mod = mod;
18556     }
18557     if (IsNonTextModifier (sqp->qual->name))
18558     {
18559       if (mod->subname == NULL)
18560       {
18561         mod->subname = StringSave ("");
18562       }
18563     }
18564     else
18565     {
18566       mod->subname = MemFree (mod->subname);
18567       mod->subname = StringSave (sqp->val);
18568     }
18569   }
18570   else
18571   {
18572     ssp = biop->subtype;
18573     while (ssp != NULL && ssp->subtype != sqp->qual->subtype)
18574     {
18575       ssp = ssp->next;
18576     }
18577     if (ssp == NULL)
18578     {
18579       ssp = SubSourceNew();
18580       ssp->subtype = sqp->qual->subtype;
18581       ssp->next = biop->subtype;
18582       biop->subtype = ssp;
18583     }
18584     if (IsNonTextModifier (sqp->qual->name))
18585     {
18586       if (ssp->name == NULL)
18587       {
18588         ssp->name = StringSave ("");
18589       }
18590     }
18591     else
18592     {
18593       ssp->name = MemFree (ssp->name);
18594       ssp->name = StringSave (sqp->val);
18595     }
18596   }
18597 
18598 }
18599 
SetTransgenicOnSourceDescWhenSourceFeatPresent(IteM i)18600 extern void SetTransgenicOnSourceDescWhenSourceFeatPresent (IteM i)
18601 {
18602   BaseFormPtr         bfp;
18603   SeqEntryPtr         sep;
18604   SetQualData         sqd;
18605   SourceQualDescData  sqdd;
18606 
18607 #ifdef WIN_MAC
18608   bfp = currentFormDataPtr;
18609 #else
18610   bfp = GetObjectExtra (i);
18611 #endif
18612   if (bfp == NULL) return;
18613 
18614   sqdd.isOrgMod = FALSE;
18615   sqdd.name = "transgenic";
18616   sqdd.subtype = SUBSRC_transgenic;
18617 
18618   sqd.qual = &sqdd;
18619   sqd.val = NULL;
18620 
18621   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
18622 
18623   VisitBioseqsInSep (sep, &sqd, SetQualOnSourceDescWhenSourceFeatPresentCallback);
18624 
18625   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
18626   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
18627   Update ();
18628 }
18629 
18630 
18631 typedef struct cdstrnaoverlap {
18632   SeqFeatPtr cds;
18633   ValNodePtr trna_list;
18634   Int4       overlap_len;
18635   CharPtr    end_str;
18636 } CDStRNAOverlapData, PNTR CDStRNAOverlapPtr;
18637 
18638 
GetOverlapLen(SeqLocPtr slp1,SeqLocPtr slp2)18639 static Int4 GetOverlapLen (SeqLocPtr slp1, SeqLocPtr slp2)
18640 {
18641   Int4  start1, stop1, start2, stop2, tmp, a, b, len = 0;
18642 
18643   if (slp1 == NULL || slp2 == NULL) return 0;
18644 
18645   start1 = SeqLocStart (slp1);
18646   stop1 = SeqLocStop (slp1);
18647   if (start1 > stop1) {
18648     tmp = start1;
18649     start1 = stop1;
18650     stop1 = tmp;
18651   }
18652   start2 = SeqLocStart (slp2);
18653   stop2 = SeqLocStop (slp2);
18654   if (start2 > stop2) {
18655     tmp = start2;
18656     start2 = stop2;
18657     stop2 = tmp;
18658   }
18659 
18660   a = MAX(start1, start2);
18661   b = MIN (stop1, stop2);
18662   len = b - a + 1;
18663   return len;
18664 }
18665 
18666 
CDStRNAOverlapFree(CDStRNAOverlapPtr p)18667 static CDStRNAOverlapPtr CDStRNAOverlapFree (CDStRNAOverlapPtr p)
18668 {
18669   if (p != NULL) {
18670     p->trna_list = ValNodeFree (p->trna_list);
18671     p->end_str = MemFree (p->end_str);
18672     p = MemFree (p);
18673   }
18674   return p;
18675 }
18676 
18677 
FreeCDStRNAOverlapList(ValNodePtr vnp)18678 static ValNodePtr FreeCDStRNAOverlapList (ValNodePtr vnp)
18679 {
18680   ValNodePtr vnp_next;
18681 
18682   while (vnp != NULL) {
18683     vnp_next = vnp->next;
18684     vnp->next = NULL;
18685     vnp->data.ptrvalue = CDStRNAOverlapFree (vnp->data.ptrvalue);
18686     vnp = ValNodeFree (vnp);
18687     vnp = vnp_next;
18688   }
18689   return vnp;
18690 }
18691 
IsBadEndStr(CharPtr end_str)18692 static Boolean IsBadEndStr (CharPtr end_str)
18693 {
18694   if (end_str == NULL) return TRUE;
18695   if (end_str[0] != 'T') return TRUE;
18696   if (end_str[1] == 0) return FALSE;
18697   if (end_str[1] == 'A' && end_str[2] == 0) return FALSE;
18698   return TRUE;
18699 }
18700 
18701 
ClickableItemFromCDStRNAOverlapList(CDStRNAOverlapPtr p)18702 static ClickableItemPtr ClickableItemFromCDStRNAOverlapList (CDStRNAOverlapPtr p)
18703 {
18704   ClickableItemPtr cip;
18705   CharPtr          fmt1 = "CDS is overlapped by more than one tRNA, longest overlap is %d";
18706   CharPtr          fmt2 = "Overlap is too long: %d";
18707 
18708   if (p == NULL || p->cds == NULL || p->trna_list == NULL) return NULL;
18709 
18710   cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
18711   ValNodeAddPointer (&(cip->item_list), OBJ_SEQFEAT, p->cds);
18712 
18713   /* potential problems - too many tRNAs, too much overlap, wrong string */
18714   /* only report wrong string if only one tRNA and overlap correct length */
18715 
18716   if (p->overlap_len > 2) {
18717     if (p->trna_list->next != NULL) {
18718       cip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt1) + 15));
18719       sprintf (cip->description, fmt1, p->overlap_len);
18720     } else {
18721       cip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt2) + 15));
18722       sprintf (cip->description, fmt2, p->overlap_len);
18723     }
18724   } else if (p->trna_list->next != NULL) {
18725     cip->description = StringSave ("CDS is overlapped by more than one tRNA!");
18726   } else if (IsBadEndStr(p->end_str)) {
18727     cip->description = StringSave ("Base pairs in partial codon before trim are neither 'T' nor 'TA'");
18728   } else {
18729     cip->description = StringSave ("Expected overlap");
18730   }
18731 
18732   return cip;
18733 }
18734 
18735 
GetEndStrForOverlap(SeqLocPtr slp,Int4 overlap_len)18736 static CharPtr GetEndStrForOverlap (SeqLocPtr slp, Int4 overlap_len)
18737 {
18738   Uint1 strand;
18739   Int4  end, start, stop;
18740   SeqPortPtr spp;
18741   CharPtr    end_str;
18742 
18743   if (slp == NULL || overlap_len < 0 || overlap_len > 2) {
18744     return NULL;
18745   }
18746   strand = SeqLocStrand (slp);
18747   if (strand == Seq_strand_minus) {
18748     end = SeqLocStart (slp);
18749     start = end + overlap_len;
18750     stop = end + 2;
18751   } else {
18752     end = SeqLocStop (slp);
18753     start = end - 2;
18754     stop = end - overlap_len + 1;
18755   }
18756   spp = SeqPortNew (BioseqFindFromSeqLoc (slp), start, stop, strand, Seq_code_iupacna);
18757   end_str = (CharPtr) MemNew (sizeof (Char) + (3 - overlap_len + 1));
18758   SeqPortRead (spp, (Uint1Ptr)end_str, 3 - overlap_len);
18759   spp = SeqPortFree (spp);
18760   return end_str;
18761 }
18762 
CDStRNAOverlapListFromItemList(ValNodePtr item_list)18763 static ValNodePtr CDStRNAOverlapListFromItemList (ValNodePtr item_list)
18764 {
18765   ValNodePtr new_item_list = NULL, vnp, vnp_trna;
18766   ValNodePtr        good_list = NULL, bad_list = NULL;
18767   SeqFeatPtr        sfp, trna;
18768   CDStRNAOverlapPtr p = NULL;
18769   Int4              len;
18770 
18771   if (item_list == NULL) return NULL;
18772 
18773   /* collect overlap groups */
18774   vnp = item_list;
18775   while (vnp != NULL) {
18776     if (vnp->choice == OBJ_SEQFEAT && vnp->data.ptrvalue != NULL) {
18777       sfp = (SeqFeatPtr) vnp->data.ptrvalue;
18778       if (sfp->idx.subtype == FEATDEF_CDS) {
18779         p = (CDStRNAOverlapPtr) MemNew (sizeof (CDStRNAOverlapData));
18780         p->cds = sfp;
18781         ValNodeAddPointer (&new_item_list, 0, p);
18782       } else if (sfp->idx.subtype == FEATDEF_tRNA && p != NULL) {
18783         ValNodeAddPointer (&(p->trna_list), OBJ_SEQFEAT, sfp);
18784       }
18785     }
18786     vnp = vnp->next;
18787   }
18788 
18789   for (vnp = new_item_list; vnp != NULL; vnp = vnp->next) {
18790     p = (CDStRNAOverlapPtr) vnp->data.ptrvalue;
18791     if (p->cds == NULL || p->trna_list == NULL) continue;
18792     for (vnp_trna = p->trna_list; vnp_trna != NULL; vnp_trna = vnp_trna->next) {
18793       if (vnp_trna->choice != OBJ_SEQFEAT || vnp_trna->data.ptrvalue == NULL) continue;
18794       trna = vnp_trna->data.ptrvalue;
18795       len = GetOverlapLen (p->cds->location, trna->location);
18796       if (p->overlap_len < len) {
18797         p->overlap_len = len;
18798       }
18799     }
18800     if (p->overlap_len > 0) {
18801       p->end_str = GetEndStrForOverlap (p->cds->location, p->overlap_len);
18802     }
18803 
18804     if (p->overlap_len == 0 || p->overlap_len > 2)
18805     {
18806       ValNodeAddPointer (&bad_list, 0, p);
18807     }
18808     else if (IsBadEndStr(p->end_str))
18809     {
18810       ValNodeAddPointer (&bad_list, 0, p);
18811     }
18812     else
18813     {
18814       ValNodeAddPointer (&good_list, 0, p);
18815     }
18816     vnp->data.ptrvalue = NULL;
18817   }
18818   new_item_list = ValNodeFree (new_item_list);
18819   new_item_list = bad_list;
18820   ValNodeLink (&new_item_list, good_list);
18821   return new_item_list;
18822 }
18823 
18824 
ClickableListFromCDStRNAOverlapList(ValNodePtr overlap_list)18825 static ValNodePtr ClickableListFromCDStRNAOverlapList (ValNodePtr overlap_list)
18826 {
18827   ClickableItemPtr cip;
18828   ValNodePtr       vnp, clickable_list = NULL;
18829 
18830   /* create clickable list of coding regions to trim */
18831   for (vnp = overlap_list; vnp != NULL; vnp = vnp->next)
18832   {
18833     cip = ClickableItemFromCDStRNAOverlapList (vnp->data.ptrvalue);
18834     if (cip != NULL) {
18835       ValNodeAddPointer (&clickable_list, 0, cip);
18836     }
18837   }
18838   return clickable_list;
18839 }
18840 
18841 
FixCDStRNAOverlaps(ValNodePtr overlap_list)18842 static void FixCDStRNAOverlaps (ValNodePtr overlap_list)
18843 {
18844   CDStRNAOverlapPtr p;
18845   ValNodePtr        vnp;
18846   SeqFeatPtr        gene;
18847 
18848   for (vnp = overlap_list; vnp != NULL; vnp = vnp->next)
18849   {
18850     p = (CDStRNAOverlapPtr) vnp->data.ptrvalue;
18851     if (p == NULL || p->cds == NULL || p->overlap_len < 1)
18852     {
18853       continue;
18854     }
18855     p->cds->location = TruncateLocation (p->cds->location, SeqLocLen (p->cds->location) - p->overlap_len);
18856     gene = GetGeneForFeature (p->cds);
18857     if (gene != NULL)
18858     {
18859       gene->location = TruncateLocation (gene->location, SeqLocLen (gene->location) - p->overlap_len);
18860     }
18861 
18862     AddTranslExcept (p->cds, "TAA stop codon is completed by the addition of 3' A residues to the mRNA", FALSE, FALSE, FALSE);
18863   }
18864 }
18865 
18866 
GetEntityIDFromItem(ValNodePtr vnp)18867 static Uint2 GetEntityIDFromItem (ValNodePtr vnp)
18868 {
18869   SeqFeatPtr sfp;
18870   SeqDescrPtr sdp;
18871   BioseqPtr   bsp;
18872   BioseqSetPtr bssp;
18873   Uint2        entityID = 0;
18874 
18875   if (vnp == NULL || vnp->data.ptrvalue == NULL) return 0;
18876   switch (vnp->choice) {
18877     case OBJ_SEQFEAT:
18878       sfp = vnp->data.ptrvalue;
18879       entityID = sfp->idx.entityID;
18880       break;
18881     case OBJ_SEQDESC:
18882       sdp = vnp->data.ptrvalue;
18883       entityID = ((ObjValNodePtr) sdp)->idx.entityID;
18884       break;
18885     case OBJ_BIOSEQ:
18886       bsp = vnp->data.ptrvalue;
18887       entityID = bsp->idx.entityID;
18888       break;
18889     case OBJ_BIOSEQSET:
18890       bssp = vnp->data.ptrvalue;
18891       entityID = bssp->idx.entityID;
18892       break;
18893   }
18894   return entityID;
18895 }
18896 
18897 
GetEntityIDFromClickableItem(ClickableItemPtr cip)18898 static Uint2 GetEntityIDFromClickableItem (ClickableItemPtr cip)
18899 {
18900   ValNodePtr vnp;
18901   Uint2      entityID = 0;
18902 
18903   if (cip == NULL || cip->item_list == NULL) return 0;
18904 
18905   for (vnp = cip->item_list; vnp != NULL && entityID == 0; vnp = vnp->next)
18906   {
18907     entityID = GetEntityIDFromItem (vnp);
18908   }
18909   return entityID;
18910 }
18911 
18912 
SendUpdatesForClickableList(ValNodePtr clickable_list)18913 static void SendUpdatesForClickableList (ValNodePtr clickable_list)
18914 {
18915   Uint2Ptr   entityIDtable;
18916   Uint2      this_entityID;
18917   ValNodePtr vnp;
18918   Int4       num, i;
18919 
18920   num = ValNodeLen (clickable_list);
18921   if (num == 0) return;
18922 
18923   entityIDtable = (Uint2Ptr) MemNew (sizeof (Uint2) * num);
18924   MemSet (entityIDtable, 0, sizeof (Uint2) * num);
18925   for (vnp = clickable_list; vnp != NULL; vnp = vnp->next) {
18926     this_entityID = GetEntityIDFromClickableItem (vnp->data.ptrvalue);
18927     for (i = 0; i < num && entityIDtable[i] != 0 && entityIDtable[i] != this_entityID; i++) {}
18928     if (i < num && entityIDtable[i] == 0) {
18929       entityIDtable[i] = this_entityID;
18930     }
18931   }
18932   for (i = 0; i < num && entityIDtable[i] != 0; i++) {
18933     ObjMgrSetDirtyFlag (entityIDtable[i], TRUE);
18934     ObjMgrSendMsg (OM_MSG_UPDATE, entityIDtable[i], 0, 0);
18935   }
18936   Update();
18937   entityIDtable = MemFree (entityIDtable);
18938 }
18939 
18940 
DivideClickableItemListByEntityID(ValNodePtr clickable_list)18941 static ValNodePtr DivideClickableItemListByEntityID (ValNodePtr clickable_list)
18942 {
18943   ValNodePtr vnp, vnp2, list_list = NULL, this_list;
18944   Uint2            entityID;
18945 
18946   for (vnp = clickable_list; vnp != NULL; vnp = vnp->next)
18947   {
18948     entityID = GetEntityIDFromClickableItem (vnp->data.ptrvalue);
18949     for (vnp2 = list_list; vnp2 != NULL && vnp2->choice != entityID; vnp2 = vnp2->next)
18950     {};
18951     if (vnp2 == NULL)
18952     {
18953       vnp2 = ValNodeAddPointer (&list_list, (Uint1) entityID, NULL);
18954     }
18955     this_list = vnp2->data.ptrvalue;
18956     ValNodeAddPointer (&this_list, vnp->choice, vnp->data.ptrvalue);
18957     vnp->data.ptrvalue = NULL;
18958     vnp2->data.ptrvalue = this_list;
18959   }
18960   return list_list;
18961 }
18962 
18963 
18964 typedef struct cdstrnatool {
18965   CLICKABLE_LIST_FORM_BLOCK
18966   ValNodePtr overlap_list;
18967 } CDStRNAToolData, PNTR CDStRNAToolPtr;
18968 
CleanupCDStRNAToolForm(GraphiC g,VoidPtr data)18969 static void CleanupCDStRNAToolForm (GraphiC g, VoidPtr data)
18970 
18971 {
18972   CDStRNAToolPtr dlg;
18973 
18974   dlg = (CDStRNAToolPtr) data;
18975   if (dlg != NULL) {
18976     dlg->clickable_list_data = FreeClickableList (dlg->clickable_list_data);
18977     dlg->overlap_list = FreeCDStRNAOverlapList (dlg->overlap_list);
18978     ObjMgrFreeUserData (dlg->input_entityID, dlg->procid, dlg->proctype, dlg->userkey);
18979   }
18980   StdCleanupFormProc (g, data);
18981 }
18982 
GetSelectedClickableItems(ValNodePtr list)18983 static ValNodePtr GetSelectedClickableItems (ValNodePtr list)
18984 {
18985   ValNodePtr       vnp, selected = NULL;
18986   ClickableItemPtr cip;
18987 
18988   for (vnp = list; vnp != NULL; vnp = vnp->next) {
18989     cip = (ClickableItemPtr) vnp->data.ptrvalue;
18990     if (cip == NULL) continue;
18991     if (cip->chosen) {
18992       ValNodeAddPointer (&selected, 0, cip);
18993     } else {
18994       ValNodeLink (&selected, GetSelectedClickableItems (cip->subcategories));
18995     }
18996   }
18997   return selected;
18998 }
18999 
19000 
TrimSelectedCDS(ButtoN b)19001 static void TrimSelectedCDS (ButtoN b)
19002 {
19003   CDStRNAToolPtr    dlg;
19004   ValNodePtr        tmp_list = NULL, overlap_list = NULL, vnp_o, vnp_c;
19005   ValNodePtr        prev_o = NULL, next_o;
19006   ClickableItemPtr  cip;
19007   CDStRNAOverlapPtr p;
19008   SeqFeatPtr        cds;
19009 
19010   dlg = (CDStRNAToolPtr) GetObjectExtra (b);
19011   if (dlg == NULL) return;
19012 
19013   tmp_list = GetSelectedClickableItems (dlg->clickable_list_data);
19014 
19015   if (tmp_list == NULL) {
19016     if (ANS_CANCEL == Message (MSG_OKC, "No features selected!  Trim all?")) {
19017       return;
19018     } else {
19019       tmp_list = dlg->clickable_list_data;
19020     }
19021   }
19022 
19023   vnp_c = tmp_list;
19024   vnp_o = dlg->overlap_list;
19025   while (vnp_c != NULL && vnp_o != NULL) {
19026     cip = (ClickableItemPtr) vnp_c->data.ptrvalue;
19027     if (cip == NULL || cip->item_list == NULL || cip->item_list->choice != OBJ_SEQFEAT) {
19028       vnp_c = vnp_c->next;
19029     } else {
19030       cds = cip->item_list->data.ptrvalue;
19031       p = (CDStRNAOverlapPtr) vnp_o->data.ptrvalue;
19032       if (p == NULL || p->cds != cds) {
19033         prev_o = vnp_o;
19034         vnp_o = vnp_o->next;
19035       } else {
19036         ValNodeAddPointer (&overlap_list, 0, p);
19037         /* better not be repeats in overlap list */
19038         next_o = vnp_o->next;
19039         if (prev_o == NULL) {
19040           dlg->overlap_list = next_o;
19041         } else {
19042           prev_o->next = next_o;
19043         }
19044         vnp_o->next = NULL;
19045         vnp_o = ValNodeFree (vnp_o);
19046         vnp_o = next_o;
19047         /* move on to next item in clickable list */
19048         vnp_c = vnp_c->next;
19049       }
19050     }
19051   }
19052 
19053   FixCDStRNAOverlaps (overlap_list);
19054   overlap_list = FreeCDStRNAOverlapList (overlap_list);
19055   SendUpdatesForClickableList (tmp_list);
19056 
19057   if (tmp_list != dlg->clickable_list_data) {
19058     tmp_list = ValNodeFree (tmp_list);
19059   }
19060 
19061   /* close the window if we're done */
19062   if (dlg->overlap_list == NULL) {
19063     Remove (dlg->form);
19064   } else {
19065     /* update list of overlaps (remove the trimmed ones) */
19066     PointerToDialog (dlg->clickable_list_dlg, NULL);
19067     dlg->clickable_list_data = FreeClickableList (dlg->clickable_list_data);
19068     dlg->clickable_list_data = ClickableListFromCDStRNAOverlapList (dlg->overlap_list);
19069     PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list_data);
19070   }
19071 }
19072 
19073 
SelectAllCDS(ButtoN b)19074 static void SelectAllCDS (ButtoN b)
19075 {
19076   CDStRNAToolPtr    dlg;
19077 
19078   dlg = (CDStRNAToolPtr) GetObjectExtra (b);
19079   if (dlg == NULL) return;
19080 
19081   ChooseCategories (dlg->clickable_list_data, TRUE);
19082   PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list_data);
19083 
19084 }
19085 
19086 
EditCDStRNAOverlap(ValNodePtr item_list)19087 static void EditCDStRNAOverlap (ValNodePtr item_list)
19088 {
19089   ValNodePtr overlap_list;
19090   CDStRNAToolPtr dlg;
19091   WindoW      w;
19092   GrouP       h, c;
19093   ButtoN      b;
19094   OMUserDataPtr            omudp;
19095 
19096   overlap_list = CDStRNAOverlapListFromItemList (item_list);
19097   if (overlap_list == NULL) {
19098     Message (MSG_ERROR, "No overlaps to correct!");
19099     return;
19100   }
19101 
19102   /* create window to display and correct overlaps */
19103   dlg = (CDStRNAToolPtr) MemNew (sizeof (CDStRNAToolData));
19104   dlg->clickable_list_data = ClickableListFromCDStRNAOverlapList (overlap_list);
19105   dlg->overlap_list = overlap_list;
19106 
19107   w = FixedWindow (-50, -33, -10, -10, "CDS tRNA Overlaps", StdCloseWindowProc);
19108   SetObjectExtra (w, dlg, CleanupCDStRNAToolForm);
19109   dlg->form = (ForM) w;
19110 
19111   /* register to receive update messages */
19112   dlg->userkey = OMGetNextUserKey ();
19113   dlg->procid = 0;
19114   dlg->proctype = OMPROC_EDIT;
19115   omudp = ObjMgrAddUserData (0, dlg->procid, dlg->proctype, dlg->userkey);
19116   if (omudp != NULL) {
19117     omudp->userdata.ptrvalue = (Pointer) dlg;
19118     omudp->messagefunc = ClickableListFormMsgFunc;
19119   }
19120 
19121 
19122 #ifndef WIN_MAC
19123   CreateStdValidatorFormMenus (w);
19124 #endif
19125 
19126   h = HiddenGroup (w, -1, 0, NULL);
19127   SetGroupSpacing (h, 10, 10);
19128 
19129   dlg->clickable_list_dlg = CreateClickableListDialog (h, "CDS-tRNA Overlaps", "Features",
19130                                                         ScrollToDiscrepancyItem, EditDiscrepancyItem, NULL,
19131                                                         GetDiscrepancyItemText);
19132   PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list_data);
19133 
19134   c = HiddenGroup (h, 4, 0, NULL);
19135   SetGroupSpacing (c, 10, 10);
19136 
19137   b = PushButton (c, "Trim Selected", TrimSelectedCDS);
19138   SetObjectExtra (b, dlg, NULL);
19139   b = PushButton (c, "Select All", SelectAllCDS);
19140   SetObjectExtra (b, dlg, NULL);
19141   b = PushButton (c, "Dismiss", StdCancelButtonProc);
19142 
19143   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->clickable_list_dlg, (HANDLE) c, NULL);
19144   RealizeWindow (w);
19145   Show (w);
19146   Update ();
19147 }
19148 
19149 
19150 extern GetSamplePtr
GetSampleForItemList(ValNodePtr item_list,ValNodePtr requested_field,GetFeatureFieldString fieldstring_func,GetDescriptorFieldString descrstring_func)19151 GetSampleForItemList
19152 (ValNodePtr               item_list,
19153  ValNodePtr               requested_field,
19154  GetFeatureFieldString    fieldstring_func,
19155  GetDescriptorFieldString descrstring_func)
19156 {
19157   ValNodePtr   vnp;
19158   GetSamplePtr gsp;
19159   SeqFeatPtr   sfp;
19160   SeqDescrPtr  sdp;
19161   CharPtr      str = NULL;
19162 
19163   if (item_list == NULL || requested_field == NULL) return NULL;
19164 
19165   gsp = GetSampleNew();
19166 
19167   for (vnp = item_list; vnp != NULL; vnp = vnp->next)
19168   {
19169     if (vnp->choice == OBJ_SEQFEAT && fieldstring_func != NULL)
19170     {
19171       sfp = (SeqFeatPtr) vnp->data.ptrvalue;
19172       str = fieldstring_func (sfp, requested_field, NULL);
19173     }
19174     else if (vnp->choice == OBJ_SEQDESC && descrstring_func != NULL)
19175     {
19176       sdp = (SeqDescrPtr) vnp->data.ptrvalue;
19177       str = descrstring_func (sdp, requested_field, NULL);
19178     }
19179     if (!StringHasNoText (str))
19180     {
19181       gsp->num_found ++;
19182       if (gsp->sample_text == NULL)
19183       {
19184         gsp->sample_text = str;
19185       }
19186       else
19187       {
19188         if (StringCmp (str, gsp->sample_text) != 0)
19189         {
19190           gsp->all_same = FALSE;
19191         }
19192       }
19193     }
19194     str = MemFree (str);
19195   }
19196 
19197   if (gsp->num_found == 0)
19198   {
19199     gsp = GetSampleFree (gsp);
19200   }
19201   return gsp;
19202 }
19203 
19204 
19205 typedef struct applytagtocdsinsrcfeat {
19206   FORM_MESSAGE_BLOCK
19207   TexT       note_text;
19208   ValNodePtr cds_list;
19209 } ApplyTagToCDSInSrcFeatData, PNTR ApplyTagToCDSInSrcFeatPtr;
19210 
19211 
CleanupApplyTagToCDSInSrcFeatForm(GraphiC g,VoidPtr data)19212 static void CleanupApplyTagToCDSInSrcFeatForm (GraphiC g, VoidPtr data)
19213 
19214 {
19215   ApplyTagToCDSInSrcFeatPtr dlg;
19216 
19217   dlg = (ApplyTagToCDSInSrcFeatPtr) data;
19218   if (dlg != NULL) {
19219     dlg->cds_list = ValNodeFree (dlg->cds_list);
19220   }
19221   StdCleanupFormProc (g, data);
19222 }
19223 
19224 
DoApplyTagToCodingRegionsInSourceFeatures(ButtoN b)19225 static void DoApplyTagToCodingRegionsInSourceFeatures (ButtoN b)
19226 {
19227   ApplyTagToCDSInSrcFeatPtr dlg;
19228   ValNodePtr                vnp;
19229   GetSamplePtr              gsp;
19230   ValNode                   vn;
19231   SeqFeatPtr                sfp;
19232   ApplyValueData            avd;
19233 
19234   dlg = (ApplyTagToCDSInSrcFeatPtr) GetObjectExtra (b);
19235   if (dlg == NULL) return;
19236 
19237   if (TextHasNoText (dlg->note_text)) {
19238     Message (MSG_ERROR, "No text supplied for note!");
19239     return;
19240   }
19241   vn.choice = 0;
19242   vn.next = NULL;
19243   vn.data.intvalue = 2;
19244   gsp = GetSampleForItemList (dlg->cds_list, &vn, GetCDSFieldString, NULL);
19245   avd.etp = GetExistingTextHandlerInfo (gsp == NULL ? 0 : gsp->num_found, FALSE);
19246   gsp = GetSampleFree (gsp);
19247   if (avd.etp != NULL && avd.etp->existing_text_choice == eExistingTextChoiceCancel)
19248   {
19249     avd.etp = MemFree (avd.etp);
19250     return;
19251   }
19252   avd.new_text = SaveStringFromText (dlg->note_text);
19253   avd.field_list = NULL;
19254   avd.text_to_replace = NULL;
19255   avd.where_to_replace = EditApplyFindLocation_anywhere;
19256 
19257   WatchCursor();
19258   Update();
19259   for (vnp = dlg->cds_list; vnp != NULL; vnp = vnp->next)
19260   {
19261     sfp = (SeqFeatPtr) vnp->data.ptrvalue;
19262     if (sfp != NULL)
19263     {
19264       sfp->comment = HandleApplyValue (sfp->comment, &avd);
19265     }
19266   }
19267   avd.etp = MemFree (avd.etp);
19268   ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
19269   ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
19270   ArrowCursor();
19271   Remove (dlg->form);
19272   Update ();
19273 }
19274 
19275 
ApplyTagToCodingRegionsInEntityID(Uint2 entityID)19276 static void ApplyTagToCodingRegionsInEntityID (Uint2 entityID)
19277 {
19278   ApplyTagToCDSInSrcFeatPtr dlg;
19279   ValNodePtr   cds_list;
19280   WindoW       w;
19281   GrouP        h, g, c;
19282   ButtoN       b;
19283   SeqEntryPtr  sep;
19284 
19285   sep = GetTopSeqEntryForEntityID (entityID);
19286 
19287   cds_list = ListCodingRegionsContainedInSourceFeatures (sep);
19288 
19289   if (cds_list == NULL) {
19290     Message (MSG_ERROR, "No coding regions found in source features!");
19291     return;
19292   }
19293 
19294   /* create window to display and correct overlaps */
19295   dlg = (ApplyTagToCDSInSrcFeatPtr) MemNew (sizeof (ApplyTagToCDSInSrcFeatData));
19296   dlg->input_entityID = entityID;
19297   dlg->cds_list = cds_list;
19298 
19299   w = FixedWindow (-50, -33, -10, -10, "Apply Note to Coding Regions in Source Features", StdCloseWindowProc);
19300   SetObjectExtra (w, dlg, CleanupApplyTagToCDSInSrcFeatForm);
19301   dlg->form = (ForM) w;
19302 
19303   h = HiddenGroup (w, -1, 0, NULL);
19304   SetGroupSpacing (h, 10, 10);
19305 
19306   g = HiddenGroup (h, 2, 0, NULL);
19307   StaticPrompt (g, "Note Text:", 0, dialogTextHeight, programFont, 'r');
19308   dlg->note_text = DialogText (g, "prophage-encoded protein", 0, NULL);
19309   c = HiddenGroup (h, 4, 0, NULL);
19310   SetGroupSpacing (c, 10, 10);
19311 
19312   b = PushButton (c, "Accept", DoApplyTagToCodingRegionsInSourceFeatures);
19313   SetObjectExtra (b, dlg, NULL);
19314   b = PushButton (c, "Dismiss", StdCancelButtonProc);
19315 
19316   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
19317   RealizeWindow (w);
19318   Show (w);
19319   Update ();
19320 }
19321 
19322 
19323 typedef struct authorizedaccessuserdialog {
19324   DIALOG_MESSAGE_BLOCK
19325   TexT study_txt;
19326 } AuthorizedAccessUserDialog, PNTR AuthorizedAccessUserDialogPtr;
19327 
19328 typedef struct authorizedaccessuserform {
19329   FEATURE_FORM_BLOCK
19330   SeqEntryPtr   sep;
19331   SeqDescrPtr   orig_sdp;
19332 } AuthorizedAccessUserForm, PNTR AuthorizedAccessUserFormPtr;
19333 
AuthorizedAccessUserFormMessage(ForM f,Int2 mssg)19334 static void AuthorizedAccessUserFormMessage (ForM f, Int2 mssg)
19335 
19336 {
19337   AuthorizedAccessUserFormPtr  afp;
19338 
19339   afp = (AuthorizedAccessUserFormPtr) GetObjectExtra (f);
19340   if (afp != NULL) {
19341     switch (mssg) {
19342       case VIB_MSG_CLOSE :
19343         Remove (f);
19344         break;
19345       case VIB_MSG_CUT :
19346         StdCutTextProc (NULL);
19347         break;
19348       case VIB_MSG_COPY :
19349         StdCopyTextProc (NULL);
19350         break;
19351       case VIB_MSG_PASTE :
19352         StdPasteTextProc (NULL);
19353         break;
19354       case VIB_MSG_DELETE :
19355         StdDeleteTextProc (NULL);
19356         break;
19357       default :
19358         if (afp->appmessage != NULL) {
19359           afp->appmessage (f, mssg);
19360         }
19361         break;
19362     }
19363   }
19364 }
19365 
19366 
UserObjectPtrToAuthorizedAccessDialog(DialoG d,Pointer data)19367 static void UserObjectPtrToAuthorizedAccessDialog (DialoG d, Pointer data)
19368 {
19369   AuthorizedAccessUserDialogPtr  adp;
19370   UserObjectPtr                  uop;
19371   UserFieldPtr                   ufp;
19372   CharPtr                        study = NULL;
19373 
19374   adp = (AuthorizedAccessUserDialogPtr) GetObjectExtra(d);
19375   if (adp == NULL) {
19376     return;
19377   }
19378 
19379   uop = (UserObjectPtr) data;
19380   if (uop != NULL) {
19381     for (ufp = uop->data; ufp != NULL && study == NULL; ufp = ufp->next) {
19382       if (ufp->label != NULL && StringICmp (ufp->label->str, "Study") == 0
19383           && ufp->choice == 1) {
19384         study = (CharPtr) ufp->data.ptrvalue;
19385       }
19386     }
19387   }
19388   SetTitle (adp->study_txt, study);
19389 }
19390 
19391 
AuthorizedAccessDialogToUserObjectPtr(DialoG d)19392 static Pointer AuthorizedAccessDialogToUserObjectPtr (DialoG d)
19393 {
19394   AuthorizedAccessUserDialogPtr  adp;
19395   UserObjectPtr                  uop;
19396   UserFieldPtr                   ufp;
19397   CharPtr                        study = NULL;
19398 
19399   adp = (AuthorizedAccessUserDialogPtr) GetObjectExtra(d);
19400   if (adp == NULL) {
19401     return NULL;
19402   }
19403 
19404   uop = UserObjectNew();
19405   uop->type = ObjectIdNew();
19406   uop->type->str = StringSave("AuthorizedAccess");
19407   if (!TextHasNoText (adp->study_txt)) {
19408     study = SaveStringFromText (adp->study_txt);
19409     ufp = UserFieldNew();
19410     ufp->label = ObjectIdNew();
19411     ufp->label->str = StringSave("Study");
19412     ufp->choice = 1;
19413     ufp->data.ptrvalue = study;
19414     uop->data = ufp;
19415   }
19416   return uop;
19417 }
19418 
19419 
CreateAuthorizedAccessDialog(GrouP g)19420 static DialoG CreateAuthorizedAccessDialog (GrouP g)
19421 
19422 {
19423   AuthorizedAccessUserDialogPtr  adp;
19424   GrouP                  p, p1;
19425 
19426   p = HiddenGroup (g, -1, 0, NULL);
19427   SetGroupSpacing (p, 10, 10);
19428 
19429   adp = (AuthorizedAccessUserDialogPtr) MemNew (sizeof (AuthorizedAccessUserDialog));
19430   if (adp == NULL) return NULL;
19431 
19432   SetObjectExtra (p, adp, NULL);
19433   adp->dialog = (DialoG) p;
19434   adp->todialog = UserObjectPtrToAuthorizedAccessDialog;
19435   adp->fromdialog = AuthorizedAccessDialogToUserObjectPtr;
19436 
19437   p1 = HiddenGroup (p, 2, 0, NULL);
19438   SetGroupSpacing (p1, 10, 10);
19439   StaticPrompt (p1, "Study", 0, dialogTextHeight, programFont, 'c');
19440   adp->study_txt = DialogText (p1, "", 10, NULL);
19441 
19442   return (DialoG) p;
19443 }
19444 
19445 
AuthorizedAccessFormAccept(ButtoN b)19446 static void AuthorizedAccessFormAccept (ButtoN b)
19447 {
19448   AuthorizedAccessUserFormPtr  rfp;
19449   ValNodePtr err;
19450 
19451   rfp = (AuthorizedAccessUserFormPtr) GetObjectExtra (b);
19452   if (rfp == NULL) {
19453     return;
19454   }
19455   err = TestDialog (rfp->data);
19456   if (err != NULL) {
19457     Message (MSG_ERROR, "%s", err->data.ptrvalue);
19458     err = ValNodeFree (err);
19459     return;
19460   }
19461   StdAcceptFormButtonProc (b);
19462 }
19463 
19464 
CreateAuthorizedAccessDescForm(Int2 left,Int2 top,Int2 width,Int2 height,CharPtr title,ValNodePtr sdp,SeqEntryPtr sep,FormActnFunc actproc)19465 static ForM CreateAuthorizedAccessDescForm (Int2 left, Int2 top, Int2 width,
19466                                    Int2 height, CharPtr title, ValNodePtr sdp,
19467                                    SeqEntryPtr sep, FormActnFunc actproc)
19468 
19469 {
19470   AuthorizedAccessUserFormPtr  afp;
19471   ButtoN               b;
19472   GrouP                c;
19473   GrouP                g;
19474   StdEditorProcsPtr    sepp;
19475   WindoW               w;
19476 
19477   w = NULL;
19478   afp = (AuthorizedAccessUserFormPtr) MemNew (sizeof (AuthorizedAccessUserForm));
19479   if (afp != NULL) {
19480     w = FixedWindow (left, top, width, height, title, StdCloseWindowProc);
19481     SetObjectExtra (w, afp, StdDescFormCleanupProc);
19482     afp->form = (ForM) w;
19483     afp->actproc = actproc;
19484     afp->formmessage = AuthorizedAccessUserFormMessage;
19485 
19486     afp->sep = sep;
19487 
19488 #ifndef WIN_MAC
19489     CreateStdEditorFormMenus (w);
19490 #endif
19491     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
19492     if (sepp != NULL) {
19493       SetActivate (w, sepp->activateForm);
19494       afp->appmessage = sepp->handleMessages;
19495     }
19496 
19497     g = HiddenGroup (w, -1, 0, NULL);
19498     afp->data = CreateAuthorizedAccessDialog (g);
19499 
19500     c = HiddenGroup (w, 2, 0, NULL);
19501     b = DefaultButton (c, "Accept", AuthorizedAccessFormAccept);
19502     SetObjectExtra (b, afp, NULL);
19503     PushButton (c, "Cancel", StdCancelButtonProc);
19504     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
19505     RealizeWindow (w);
19506   }
19507   return (ForM) w;
19508 }
19509 
19510 
AuthorizedAccessUserGenFunc(Pointer data)19511 extern Int2 LIBCALLBACK AuthorizedAccessUserGenFunc (Pointer data)
19512 
19513 {
19514   AuthorizedAccessUserFormPtr  afp;
19515   ObjectIdPtr          oip;
19516   OMProcControlPtr     ompcp;
19517   OMUserDataPtr        omudp;
19518   ObjMgrProcPtr        proc;
19519   ValNodePtr           sdp;
19520   SeqEntryPtr          sep;
19521   UserObjectPtr        uop;
19522   WindoW               w;
19523 
19524   ompcp = (OMProcControlPtr) data;
19525   w = NULL;
19526   sdp = NULL;
19527   sep = NULL;
19528   uop = NULL;
19529   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
19530   proc = ompcp->proc;
19531   switch (ompcp->input_itemtype) {
19532     case OBJ_SEQDESC :
19533       sdp = (ValNodePtr) ompcp->input_data;
19534       if (sdp != NULL && sdp->choice != Seq_descr_user) {
19535         return OM_MSG_RET_ERROR;
19536       }
19537       if (sdp != NULL) {
19538         uop = (UserObjectPtr) sdp->data.ptrvalue;
19539       }
19540       break;
19541     case OBJ_BIOSEQ :
19542       break;
19543     case OBJ_BIOSEQSET :
19544       break;
19545     case 0 :
19546       break;
19547     default :
19548       return OM_MSG_RET_ERROR;
19549   }
19550   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
19551                                 ompcp->input_itemtype, ompcp->proc->procid);
19552   if (omudp != NULL) {
19553     if (StringCmp (proc->procname, "Edit AuthorizedAccess User Desc") == 0) {
19554       afp = (AuthorizedAccessUserFormPtr) omudp->userdata.ptrvalue;
19555       if (afp != NULL) {
19556         Select (afp->form);
19557       }
19558       return OM_MSG_RET_DONE;
19559     } else {
19560       return OM_MSG_RET_OK; /* not this type, check next registered user object editor */
19561     }
19562   }
19563   if (uop != NULL) {
19564     oip = uop->type;
19565     if (oip == NULL || oip->str == NULL) return OM_MSG_RET_OK;
19566     if (StringCmp (oip->str, "AuthorizedAccess") != 0) return OM_MSG_RET_OK;
19567   }
19568   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
19569   w = (WindoW) CreateAuthorizedAccessDescForm (-50, -33, -10, -10,
19570                                        "AuthorizedAccess", sdp, sep,
19571                                        StdDescFormActnProc);
19572   afp = (AuthorizedAccessUserFormPtr) GetObjectExtra (w);
19573   if (afp != NULL) {
19574     afp->input_entityID = ompcp->input_entityID;
19575     afp->input_itemID = ompcp->input_itemID;
19576     afp->input_itemtype = ompcp->input_itemtype;
19577     afp->this_itemtype = OBJ_SEQDESC;
19578     afp->this_subtype = Seq_descr_user;
19579     afp->procid = ompcp->proc->procid;
19580     afp->proctype = ompcp->proc->proctype;
19581     afp->userkey = OMGetNextUserKey ();
19582     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
19583 	                           OMPROC_EDIT, afp->userkey);
19584     if (omudp != NULL) {
19585       omudp->userdata.ptrvalue = (Pointer) afp;
19586       omudp->messagefunc = StdVibrantEditorMsgFunc;
19587     }
19588     SendMessageToForm (afp->form, VIB_MSG_INIT);
19589     if (sdp != NULL) {
19590       PointerToDialog (afp->data, (Pointer) sdp->data.ptrvalue);
19591       SetClosestParentIfDuplicating ((BaseFormPtr) afp);
19592       afp->orig_sdp = sdp;
19593     }
19594   }
19595   Show (w);
19596   Select (w);
19597   return OM_MSG_RET_DONE;
19598 }
19599 
19600