1 /*   sequin6.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:  sequin6.c
27 *
28 * Author:  Jonathan Kans
29 *
30 * Version Creation Date:   11/12/97
31 *
32 * $Revision: 6.426 $
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 <ncbilang.h>
47 #include <gather.h>
48 #include <asn2gnbp.h>
49 #include <bspview.h>
50 #include <import.h>
51 #include <objsub.h>
52 #include <explore.h>
53 #include <subutil.h>
54 #include <gbftdef.h>
55 #include <edutil.h>
56 #include <salpanel.h>
57 #include <seqpanel.h>
58 #include <biosrc.h>
59 #include <vsm.h>
60 #include <actutils.h>
61 #include <findrepl.h>
62 #define NLM_GENERATED_CODE_PROTO
63 #include <objmacro.h>
64 #include <macrodlg.h>
65 #include <macroapi.h>
66 
67 #define NUMBER_OF_SUFFIXES    7
68 
ENUM_ALIST(name_suffix_alist)69 static ENUM_ALIST(name_suffix_alist)
70   {" ",    0},
71   {"Jr.",  1},
72   {"Sr.",  2},
73   {"II",   4},
74   {"III",  5},
75   {"IV",   6},
76   {"V",    7},
77   {"VI",   8},
78 END_ENUM_ALIST
79 
80 
81 #define PUBLICATION_PUBLISHED_FIELD 1
82 #define PUBLICATION_INPRESS_FIELD   2
83 #define PUBLICATION_UNPUB_FIELD     3
84 
85 
86 #define GENE_LOCUS_FIELD        1
87 #define GENE_DESCRIPTION_FIELD  2
88 #define GENE_ALLELE_FIELD       3
89 #define GENE_MAPLOC_FIELD       4
90 #define GENE_LOCUS_TAG_FIELD    5
91 #define GENE_SYNONYM_FIELD      6
92 #define GENE_COMMENT_FIELD      7
93 
94 static ENUM_ALIST(gene_field_alist)
95   {" ",                    0},
96   {"Gene locus",           GENE_LOCUS_FIELD},
97   {"Gene description",     GENE_DESCRIPTION_FIELD},
98   {"Gene allele",          GENE_ALLELE_FIELD},
99   {"Gene maploc",          GENE_MAPLOC_FIELD},
100   {"Locus_tag",            GENE_LOCUS_TAG_FIELD},
101   {"Gene synonym",         GENE_SYNONYM_FIELD},
102   {"Gene comment",         GENE_COMMENT_FIELD},
103 END_ENUM_ALIST
104 
105 #define CDS_COMMENT   1
106 #define CDS_GENE_XREF 2
107 #define CDS_DB_XREF   3
108 
109 static ENUM_ALIST(cds_field_alist)
110   {" ",                    0},
111   {"CDS comment",          CDS_COMMENT},
112   {"gene xref",            CDS_GENE_XREF},
113   {"db_xref",              CDS_DB_XREF},
114 END_ENUM_ALIST
115 
116 #define PROT_NAME_FIELD        1
117 #define PROT_DESCRIPTION_FIELD 2
118 #define PROT_ECNUM_FIELD       3
119 #define PROT_ACTIVITY_FIELD    4
120 #define PROT_COMMENT_FIELD     5
121 
122 static ENUM_ALIST(prot_field_alist)
123   {" ",                    0},
124   {"Protein name",         PROT_NAME_FIELD},
125   {"Protein description",  PROT_DESCRIPTION_FIELD},
126   {"Protein E.C. number",  PROT_ECNUM_FIELD},
127   {"Protein activity",     PROT_ACTIVITY_FIELD},
128   {"Protein comment",      PROT_COMMENT_FIELD},
129 END_ENUM_ALIST
130 
131 #define RNA_NAME_FIELD       1
132 #define RNA_COMMENT_FIELD    2
133 #define RNA_GENE_XREF_FIELD  3
134 
135 static ENUM_ALIST(rnax_field_alist)
136   {" ",                    0},
137   {"RNA Name",             RNA_NAME_FIELD},
138   {"RNA Comment",          RNA_COMMENT_FIELD},
139   {"gene xref",            RNA_GENE_XREF_FIELD},
140 END_ENUM_ALIST
141 
142 #define ORGREF_SCI_NAME_FIELD    1
143 #define ORGREF_COMMON_NAME_FIELD 2
144 #define ORGREF_LINEAGE_FIELD     3
145 #define ORGREF_DIVISION_FIELD    4
146 
147 static ENUM_ALIST(orgref_field_alist)
148   {" ",                    0},
149   {"Scientific Name",      ORGREF_SCI_NAME_FIELD},
150   {"Common Name",          ORGREF_COMMON_NAME_FIELD},
151   {"Lineage",              ORGREF_LINEAGE_FIELD},
152   {"Division",             ORGREF_DIVISION_FIELD},
153 END_ENUM_ALIST
154 
155 #define IMPORT_GBQUAL_FIELD  1
156 #define IMPORT_COMMENT_FIELD 2
157 
158 static ENUM_ALIST(impfeat_field_alist)
159   {" ",        0},
160   {"GBQual",   IMPORT_GBQUAL_FIELD},
161   {"Comment",  IMPORT_COMMENT_FIELD},
162 END_ENUM_ALIST
163 
164 
165 #define NUM_SUBTARGET_POPUPS 12
166 
167 
168 static DialoG ImpFeatSelectDialog (GrouP g, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
169 {
170   EnumFieldAssocPtr list, ap;
171   ValNodePtr   choice_list = NULL;
172 
173   list = import_featdef_alist (FALSE, FALSE, FALSE);
174   SortEnumFieldAssocPtrArray (list, CompareImpFeatEnumFieldAssoc);
175   for (ap = list; ap->name != NULL; ap++) {
176     if (ap == list) {
177       ValNodeAddPointer (&choice_list, 0, StringSave ("All import features"));
178     } else {
179       ValNodeAddPointer (&choice_list, 0, StringSave (ap->name));
180     }
181   }
182   return ValNodeSelectionDialog (g, choice_list, TALL_SELECTION_LIST,
183                                                 ValNodeStringName,
184                                 ValNodeSimpleDataFree, ValNodeStringCopy,
185                                 ValNodeChoiceMatch, "Import Feature Type",
186                                 change_notify, change_userdata, FALSE);
187 }
188 
189 typedef enum {
190   eFieldTypeGene = 0,
191   eFieldTypeCDS,
192   eFieldTypeProtein,
193   eFieldTypeRNA,
194   eFieldTypeBioSource,
195   eFieldTypeOrgModSubSource,
196   eFieldTypeImport,
197   eFieldTypeDefline,
198   eFieldTypeCommentDescriptor,
199   eFieldTypeFeatureNote,
200   eFieldTypePublication,
201   eFieldType_Max
202 } SegregateFieldType;
203 
204 static CharPtr field_type_names[] = {
205   "Gene",
206   "CDS",
207   "Protein",
208   "RNA",
209   "BioSource",
210   "OrgMod and SubSource",
211   "Import Feature",
212   "DefLine",
213   "Comment Descriptor",
214   "Feature Note",
215   "Publication" };
216 
217 
218 typedef struct fieldsubfield {
219   Int4 field;
220   Int4 subfield;
221   CharPtr impfeat_key;
222   ValNodePtr subfield_list;
223 } FieldSubfieldData, PNTR FieldSubfieldPtr;
224 
225 
FieldSubfieldFree(FieldSubfieldPtr f)226 static FieldSubfieldPtr FieldSubfieldFree (FieldSubfieldPtr f)
227 {
228   if (f != NULL) {
229     f->subfield_list = ValNodeFree (f->subfield_list);
230     f->impfeat_key = MemFree (f->impfeat_key);
231     f = MemFree (f);
232   }
233   return f;
234 }
235 
236 
237 typedef struct fieldsubfielddlg {
238   DIALOG_MESSAGE_BLOCK
239   PopuP field_list;
240   DialoG subfield_dlg[eFieldType_Max];
241   DialoG impfeat_type;
242   Boolean allowed_fields[eFieldType_Max];
243   Nlm_ChangeNotifyProc     change_notify;
244   Pointer                  change_userdata;
245 } FieldSubfieldDlgData, PNTR FieldSubfieldDlgPtr;
246 
247 
FieldNumFromListVal(Int4 list_val,BoolPtr allowed_fields)248 static Int4 FieldNumFromListVal (Int4 list_val, BoolPtr allowed_fields)
249 {
250   Int4 i;
251   Int4 field_num = -1;
252 
253   if (list_val < 1) return -1;
254 
255   for (i = 0; i < eFieldType_Max && field_num < 0; i++) {
256     if (allowed_fields[i]) {
257       if (list_val - 1 == i) {
258         field_num = i;
259       }
260     } else {
261       list_val++;
262     }
263   }
264   return field_num;
265 }
266 
267 
ListValFromFieldNum(Int4 field_num,BoolPtr allowed_fields)268 static Int4 ListValFromFieldNum (Int4 field_num, BoolPtr allowed_fields)
269 {
270   Int4 list_val = 0, i = 0;
271 
272   if (field_num < 0) return 0;
273 
274   while (i <= field_num) {
275     if (allowed_fields[i]) {
276       list_val++;
277     }
278     i++;
279   }
280   return list_val;
281 }
282 
283 
ChangeFieldType(PopuP p)284 static void ChangeFieldType (PopuP p)
285 {
286   FieldSubfieldDlgPtr dlg;
287   Int4                list_val, field_num, i;
288 
289   dlg = (FieldSubfieldDlgPtr) GetObjectExtra (p);
290   if (dlg == NULL) return;
291 
292   list_val = GetValue (dlg->field_list);
293   field_num = FieldNumFromListVal (list_val, dlg->allowed_fields);
294 
295   for (i = 0; i < eFieldType_Max; i++) {
296     if (dlg->subfield_dlg[i] == NULL) continue;
297     if (i == field_num) {
298       Show (dlg->subfield_dlg[i]);
299     } else {
300       Hide (dlg->subfield_dlg[i]);
301     }
302   }
303   if (field_num == eFieldTypeImport) {
304     Show (dlg->impfeat_type);
305   } else {
306     Hide (dlg->impfeat_type);
307   }
308   if (dlg->change_notify != NULL) {
309     (dlg->change_notify) (dlg->change_userdata);
310   }
311 }
312 
313 
FieldSubfieldToDialog(DialoG d,Pointer data)314 static void FieldSubfieldToDialog (DialoG d, Pointer data)
315 {
316   FieldSubfieldDlgPtr dlg;
317   FieldSubfieldPtr    f;
318   Int4                list_val;
319   ValNode             vn;
320 
321   dlg = (FieldSubfieldDlgPtr) GetObjectExtra (d);
322   if (dlg == NULL) return;
323 
324   f = (FieldSubfieldPtr) data;
325   if (f == NULL || f->field < 0) {
326     SetValue (dlg->field_list, 0);
327   } else {
328     list_val = ListValFromFieldNum (f->field, dlg->allowed_fields);
329     SetValue (dlg->field_list, list_val);
330     if (dlg->subfield_dlg[f->field] != NULL) {
331       if (list_val == eFieldTypeFeatureNote) {
332         PointerToDialog (dlg->subfield_dlg[eFieldTypeFeatureNote], f->subfield_list);
333       } else {
334         vn.choice = f->subfield;
335         vn.data.ptrvalue = NULL;
336         vn.next = NULL;
337         PointerToDialog (dlg->subfield_dlg[f->field], &vn);
338         if (f->field == eFieldTypeImport) {
339           vn.choice = 0;
340           vn.data.ptrvalue = f->impfeat_key;
341           PointerToDialog (dlg->impfeat_type, &vn);
342         }
343       }
344     }
345   }
346   ChangeFieldType (dlg->field_list);
347 }
348 
349 
DialogToFieldSubfield(DialoG d)350 static Pointer DialogToFieldSubfield (DialoG d)
351 {
352   FieldSubfieldDlgPtr dlg;
353   FieldSubfieldPtr f;
354   Int4             val;
355   ValNodePtr       vnp;
356   SourceQualDescPtr sqdp;
357 
358   dlg = (FieldSubfieldDlgPtr) GetObjectExtra (d);
359   if (dlg == NULL) return NULL;
360 
361   f = (FieldSubfieldPtr) MemNew (sizeof (FieldSubfieldData));
362   f->field = -1;
363   f->subfield = -1;
364   f->subfield_list = NULL;
365   f->impfeat_key = NULL;
366 
367   val = GetValue (dlg->field_list);
368   if (val > 0) {
369     f->field = FieldNumFromListVal (val, dlg->allowed_fields);
370     if (dlg->subfield_dlg[f->field] == NULL) {
371       f->subfield = 0;
372     } else {
373       if (f->field == eFieldTypeFeatureNote) {
374         f->subfield_list = DialogToPointer (dlg->subfield_dlg[f->field]);
375       } else {
376         vnp = DialogToPointer (dlg->subfield_dlg[f->field]);
377         if (vnp != NULL) {
378           if (f->field == eFieldTypeOrgModSubSource) {
379             sqdp = (SourceQualDescPtr) vnp->data.ptrvalue;
380             if (sqdp != NULL) {
381               f->subfield = sqdp->subtype;
382               if (!sqdp->isOrgMod) {
383                 f->subfield += 1000;
384               }
385             }
386           } else {
387             f->subfield = vnp->choice;
388             vnp = ValNodeFree (vnp);
389           }
390         }
391         if (f->field == eFieldTypeImport) {
392           vnp = DialogToPointer (dlg->impfeat_type);
393           if (vnp != NULL) {
394             f->impfeat_key = StringSave (vnp->data.ptrvalue);
395             vnp = ValNodeFree (vnp);
396           }
397         }
398       }
399     }
400   }
401 
402   return f;
403 }
404 
405 
TestFieldSubfieldDialog(DialoG d)406 static ValNodePtr TestFieldSubfieldDialog (DialoG d)
407 {
408   ValNodePtr          err_list = NULL;
409   FieldSubfieldPtr    f;
410 
411   f = DialogToPointer (d);
412   if (f == NULL || f->field < 0
413       || (f->subfield < 0 && f->subfield_list == NULL)
414       || (f->field == eFieldTypeImport && f->impfeat_key == NULL)) {
415     ValNodeAddPointer (&err_list, 0, "Must choose field");
416   }
417   f = FieldSubfieldFree (f);
418   return err_list;
419 }
420 
421 
422 static DialoG
CreateFieldSubfieldDlg(GrouP h,BoolPtr allowed_fields,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)423 CreateFieldSubfieldDlg
424 (GrouP h,
425  BoolPtr allowed_fields,
426  Nlm_ChangeNotifyProc     change_notify,
427  Pointer                  change_userdata)
428 {
429   FieldSubfieldDlgPtr dlg;
430   GrouP               p, g, g2;
431   Int4                i;
432   ValNode             vn;
433 
434   dlg = (FieldSubfieldDlgPtr) MemNew (sizeof (FieldSubfieldDlgData));
435   if (dlg == NULL)
436   {
437     return NULL;
438   }
439 
440   p = HiddenGroup (h, 2, 0, NULL);
441   SetObjectExtra (p, dlg, StdCleanupExtraProc);
442 
443   dlg->dialog = (DialoG) p;
444   dlg->todialog = FieldSubfieldToDialog;
445   dlg->fromdialog = DialogToFieldSubfield;
446   dlg->testdialog = TestFieldSubfieldDialog;
447   dlg->change_notify = change_notify;
448   dlg->change_userdata = change_userdata;
449 
450   if (allowed_fields == NULL) {
451     MemSet (dlg->allowed_fields, TRUE, sizeof (dlg->allowed_fields));
452   } else {
453     for (i = 0; i < eFieldType_Max; i++) {
454       dlg->allowed_fields[i] = allowed_fields[i];
455     }
456   }
457 
458   dlg->field_list = PopupList (p, TRUE, ChangeFieldType);
459   SetObjectExtra (dlg->field_list, dlg, NULL);
460   for (i = 0; i < eFieldType_Max; i++) {
461     if (dlg->allowed_fields[i]) {
462       PopupItem (dlg->field_list, field_type_names[i]);
463     }
464   }
465 
466   g = HiddenGroup (p, 0, 0, NULL);
467   dlg->subfield_dlg[eFieldTypeGene] = EnumAssocSelectionDialog (g, gene_field_alist,
468                                                                 NULL, FALSE,
469                                                                 dlg->change_notify,
470                                                                 dlg->change_userdata);
471   dlg->subfield_dlg[eFieldTypeCDS] = EnumAssocSelectionDialog (g, cds_field_alist,
472                                                                 NULL, FALSE,
473                                                                 dlg->change_notify,
474                                                                 dlg->change_userdata);
475   dlg->subfield_dlg[eFieldTypeProtein] = EnumAssocSelectionDialog (g, prot_field_alist,
476                                                                 NULL, FALSE,
477                                                                 dlg->change_notify,
478                                                                 dlg->change_userdata);
479   dlg->subfield_dlg[eFieldTypeRNA] = EnumAssocSelectionDialog (g, rnax_field_alist,
480                                                                 NULL, FALSE,
481                                                                 dlg->change_notify,
482                                                                 dlg->change_userdata);
483   dlg->subfield_dlg[eFieldTypeBioSource] = EnumAssocSelectionDialog (g, orgref_field_alist,
484                                                                 NULL, FALSE,
485                                                                 dlg->change_notify,
486                                                                 dlg->change_userdata);
487   /* Set default BioSource field to scientific name */
488   vn.choice = ORGREF_SCI_NAME_FIELD;
489   vn.next = NULL;
490   vn.data.ptrvalue = NULL;
491   PointerToDialog (dlg->subfield_dlg[eFieldTypeBioSource], &vn);
492 
493   dlg->subfield_dlg[eFieldTypeOrgModSubSource] = SourceQualTypeSelectionDialog (g, FALSE,
494                                                                                 dlg->change_notify,
495                                                                                 dlg->change_userdata);
496 
497   if (dlg->allowed_fields[eFieldTypeImport]) {
498     g2 = HiddenGroup (g, 2, 0, NULL);
499     dlg->impfeat_type = ImpFeatSelectDialog (g2, change_notify, change_userdata);
500     Hide (dlg->impfeat_type);
501 
502     dlg->subfield_dlg[eFieldTypeImport] = EnumAssocSelectionDialog (g2, impfeat_field_alist,
503                                                                 NULL, FALSE,
504                                                                 dlg->change_notify,
505                                                                 dlg->change_userdata);
506   }
507   dlg->subfield_dlg[eFieldTypeFeatureNote] = FeatureSelectionDialog (g, TRUE, dlg->change_notify, dlg->change_userdata);
508 
509   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->subfield_dlg[eFieldTypeGene],
510                               (HANDLE) dlg->subfield_dlg[eFieldTypeCDS],
511                               (HANDLE) dlg->subfield_dlg[eFieldTypeProtein],
512                               (HANDLE) dlg->subfield_dlg[eFieldTypeRNA],
513                               (HANDLE) dlg->subfield_dlg[eFieldTypeBioSource],
514                               (HANDLE) dlg->subfield_dlg[eFieldTypeOrgModSubSource],
515                               (HANDLE) dlg->subfield_dlg[eFieldTypeFeatureNote],
516                               (HANDLE) g2,
517                               NULL);
518 
519   for (i = 0; i < eFieldType_Max; i++) {
520     Hide (dlg->subfield_dlg[i]);
521   }
522   return (DialoG) p;
523 }
524 
525 
526 typedef struct convertformdata {
527   FEATURE_FORM_BLOCK
528 
529   TexT               deleteText;
530   CharPtr            deleteStr;
531   GrouP              deleteLevel;
532   Int2               deleteLevelInt;
533   DialoG             target_dlg;
534   Int2               impfeat_type;
535   ButtoN             accept;
536   ButtoN             leaveDlgUp;
537   Int2               type;
538   Int2               subtype;
539 
540   DialoG             textportion_dlg;
541   TextPortionXPtr     textportion;
542   Boolean            remove_inside;
543 
544   CharPtr            foundstr;
545   GrouP              repeat_remove_grp;
546 
547   Boolean            isDirty;
548   Boolean            repeat_remove;
549   GrouP              ifNotFoundGroup;
550   Int2               ifNotFound;
551   BioseqSetPtr       target_set;
552   Nlm_ChangeNotifyProc set_accept_proc;
553   ValNodePtr         id_list;
554 
555 } ConvertFormData, PNTR ConvertFormPtr;
556 
ConvertFormNew(void)557 static ConvertFormPtr ConvertFormNew (void)
558 {
559   ConvertFormPtr cfp;
560 
561   cfp = (ConvertFormPtr) MemNew (sizeof (ConvertFormData));
562   if (cfp == NULL) return NULL;
563   MemSet (cfp, 0, sizeof (ConvertFormData));
564   return cfp;
565 }
566 
567 
568 /* Values for ifNotFound field */
569 
570 #define DO_NOTHING       2
571 #define REMOVE_ALL_TEXT  3
572 
573 
574 /*-------------------------------------------------------------------------*/
575 /*                                                                         */
576 /* SaveStringFromTextNoStripSpaces () -                                    */
577 /*                                                                         */
578 /*-------------------------------------------------------------------------*/
579 
SaveStringFromTextNoStripSpaces(TexT t)580 static CharPtr SaveStringFromTextNoStripSpaces (TexT t)
581 
582 {
583   size_t   len;
584   CharPtr  str;
585 
586   len = TextLength (t);
587   if (len > 0) {
588     str = (CharPtr) MemNew(len + 1);
589     if (str != NULL) {
590       GetTitle (t, str, len + 1);
591       return str;
592     } else {
593       return NULL;
594     }
595   } else {
596     return NULL;
597   }
598 }
599 
ConvertFormTextCallback(TexT t)600 static void ConvertFormTextCallback (TexT t)
601 {
602   ConvertFormPtr cfp;
603 
604   cfp = (ConvertFormPtr) GetObjectExtra (t);
605   if (cfp != NULL && cfp->set_accept_proc != NULL) {
606     (cfp->set_accept_proc) (cfp);
607   }
608 }
609 
610 
ChangeTargetFields(Pointer data)611 static void ChangeTargetFields (Pointer data)
612 
613 {
614   ConvertFormPtr  cfp;
615 
616   cfp = (ConvertFormPtr) data;
617   if (cfp == NULL) return;
618 
619   if (cfp->set_accept_proc != NULL) {
620     cfp->set_accept_proc (cfp);
621   }
622 }
623 
624 
625 /*=========================================================================*/
626 /*                                                                         */
627 /* CheckForString () -- Searches for a given string with another string.   */
628 /*                                                                         */
629 /*=========================================================================*/
630 
CheckForString(CharPtr searchStr,CharPtr sourceStr)631 static Boolean CheckForString (CharPtr searchStr,
632 			       CharPtr sourceStr)
633 {
634   if (NULL == SearchForString (sourceStr, searchStr, FALSE, FALSE))
635     return FALSE;
636   else
637     return TRUE;
638 }
639 
640 /*=========================================================================*/
641 /*                                                                         */
642 /* GeneRefPtr () -- Search a GeneRef feature for a given string.           */
643 /*                                                                         */
644 /*=========================================================================*/
645 
SearchGeneRef(GeneRefPtr grp,SeqFeatPtr sfp,ConvertFormPtr cfp)646 static Boolean SearchGeneRef (GeneRefPtr     grp,
647 			      SeqFeatPtr     sfp,
648 			      ConvertFormPtr cfp)
649 {
650   ValNodePtr vnp;
651 
652   /* Check parameters */
653 
654   if ((NULL == grp) || (NULL == sfp))
655     return FALSE;
656 
657   /* Check each text field for the given string */
658 
659   switch (cfp->subtype) {
660   case 1 :
661     return CheckForString (cfp->deleteStr, grp->locus);
662     break;
663   case 2 :
664     return CheckForString (cfp->deleteStr, grp->desc);
665     break;
666   case 3 :
667     return CheckForString (cfp->deleteStr, grp->allele);
668     break;
669   case 4 :
670     return CheckForString (cfp->deleteStr, grp->maploc);
671     break;
672   case 5 :
673     return CheckForString (cfp->deleteStr, grp->locus_tag);
674     break;
675   case 6 :
676     for (vnp = grp->syn; vnp != NULL; vnp = vnp->next) {
677       if (TRUE == CheckForString (cfp->deleteStr,
678 				  vnp->data.ptrvalue))
679 	return TRUE;
680     }
681     return FALSE;
682     break;
683   case 7 :
684     return CheckForString (cfp->deleteStr, sfp->comment);
685     break;
686   default :
687     break;
688   }
689 
690   return FALSE;
691 }
692 
693 /*=========================================================================*/
694 /*                                                                         */
695 /* SearchCDSFeat () -- Search a CDS feature for a given string.            */
696 /*                                                                         */
697 /*=========================================================================*/
698 
SearchCDSFeat(SeqFeatPtr sfp,ConvertFormPtr cfp)699 static Boolean SearchCDSFeat (SeqFeatPtr     sfp,
700 			      ConvertFormPtr cfp)
701 {
702 
703   /* Check parameters */
704 
705   if (NULL == sfp)
706     return FALSE;
707 
708   /* Check each text field for the given string */
709 
710   switch (cfp->subtype) {
711   case 1 :
712     return CheckForString (cfp->deleteStr, sfp->comment);
713     break;
714   case 2 :
715   default :
716     break;
717   }
718 
719   /* If no match found, return FALSE */
720 
721   return FALSE;
722 }
723 
724 /*=========================================================================*/
725 /*                                                                         */
726 /* SearchRnaRef () -- Search an RnaRef feature for a given string.         */
727 /*                                                                         */
728 /*=========================================================================*/
729 
SearchRnaRef(RnaRefPtr rrp,SeqFeatPtr sfp,ConvertFormPtr cfp)730 static Boolean SearchRnaRef (RnaRefPtr      rrp,
731 			     SeqFeatPtr     sfp,
732 			     ConvertFormPtr cfp)
733 {
734   /* Check parameters */
735 
736   if ((NULL == rrp) || (NULL == sfp))
737     return FALSE;
738 
739   /* Check each text field for the given string */
740 
741   switch (cfp->subtype) {
742   case 1 :
743     if ((0 == rrp->ext.choice) || (1 == rrp->ext.choice)) {
744       return CheckForString (cfp->deleteStr, rrp->ext.value.ptrvalue);
745     }
746     break;
747   case 2 :
748     return CheckForString (cfp->deleteStr, sfp->comment);
749     break;
750   case 3 :
751   default :
752     break;
753   }
754 
755   /* If no match found, return FALSE */
756 
757   return FALSE;
758 }
759 
760 /*=========================================================================*/
761 /*                                                                         */
762 /* SearchProtRef () -- Search a ProtRef feature for a given string.        */
763 /*                                                                         */
764 /*=========================================================================*/
765 
SearchProtRef(ProtRefPtr prp,SeqFeatPtr sfp,ConvertFormPtr cfp)766 static Boolean SearchProtRef (ProtRefPtr     prp,
767 			      SeqFeatPtr     sfp,
768 			      ConvertFormPtr cfp)
769 {
770   ValNodePtr vnp;
771 
772   /* Check parameters */
773 
774   if (NULL == prp)
775     return FALSE;
776 
777   /* Check each text field for the given string */
778 
779   switch (cfp->subtype) {
780 
781     /* Search the name field */
782 
783   case 1 :
784     for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
785       if (TRUE == CheckForString (cfp->deleteStr,
786 				  (CharPtr) vnp->data.ptrvalue))
787 	return TRUE;
788     }
789     break;
790 
791     /* Search the desc field */
792 
793   case 2 :
794     return CheckForString (cfp->deleteStr, prp->desc);
795     break;
796 
797     /* Search the ec field */
798 
799   case 3 :
800     for (vnp = prp->ec; vnp != NULL; vnp = vnp->next) {
801       if (TRUE == CheckForString (cfp->deleteStr, vnp->data.ptrvalue))
802 	return TRUE;
803     }
804     break;
805 
806     /* Search the activity field */
807 
808   case 4 :
809     for (vnp = prp->activity; vnp != NULL; vnp = vnp->next) {
810       if (TRUE == CheckForString (cfp->deleteStr, vnp->data.ptrvalue))
811 	return TRUE;
812     }
813     break;
814 
815     /* Search the comment field */
816 
817   case 5 :
818     return CheckForString (cfp->deleteStr, sfp->comment);
819     break;
820 
821     /* Default check */
822 
823   default :
824     break;
825   }
826 
827   /* If we made it this far no match was found */
828 
829   return FALSE;
830 }
831 
832 /*=========================================================================*/
833 /*                                                                         */
834 /* SearchImpFeat () -- Search an ImpFeat feature for a given string.       */
835 /*                                                                         */
836 /*=========================================================================*/
837 
SearchImpFeat(SeqFeatPtr sfp,ConvertFormPtr cfp)838 static Boolean SearchImpFeat (SeqFeatPtr     sfp,
839 			      ConvertFormPtr cfp)
840 {
841   GBQualPtr       gbqp;
842 
843   /* Check parameters */
844 
845   if (NULL == sfp)
846     return FALSE;
847 
848   switch (cfp->subtype) {
849 
850     /* Search the GB Quals */
851 
852   case IMPORT_GBQUAL_FIELD :
853     gbqp = sfp->qual;
854     while (NULL != gbqp) {
855       if (NULL != gbqp->val)
856 	if (TRUE == CheckForString (cfp->deleteStr, gbqp->val))
857 	  return TRUE;
858       gbqp = gbqp->next;
859     }
860     return FALSE;
861     break;
862 
863     /* Search the comment field */
864 
865   case IMPORT_COMMENT_FIELD :
866     return CheckForString (cfp->deleteStr, sfp->comment);
867     break;
868   default :
869     break;
870   }
871 
872   return FALSE;
873 }
874 
875 
DoesBioSourceContainText(BioSourcePtr biop,ConvertFormPtr cfp)876 static Boolean DoesBioSourceContainText
877 (BioSourcePtr biop,
878  ConvertFormPtr cfp)
879 {
880   OrgRefPtr     orp;
881   Boolean       found;
882   OrgNamePtr    onp;
883 
884   if (biop == NULL || cfp == NULL) return FALSE;
885 
886   found = FALSE;
887 
888   orp = biop->org;
889   if (orp == NULL) return FALSE;
890   switch (cfp->subtype) {
891     case ORGREF_SCI_NAME_FIELD :
892       found = CheckForString (cfp->deleteStr, orp->taxname);
893       break;
894     case ORGREF_COMMON_NAME_FIELD :
895 	  found = CheckForString (cfp->deleteStr, orp->common);
896       break;
897     case ORGREF_LINEAGE_FIELD :
898       onp = orp->orgname;
899       if (onp == NULL) {
900         onp = OrgNameNew ();
901         orp->orgname = onp;
902       }
903       if (onp != NULL)
904 	    found = CheckForString (cfp->deleteStr, onp->lineage);
905 	  else
906 	    found = FALSE;
907       break;
908     case ORGREF_DIVISION_FIELD :
909       onp = orp->orgname;
910       if (onp == NULL) {
911         onp = OrgNameNew ();
912         orp->orgname = onp;
913       }
914       if (onp != NULL)
915         found = CheckForString (cfp->deleteStr, onp->div);
916 	  else
917 	    found = FALSE;
918       break;
919     default :
920       break;
921   }
922   return found;
923 }
924 
DoSubSourcesContainText(BioSourcePtr biop,ConvertFormPtr cfp)925 static Boolean DoSubSourcesContainText
926 (BioSourcePtr biop,
927  ConvertFormPtr cfp)
928 {
929   OrgRefPtr     orp;
930   OrgModPtr     mod;
931   SubSourcePtr  ssp;
932   OrgNamePtr    onp;
933   Boolean found = FALSE;
934 
935   if (biop == NULL || cfp == NULL) return FALSE;
936   if (cfp->subtype < 1000) {
937 	orp = biop->org;
938 	if (orp == NULL) {
939 	  orp = OrgRefNew ();
940 	  biop->org = orp;
941 	}
942 	if (orp != NULL) {
943 	  onp = orp->orgname;
944 	  if (onp == NULL) {
945 	    onp = OrgNameNew ();
946 	    orp->orgname = onp;
947 	  }
948 	  if (onp != NULL) {
949 	    mod = onp->mod;
950 	    while (mod != NULL && mod->subtype != cfp->subtype) {
951 	      mod = mod->next;
952 	    }
953 	    if (mod != NULL)
954 	      found = CheckForString (cfp->deleteStr, mod->subname);
955 	    else
956 	      found = FALSE;
957 	  }
958 	  else
959 	    found = FALSE;
960 	}
961   } else {
962 	ssp = biop->subtype;
963 	while (ssp != NULL && ssp->subtype != (cfp->subtype - 1000)) {
964 	  ssp = ssp->next;
965 	}
966 	while (ssp != NULL) {
967 	  if (ssp->subtype == (cfp->subtype - 1000)) {
968 	    found = CheckForString (cfp->deleteStr, ssp->name);
969 	    if (found)
970 	      break;
971 	  }
972 	  ssp = ssp->next;
973 	}
974 	if (NULL == ssp)
975 	  found = FALSE;
976   }
977   return found;
978 }
979 
980 
981 typedef Boolean (LIBCALLBACK *wantSegregateNucProtSetFunction)
982 ( BioseqSetPtr bssp,
983   Pointer      userdata);
984 
985 typedef Boolean (LIBCALLBACK *wantSegregateSequenceFunction)
986 ( BioseqPtr bsp,
987   Pointer   userdata);
988 
989 /*=========================================================================*/
990 /*                                                                         */
991 /* SegregateItemsRecursor () - Given a functions for determining which bioseqs     */
992 /*                     meet conditions, segregate bioseqs into separate    */
993 /*                     sets.                                               */
994 /*                                                                         */
995 /*=========================================================================*/
996 
SegregateItemsRecursor(SeqEntryPtr seqlist,BioseqSetPtr set1,BioseqSetPtr set2,wantSegregateNucProtSetFunction do_np,wantSegregateSequenceFunction do_seq,Pointer userdata)997 static void SegregateItemsRecursor
998 (SeqEntryPtr                     seqlist,
999  BioseqSetPtr                    set1,
1000  BioseqSetPtr                    set2,
1001  wantSegregateNucProtSetFunction do_np,
1002  wantSegregateSequenceFunction   do_seq,
1003  Pointer                         userdata
1004  )
1005 {
1006 
1007   BioseqPtr         bsp;
1008   BioseqSetPtr      this_bssp;
1009   SeqEntryPtr       this_list;
1010   SeqEntryPtr       sep, next_sep;
1011   SeqEntryPtr       set1last, set2last;
1012 
1013 
1014   if (set1 == NULL || set2 == NULL || seqlist == NULL)
1015     return;
1016 
1017   set1last = set1->seq_set;
1018   while (set1last != NULL && set1last->next != NULL) {
1019     set1last = set1last->next;
1020   }
1021   set2last = set2->seq_set;
1022   while (set2last != NULL && set2last->next != NULL) {
1023     set2last = set2last->next;
1024   }
1025 
1026   sep = seqlist;
1027   while (sep != NULL) {
1028     next_sep = sep->next;
1029     if (IS_Bioseq_set (sep)) {
1030       this_bssp = (BioseqSetPtr) sep->data.ptrvalue;
1031       if (this_bssp->_class == BioseqseqSet_class_nuc_prot) {
1032         if (do_np != NULL && do_np (this_bssp, userdata)) {
1033           if (set2last == NULL) {
1034             set2->seq_set = sep;
1035           } else {
1036             set2last->next = sep;
1037           }
1038           set2last = sep;
1039         } else {
1040           if (set1last == NULL) {
1041             set1->seq_set = sep;
1042           } else {
1043             set1last->next = sep;
1044           }
1045           set1last = sep;
1046         }
1047         sep->next = NULL;
1048       } else {
1049         /* copy class types from this set if class types are not set */
1050         if (set1->_class == BioseqseqSet_class_genbank
1051             && set2->_class == BioseqseqSet_class_genbank) {
1052           set1->_class = this_bssp->_class;
1053           set2->_class = this_bssp->_class;
1054         }
1055         /* copy descriptors from this set */
1056         if (this_bssp != set1) {
1057           ValNodeLink (&(set1->descr),
1058                        AsnIoMemCopy ((Pointer) this_bssp->descr,
1059                                      (AsnReadFunc) SeqDescrAsnRead,
1060                                      (AsnWriteFunc) SeqDescrAsnWrite));
1061         }
1062         if (this_bssp != set2) {
1063           ValNodeLink (&(set2->descr),
1064                        AsnIoMemCopy ((Pointer) this_bssp->descr,
1065                                      (AsnReadFunc) SeqDescrAsnRead,
1066                                      (AsnWriteFunc) SeqDescrAsnWrite));
1067         }
1068         if (this_bssp != set1 && this_bssp != set2) {
1069           this_bssp->descr = SeqDescrFree (this_bssp->descr);
1070         }
1071 
1072         this_list = this_bssp->seq_set;
1073         this_bssp->seq_set = NULL;
1074         SegregateItemsRecursor (this_list, set1, set2, do_np, do_seq, userdata);
1075       }
1076     } else if (IS_Bioseq (sep)) {
1077       bsp = (BioseqPtr) sep->data.ptrvalue;
1078       if (do_seq != NULL && do_seq (bsp, userdata)) {
1079         if (set2last == NULL) {
1080           set2->seq_set = sep;
1081         } else {
1082           set2last->next = sep;
1083         }
1084         set2last = sep;
1085       } else {
1086         if (set1last == NULL) {
1087           set1->seq_set = sep;
1088         } else {
1089           set1last->next = sep;
1090         }
1091         set1last = sep;
1092       }
1093       sep->next = NULL;
1094     }
1095     sep = next_sep;
1096   }
1097 }
1098 
1099 
DoFeaturesInAnnotContainText(SeqAnnotPtr sap,ConvertFormPtr cfp)1100 static Boolean DoFeaturesInAnnotContainText (SeqAnnotPtr sap, ConvertFormPtr cfp)
1101 {
1102   SeqFeatPtr     sfp;
1103   GeneRefPtr     grp;
1104   ProtRefPtr     prp;
1105   RnaRefPtr      rrp;
1106   Boolean        found = FALSE;
1107   ValNodePtr     vnp;
1108   FieldSubfieldPtr f;
1109 
1110   if (sap == NULL || cfp == NULL) return FALSE;
1111 
1112   /* Search the requested item for the given string */
1113 
1114   while (sap != NULL && !found) {
1115     if (sap->type == 1) {
1116       sfp = (SeqFeatPtr) sap->data;
1117       while (sfp != NULL && !found) {
1118         if (sfp->data.choice == SEQFEAT_GENE && cfp->type == eFieldTypeGene) {
1119           grp = (GeneRefPtr) sfp->data.value.ptrvalue;
1120 	      found = SearchGeneRef (grp, sfp, cfp);
1121         } else if (sfp->data.choice == SEQFEAT_CDREGION && cfp->type == eFieldTypeCDS) {
1122 	      found = SearchCDSFeat (sfp, cfp);
1123         } else if (sfp->data.choice == SEQFEAT_PROT && cfp->type == eFieldTypeProtein) {
1124           prp = (ProtRefPtr) sfp->data.value.ptrvalue;
1125 	      found = SearchProtRef (prp, sfp, cfp);
1126         } else if (sfp->data.choice == SEQFEAT_RNA && cfp->type == eFieldTypeRNA) {
1127           rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
1128 	      found = SearchRnaRef (rrp, sfp, cfp);
1129         } else if (sfp->data.choice == SEQFEAT_IMP &&
1130 		      cfp->type == eFieldTypeImport) {
1131 	      found = SearchImpFeat (sfp, cfp);
1132         } else if (cfp->type == eFieldTypeFeatureNote) {
1133           f = DialogToPointer (cfp->target_dlg);
1134           if (f != NULL) {
1135             for (vnp = f->subfield_list; vnp != NULL; vnp = vnp->next) {
1136               if (vnp->choice == sfp->idx.subtype
1137                   && CheckForString (cfp->deleteStr, sfp->comment)) {
1138                 found = TRUE;
1139               }
1140             }
1141             f = FieldSubfieldFree (f);
1142           }
1143         }
1144         sfp = sfp->next;
1145       }
1146     }
1147     sap = sap->next;
1148   }
1149   return found;
1150 }
1151 
DoFeaturesContainText_Callback(BioseqPtr bsp,ConvertFormPtr cfp)1152 static Boolean DoFeaturesContainText_Callback
1153 (BioseqPtr      bsp,
1154  ConvertFormPtr cfp)
1155 {
1156 
1157   SeqAnnotPtr    sap;
1158 
1159   /* Check parameters */
1160 
1161   if (bsp == NULL || cfp == NULL)
1162     return FALSE;
1163 
1164   /* Get the list of annotations */
1165 
1166   sap = bsp->annot;
1167 
1168   /* Search the requested item for the given string */
1169 
1170   return DoFeaturesInAnnotContainText (sap, cfp);
1171 }
1172 
1173 typedef struct objstringdata
1174 {
1175   CharPtr match;
1176   Boolean found;
1177 } ObjStringData, PNTR ObjStringPtr;
1178 
AsnWriteRemoveForDCallBack(AsnExpOptStructPtr pAEOS)1179 static void LIBCALLBACK AsnWriteRemoveForDCallBack (AsnExpOptStructPtr pAEOS)
1180 
1181 {
1182   CharPtr        pchFind;
1183   CharPtr        pchSource;
1184   ObjStringPtr   osp;
1185 
1186   osp = (ObjStringPtr) pAEOS->data;
1187   if (ISA_STRINGTYPE (AsnFindBaseIsa (pAEOS->atp))) {
1188 	pchSource = (CharPtr) pAEOS->dvp->ptrvalue;
1189 	pchFind = osp->match;
1190 	if (StringSearch (pchSource, pchFind) != NULL) {
1191 	  osp->found = TRUE;
1192 	}
1193   }
1194 }
1195 
ObjectHasSubstring(ObjMgrTypePtr omtp,AsnIoPtr aip,Pointer ptr,ObjStringPtr osp)1196 static Boolean ObjectHasSubstring (ObjMgrTypePtr omtp, AsnIoPtr aip, Pointer ptr, ObjStringPtr osp)
1197 
1198 {
1199   osp->found = FALSE;
1200   (omtp->asnwrite) (ptr, aip, NULL);
1201   return osp->found;
1202 }
1203 
GetPubStatus(PubdescPtr pdp)1204 static Uint1 GetPubStatus (PubdescPtr pdp)
1205 {
1206   ValNodePtr vnp;
1207   CitGenPtr  cgp;
1208   CitArtPtr  cap;
1209   CitJourPtr cjp;
1210   CitBookPtr cbp;
1211   CitSubPtr  csp;
1212   MedlineEntryPtr mlp;
1213   ImprintPtr ip = NULL;
1214   Uint1      status = 255; /* 255 is currently not a valid status */
1215 
1216   if (pdp == NULL) return status;
1217 
1218   for (vnp = pdp->pub; vnp != NULL && ip == NULL; vnp = vnp->next)
1219   {
1220   	switch (vnp->choice)
1221   	{
1222   	  case PUB_Gen:
1223         cgp = (CitGenPtr) vnp->data.ptrvalue;
1224   	    if (cgp != NULL && StringICmp (cgp->cit, "Unpublished"))
1225   	    {
1226   	  	  return PUB_STATUS_UNPUBLISHED;
1227   	    }
1228   	    break;
1229   	  case PUB_Article:
1230   	  case PUB_Medline:
1231   	    if (vnp->choice == PUB_Article)
1232   	    {
1233   	      cap = (CitArtPtr) vnp->data.ptrvalue;
1234   	    }
1235   	    else
1236   	    {
1237   	      cap = NULL;
1238   	      mlp = (MedlineEntryPtr) vnp->data.ptrvalue;
1239   	      if (mlp != NULL)
1240   	      {
1241   	        cap = mlp->cit;
1242   	      }
1243   	    }
1244   	    if (cap != NULL && cap->from == 1)
1245   	    {
1246   	      cjp = (CitJourPtr) cap->fromptr;
1247   	      if (cjp != NULL)
1248   	      {
1249   	      	ip = cjp->imp;
1250   	      }
1251   	    }
1252   	    break;
1253   	  case PUB_Man:
1254       case PUB_Book:
1255         cbp = (CitBookPtr) vnp->data.ptrvalue;
1256         if (cbp != NULL)
1257         {
1258           ip = cbp->imp;
1259         }
1260         break;
1261   	  case PUB_Sub:
1262   	    csp = (CitSubPtr) vnp->data.ptrvalue;
1263   	    if (csp != NULL)
1264   	    {
1265   	      ip = csp->imp;
1266   	    }
1267   	    break;
1268   	}
1269   }
1270   if (ip != NULL)
1271   {
1272   	status = ip->prepub;
1273   }
1274   return status;
1275 }
1276 
DoesPubStatusMatch(PubdescPtr pdp,ConvertFormPtr cfp)1277 static Boolean DoesPubStatusMatch (PubdescPtr pdp, ConvertFormPtr cfp)
1278 {
1279   Uint1 pub_status;
1280 
1281   if (pdp == NULL || cfp == NULL) return FALSE;
1282   if (cfp->subtype == 0) return TRUE;
1283 
1284   pub_status = GetPubStatus (pdp);
1285 
1286   if (cfp->subtype == PUBLICATION_PUBLISHED_FIELD
1287       && pub_status == PUB_STATUS_PUBLISHED)
1288   {
1289   	return TRUE;
1290   }
1291   else if (cfp->subtype == PUBLICATION_INPRESS_FIELD
1292       && pub_status == PUB_STATUS_IN_PRESS)
1293   {
1294   	return TRUE;
1295   }
1296   else if (cfp->subtype == PUBLICATION_UNPUB_FIELD
1297       && pub_status == PUB_STATUS_UNPUBLISHED)
1298   {
1299   	return TRUE;
1300   }
1301   else
1302   {
1303   	return FALSE;
1304   }
1305 }
1306 
DoesSequenceHavePubWithText(BioseqPtr bsp,ConvertFormPtr cfp)1307 static Boolean DoesSequenceHavePubWithText (BioseqPtr bsp, ConvertFormPtr cfp)
1308 {
1309   AsnExpOptPtr      aeop;
1310   AsnIoPtr          aip;
1311   ObjStringData     osd;
1312   SeqMgrDescContext dcontext;
1313   SeqDescrPtr       sdp;
1314   SeqMgrFeatContext fcontext;
1315   SeqFeatPtr        sfp;
1316   Boolean           rval = FALSE;
1317   ObjMgrPtr         omp;
1318   ObjMgrTypePtr     omtp;
1319   PubdescPtr        pdp;
1320 
1321   if (bsp == NULL || cfp == NULL) return FALSE;
1322   omp = ObjMgrGet ();
1323   if (omp == NULL) return FALSE;
1324   omtp = ObjMgrTypeFind (omp, OBJ_SEQDESC, NULL, NULL);
1325   if (omtp == NULL) return FALSE;
1326 
1327   aip = AsnIoNullOpen ();
1328   aeop = AsnExpOptNew (aip, NULL, NULL, AsnWriteRemoveForDCallBack);
1329   if (aeop != NULL) {
1330     aeop->user_data = (Pointer) &osd;
1331   }
1332   osd.match = cfp->deleteStr;
1333 
1334   /* look for publication descriptors */
1335   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_pub, &dcontext);
1336   while (sdp != NULL && !rval) {
1337     if (ObjectHasSubstring (omtp, aip, (Pointer) sdp, &osd)) {
1338       pdp = (PubdescPtr) sdp->data.ptrvalue;
1339       if (DoesPubStatusMatch (pdp, cfp))
1340       {
1341         rval = TRUE;
1342       }
1343     }
1344     sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_pub, &dcontext);
1345   }
1346 
1347   if (!rval)
1348   {
1349     omtp = ObjMgrTypeFind (omp, OBJ_SEQFEAT, NULL, NULL);
1350     if (omtp != NULL)
1351     {
1352       /* look for publication features */
1353       sfp = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_PUB, &fcontext);
1354       while (sfp != NULL && !rval)
1355       {
1356         if (ObjectHasSubstring (omtp, aip, (Pointer) sfp, &osd))
1357         {
1358           pdp = (PubdescPtr) sfp->data.value.ptrvalue;
1359           if (DoesPubStatusMatch (pdp, cfp))
1360           {
1361             rval = TRUE;
1362           }
1363         }
1364         sfp = SeqMgrGetNextFeature (bsp, sfp, 0, FEATDEF_PUB, &fcontext);
1365       }
1366     }
1367   }
1368 
1369   AsnIoClose (aip);
1370   return rval;
1371 }
1372 
DoesNucProtSetHavePubWithText(BioseqSetPtr bssp,ConvertFormPtr cfp)1373 static Boolean DoesNucProtSetHavePubWithText (BioseqSetPtr bssp, ConvertFormPtr cfp)
1374 {
1375   AsnExpOptPtr      aeop;
1376   AsnIoPtr          aip;
1377   ObjStringData     osd;
1378   SeqDescrPtr       sdp;
1379   Boolean           rval = FALSE;
1380   ObjMgrPtr         omp;
1381   ObjMgrTypePtr     omtp;
1382   PubdescPtr        pdp;
1383 
1384   if (bssp == NULL || cfp == NULL) return FALSE;
1385   omp = ObjMgrGet ();
1386   if (omp == NULL) return FALSE;
1387   omtp = ObjMgrTypeFind (omp, OBJ_SEQDESC, NULL, NULL);
1388   if (omtp == NULL) return FALSE;
1389 
1390   aip = AsnIoNullOpen ();
1391   aeop = AsnExpOptNew (aip, NULL, NULL, AsnWriteRemoveForDCallBack);
1392   if (aeop != NULL) {
1393     aeop->user_data = (Pointer) &osd;
1394   }
1395   osd.match = cfp->deleteStr;
1396 
1397   /* look for publication descriptors */
1398   sdp = bssp->descr;
1399   while (sdp != NULL && !rval) {
1400     if (sdp->choice == Seq_descr_pub && ObjectHasSubstring (omtp, aip, (Pointer) sdp, &osd)) {
1401       pdp = (PubdescPtr) sdp->data.ptrvalue;
1402       if (DoesPubStatusMatch (pdp, cfp))
1403       {
1404         rval = TRUE;
1405       }
1406     }
1407     sdp = sdp->next;
1408   }
1409 
1410   AsnIoClose (aip);
1411   return rval;
1412 }
1413 
DoesSimpleDescriptorForSequenceContainText(BioseqPtr bsp,CharPtr checkStr,Uint1 desc_choice)1414 static Boolean DoesSimpleDescriptorForSequenceContainText (BioseqPtr bsp, CharPtr checkStr, Uint1 desc_choice)
1415 {
1416   SeqMgrDescContext dcontext;
1417   SeqDescrPtr       sdp;
1418   Boolean           found = FALSE;
1419 
1420   for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, desc_choice, &dcontext);
1421        sdp != NULL && !found;
1422        sdp = SeqMgrGetNextDescriptor (bsp, sdp, desc_choice, &dcontext))
1423   {
1424     found = CheckForString (checkStr, sdp->data.ptrvalue);
1425   }
1426   return found;
1427 }
1428 
1429 
DoesSequenceContainText(BioseqPtr bsp,Pointer userdata)1430 static Boolean LIBCALLBACK DoesSequenceContainText (BioseqPtr bsp, Pointer userdata)
1431 {
1432   BioSourcePtr biop;
1433   ConvertFormPtr cfp;
1434   Boolean      found = FALSE;
1435   SeqDescrPtr       sdp;
1436   SeqMgrDescContext descContext;
1437 
1438   cfp = (ConvertFormPtr) userdata;
1439   if (bsp == NULL || cfp == NULL) return FALSE;
1440 
1441   switch (cfp->type) {
1442     case eFieldTypeGene :
1443     case eFieldTypeCDS :
1444     case eFieldTypeProtein :
1445     case eFieldTypeRNA :
1446     case eFieldTypeImport :
1447     case eFieldTypeFeatureNote :
1448       found = DoFeaturesContainText_Callback (bsp, cfp);
1449       break;
1450     case eFieldTypeBioSource :
1451     case eFieldTypeOrgModSubSource :
1452       sdp = SeqMgrGetNextDescriptor (bsp, NULL, 0, &descContext);
1453       while (NULL != sdp && ! found) {
1454         if (Seq_descr_source == sdp->choice
1455             && (biop = sdp->data.ptrvalue) != NULL) {
1456           if (cfp->type == eFieldTypeBioSource) {
1457             found = DoesBioSourceContainText (biop, cfp);
1458           } else if (cfp->type == eFieldTypeOrgModSubSource) {
1459             found = DoSubSourcesContainText (biop, cfp);
1460           }
1461         }
1462         sdp = SeqMgrGetNextDescriptor (bsp, sdp, 0, &descContext);
1463       }
1464       break;
1465     case eFieldTypeDefline :
1466       found = DoesSimpleDescriptorForSequenceContainText (bsp, cfp->deleteStr, Seq_descr_title);
1467       break;
1468     case eFieldTypeCommentDescriptor:
1469       found = DoesSimpleDescriptorForSequenceContainText (bsp, cfp->deleteStr, Seq_descr_comment);
1470       break;
1471   	case eFieldTypePublication :
1472   	  found = DoesSequenceHavePubWithText (bsp, cfp);
1473   	  break;
1474     default:
1475       break;
1476   }
1477   return found;
1478 }
1479 
DoesNucProtSetContainText(BioseqSetPtr bssp,Pointer userdata)1480 static Boolean LIBCALLBACK  DoesNucProtSetContainText (BioseqSetPtr bssp, Pointer userdata)
1481 {
1482   SeqEntryPtr sep;
1483   BioseqPtr   bsp;
1484   ConvertFormPtr cfp;
1485 
1486   if (bssp == NULL) return FALSE;
1487   cfp = (ConvertFormPtr) userdata;
1488   if (cfp == NULL) return FALSE;
1489   if (cfp->type == eFieldTypePublication && DoesNucProtSetHavePubWithText (bssp, cfp))
1490   {
1491   	return TRUE;
1492   }
1493   if (DoFeaturesInAnnotContainText (bssp->annot, cfp))
1494   {
1495   	return TRUE;
1496   }
1497 
1498   for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
1499     if (IS_Bioseq (sep)) {
1500       bsp = (BioseqPtr) sep->data.ptrvalue;
1501       if (DoesSequenceContainText (bsp, (Pointer)cfp)) {
1502         return TRUE;
1503       }
1504     }
1505   }
1506   return FALSE;
1507 }
1508 
SegregateItemsByText(SeqEntryPtr seqlist,ConvertFormPtr cfp,BioseqSetPtr set1,BioseqSetPtr set2)1509 static void SegregateItemsByText
1510 (SeqEntryPtr                     seqlist,
1511  ConvertFormPtr                  cfp,
1512  BioseqSetPtr                    set1,
1513  BioseqSetPtr                    set2)
1514 {
1515   SegregateItemsRecursor (seqlist, set1, set2,
1516                   DoesNucProtSetContainText,
1517                   DoesSequenceContainText, (Pointer)cfp);
1518 }
1519 
1520 typedef void (LIBCALLBACK *segregateFunction) (
1521   SeqEntryPtr  seqlist,
1522   Pointer      userdata,
1523   BioseqSetPtr set1,
1524   BioseqSetPtr set2
1525 );
1526 
1527 
CreateSetsForSegregate(BioseqSetPtr bssp,BioseqSetPtr PNTR pNewSet1,BioseqSetPtr PNTR pNewSet2)1528 static void CreateSetsForSegregate (BioseqSetPtr bssp, BioseqSetPtr PNTR pNewSet1, BioseqSetPtr PNTR pNewSet2)
1529 {
1530   BioseqSetPtr parent_set;
1531   SeqEntryPtr  tmp1, tmp2, last_sep;
1532   BioseqSetPtr newset1, newset2;
1533 
1534   if (bssp == NULL || pNewSet1 == NULL || pNewSet2 == NULL) return;
1535 
1536   parent_set = (BioseqSetPtr)(bssp->idx.parentptr);
1537 
1538   if (parent_set == NULL || parent_set->seq_set == NULL) {
1539     /* this set has no parent, so make it the parent set, class GenBank,
1540      * and create two new sets using the original set class as members of this set
1541      */
1542     newset1 = BioseqSetNew ();
1543     if (newset1 == NULL) return;
1544     newset2 = BioseqSetNew ();
1545     if (newset2 == NULL) return;
1546     newset1->_class = bssp->_class;
1547     newset2->_class = bssp->_class;
1548     tmp1 = SeqEntryNew ();
1549     if (tmp1 == NULL) return;
1550     tmp1->choice = 2;
1551     tmp1->data.ptrvalue = (Pointer) newset1;
1552     tmp2 = SeqEntryNew ();
1553     if (tmp2 == NULL) return;
1554     tmp2->choice = 2;
1555     tmp2->data.ptrvalue = (Pointer) newset2;
1556     bssp->seq_set = tmp1;
1557     tmp1->next = tmp2;
1558     bssp->_class = BioseqseqSet_class_genbank;
1559     /* Propagate descriptors down */
1560     ValNodeLink (&(newset1->descr),
1561                  AsnIoMemCopy ((Pointer) bssp->descr,
1562                                (AsnReadFunc) SeqDescrAsnRead,
1563                                (AsnWriteFunc) SeqDescrAsnWrite));
1564     ValNodeLink (&(newset2->descr),
1565                  AsnIoMemCopy ((Pointer) bssp->descr,
1566                                (AsnReadFunc) SeqDescrAsnRead,
1567                                (AsnWriteFunc) SeqDescrAsnWrite));
1568     bssp->descr = SeqDescrFree (bssp->descr);
1569   } else {
1570     last_sep = parent_set->seq_set;
1571     newset1 = bssp;
1572     newset2 = BioseqSetNew ();
1573     if (newset2 == NULL) return;
1574     newset2->_class = newset1->_class;
1575     tmp1 = SeqEntryNew ();
1576     if (tmp1 == NULL) return;
1577     tmp1->choice = 2;
1578     tmp1->data.ptrvalue = (Pointer) newset2;
1579     while (last_sep != NULL && last_sep->next != NULL) {
1580       last_sep = last_sep->next;
1581     }
1582     if (last_sep == NULL) return;
1583     last_sep->next = tmp1;
1584     /* copy descriptors horizontally */
1585     ValNodeLink (&(newset2->descr),
1586                  AsnIoMemCopy ((Pointer) bssp->descr,
1587                                (AsnReadFunc) SeqDescrAsnRead,
1588                                (AsnWriteFunc) SeqDescrAsnWrite));
1589   }
1590   *pNewSet1 = newset1;
1591   *pNewSet2 = newset2;
1592 }
1593 
1594 
SegregateItemsGenericCallback(SeqEntryPtr sep,BioseqSetPtr bssp,Uint2 entityID,Pointer userdata,segregateFunction seg_func)1595 static void SegregateItemsGenericCallback
1596 (SeqEntryPtr       sep,
1597  BioseqSetPtr      bssp,
1598  Uint2             entityID,
1599  Pointer           userdata,
1600  segregateFunction seg_func)
1601 {
1602   ObjMgrDataPtr     omdptop;
1603   ObjMgrData        omdata;
1604   BioseqSetPtr      newset1;
1605   BioseqSetPtr      newset2;
1606   Uint2             parenttype;
1607   Pointer           parentptr;
1608   SeqEntryPtr       seqlist;
1609 
1610   if (sep == NULL || seg_func == NULL) return;
1611   /* Display the 'working' cursor */
1612 
1613   WatchCursor ();
1614   Update ();
1615 
1616 
1617   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
1618   GetSeqEntryParent (sep, &parentptr, &parenttype);
1619 
1620   seqlist = bssp->seq_set;
1621   bssp->seq_set = NULL;
1622 
1623   CreateSetsForSegregate (bssp, &newset1, &newset2);
1624 
1625   /* Do the search and move sequences */
1626   (*seg_func)(seqlist, userdata, newset1, newset2);
1627 
1628   /* Remove the window and update things */
1629   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
1630   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata);
1631   ObjMgrSetDirtyFlag (entityID, TRUE);
1632   ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
1633 
1634   ArrowCursor ();
1635   Update ();
1636 
1637   /* Return successfully */
1638   return;
1639 
1640 }
1641 
1642 
OkToSegregate(OMProcControlPtr ompcp)1643 static Boolean OkToSegregate (OMProcControlPtr ompcp)
1644 {
1645   if (ompcp == NULL
1646       || ompcp->input_itemtype != OBJ_BIOSEQSET
1647       || ompcp->input_data == NULL) {
1648     Message (MSG_ERROR, "You must select a set to segregate!");
1649     return FALSE;
1650   } else {
1651     return TRUE;
1652   }
1653 }
1654 
1655 
1656 /*=========================================================================*/
1657 /*                                                                         */
1658 /* SegregateByText_Callback () - Finds and deletes all items of a selected */
1659 /*                            type that contain a given text phrase.       */
1660 /*                                                                         */
1661 /*=========================================================================*/
1662 
SegregateByText_Callback(ButtoN b)1663 static void SegregateByText_Callback (ButtoN b)
1664 {
1665   ConvertFormPtr    cfp;
1666   SeqEntryPtr       sep;
1667   BioseqSetPtr      bssp;
1668   SeqEntryPtr       seqlist;
1669   BioseqSetPtr      newset1, newset2;
1670   ObjMgrDataPtr     omdptop;
1671   ObjMgrData        omdata;
1672   Uint2             parenttype;
1673   Pointer           parentptr;
1674   Boolean           leaveDlgUp = FALSE;
1675   FieldSubfieldPtr  f;
1676 
1677   /* Check the initial conditions and get the sequence */
1678   cfp = (ConvertFormPtr) GetObjectExtra (b);
1679   if (cfp == NULL) {
1680     return;
1681   }
1682   if (cfp->input_entityID == 0 || cfp->target_set == NULL) {
1683     Remove (cfp->form);
1684     return;
1685   }
1686 
1687   sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
1688   if (sep == NULL) {
1689     Remove (cfp->form);
1690     return;
1691   }
1692 
1693   if (GetStatus (cfp->leaveDlgUp))
1694   {
1695   	leaveDlgUp = TRUE;
1696   }
1697 
1698   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
1699   GetSeqEntryParent (sep, &parentptr, &parenttype);
1700 
1701   bssp = cfp->target_set;
1702   seqlist = bssp->seq_set;
1703   bssp->seq_set = NULL;
1704 
1705   CreateSetsForSegregate (bssp, &newset1, &newset2);
1706 
1707   /* Get the string to search for */
1708 
1709   cfp->deleteStr = SaveStringFromTextNoStripSpaces (cfp->deleteText);
1710   if (StringHasNoText (cfp->deleteStr)){
1711     if (!leaveDlgUp)
1712     {
1713       Remove (cfp->form);
1714     }
1715     return;
1716   }
1717 
1718   /* Get the type of items to search */
1719   f = DialogToPointer (cfp->target_dlg);
1720   if (f == NULL || f->field < 0 || (f->subfield < 0 && f->subfield_list == NULL)) {
1721     f = FieldSubfieldFree (f);
1722     if (!leaveDlgUp)
1723     {
1724       Remove (cfp->form);
1725     }
1726     return;
1727   }
1728 
1729   cfp->type = f->field;
1730   cfp->subtype = f->subfield;
1731   f = FieldSubfieldFree (f);
1732 
1733   /* Display the 'working' cursor */
1734 
1735   WatchCursor ();
1736   Update ();
1737 
1738   /* Do the search and move sequences */
1739   SegregateItemsByText (seqlist, cfp, newset1, newset2);
1740 
1741   /* Remove the window and update things */
1742   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
1743   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata);
1744   ObjMgrSetDirtyFlag (cfp->input_entityID, TRUE);
1745   ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID, 0, 0);
1746 
1747   ArrowCursor ();
1748   Update ();
1749   if (!leaveDlgUp)
1750   {
1751     Remove (cfp->form);
1752   }
1753 
1754   /* Return successfully */
1755   return;
1756 }
1757 
1758 
1759 
1760 
1761 /*-------------------------------------------------------------------------*/
1762 /*                                                                         */
1763 /* SetSegregateAcceptButton () -- Enable/Disable the Accept button depending  */
1764 /*                             on the condition of other window objects.   */
1765 /*                                                                         */
1766 /*-------------------------------------------------------------------------*/
1767 
SetSegregateAcceptButton(Pointer data)1768 static void SetSegregateAcceptButton (Pointer data)
1769 
1770 {
1771   ConvertFormPtr  cfp;
1772   FieldSubfieldPtr f;
1773 
1774   cfp = (ConvertFormPtr) data;
1775   if (cfp == NULL)
1776     return;
1777 
1778   /* Disable if a target has not been selected */
1779   f = DialogToPointer (cfp->target_dlg);
1780   if (f == NULL || f->field < 0 || (f->subfield < 0 && f->subfield_list == NULL)) {
1781     SafeDisable (cfp->accept);
1782     f = FieldSubfieldFree (f);
1783     return;
1784   }
1785   f = FieldSubfieldFree (f);
1786 
1787   if (cfp->deleteText != NULL) {
1788     /* Disable if there is no delete string */
1789     if (TextHasNoText (cfp->deleteText)) {
1790       SafeDisable (cfp->accept);
1791       return;
1792     }
1793   }
1794 
1795   /* If we made it to here, then we passed all */
1796   /* test and can enable the accept button.    */
1797 
1798   SafeEnable (cfp->accept);
1799 }
1800 
CleanupSegregatePage(GraphiC g,VoidPtr data)1801 static void CleanupSegregatePage (GraphiC g, VoidPtr data)
1802 
1803 {
1804   ConvertFormPtr  cfp;
1805 
1806   cfp = (ConvertFormPtr) data;
1807   if (cfp != NULL) {
1808   }
1809   StdCleanupFormProc (g, data);
1810 }
1811 
1812 /*=========================================================================*/
1813 /*                                                                         */
1814 /* CreateSegregateByTextWindow () - Creates and then displays the window   */
1815 /*                        for getting segregate by text info from the user.*/
1816 /*                                                                         */
1817 /*=========================================================================*/
1818 
CreateSegregateByTextWindow(Pointer data)1819 extern Int2 LIBCALLBACK CreateSegregateByTextWindow (Pointer data)
1820 {
1821   Boolean            allowed[eFieldType_Max];
1822   GrouP              c;
1823   ConvertFormPtr     cfp;
1824   GrouP              g;
1825   GrouP              h;
1826   OMProcControlPtr   ompcp;
1827   GrouP              p;
1828   StdEditorProcsPtr  sepp;
1829   WindoW             w;
1830 
1831   /* Check parameters and get a pointer to the current data */
1832 
1833   ompcp = (OMProcControlPtr) data;
1834   if (!OkToSegregate(ompcp)) {
1835     return OM_MSG_RET_ERROR;
1836   }
1837 
1838   /* Create a new window, and a struct */
1839   /* to pass around the data in.       */
1840 
1841   cfp = ConvertFormNew ();
1842   if (cfp == NULL)
1843     return OM_MSG_RET_ERROR;
1844   cfp->target_set = (BioseqSetPtr)ompcp->input_data;
1845   cfp->set_accept_proc = SetSegregateAcceptButton;
1846 
1847   w = FixedWindow (-50, -33, -10, -10, "Segregate By Text String",
1848 		   StdCloseWindowProc);
1849   SetObjectExtra (w, cfp, CleanupSegregatePage);
1850   cfp->form = (ForM) w;
1851 
1852   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
1853   if (sepp != NULL) {
1854     SetActivate (w, sepp->activateForm);
1855     cfp->appmessage = sepp->handleMessages;
1856   }
1857 
1858   cfp->input_entityID = ompcp->input_entityID;
1859   cfp->input_itemID = ompcp->input_itemID;
1860   cfp->input_itemtype = ompcp->input_itemtype;
1861 
1862   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
1863   if (sepp != NULL) {
1864     SetActivate (w, sepp->activateForm);
1865     cfp->appmessage = sepp->handleMessages;
1866   }
1867 
1868   /* Add the popup lists */
1869 
1870   h = HiddenGroup (w, -1, 0, NULL);
1871   SetGroupSpacing (h, 10, 10);
1872 
1873   g = HiddenGroup (h, 3, 0, NULL);
1874 
1875   StaticPrompt (g, "Segregate sequences with the string", 0, dialogTextHeight,
1876 		programFont, 'l');
1877   cfp->deleteText = DialogText (g, "", 10, ConvertFormTextCallback);
1878   SetObjectExtra (cfp->deleteText, cfp, NULL);
1879 
1880   p = HiddenGroup (h, 6, 0, NULL);
1881   StaticPrompt (p, "Find string in", 0, popupMenuHeight, programFont, 'l');
1882   MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
1883   allowed[eFieldTypeCommentDescriptor] = TRUE;
1884 
1885   cfp->target_dlg = CreateFieldSubfieldDlg (p, allowed, ChangeTargetFields, cfp);
1886 
1887   /* Add Accept and Cancel buttons */
1888 
1889   c = HiddenGroup (h, 4, 0, NULL);
1890   cfp->accept = DefaultButton (c, "Accept", SegregateByText_Callback);
1891   SetObjectExtra (cfp->accept, cfp, NULL);
1892   Disable (cfp->accept);
1893   PushButton (c, "Cancel", StdCancelButtonProc);
1894   cfp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
1895 
1896   /* Line things up nicely */
1897 
1898   AlignObjects (ALIGN_LEFT, (HANDLE) p, (HANDLE) c, (HANDLE) h, NULL);
1899 
1900   /* Display the window now */
1901 
1902   RealizeWindow (w);
1903   Show (w);
1904   Select (w);
1905   Select (cfp->accept);
1906   Update ();
1907   return OM_MSG_RET_OK;
1908 }
1909 
1910 
1911 typedef struct segregatefeatdata {
1912   FEATURE_FORM_BLOCK
1913 
1914   PopuP        type_popup;
1915   ValNodePtr   type_list;
1916   ButtoN       accept;
1917 
1918   BioseqSetPtr target_set;
1919   Uint2        segregate_type;
1920   Boolean      is_feat;
1921 } SegregateFeatData, PNTR SegregateFeatPtr;
1922 
DoesSequenceContainFeatureType(BioseqPtr bsp,Pointer userdata)1923 static Boolean LIBCALLBACK DoesSequenceContainFeatureType (BioseqPtr bsp, Pointer userdata)
1924 {
1925   SeqMgrFeatContext context;
1926   SeqFeatPtr        feat;
1927   SegregateFeatPtr  sfp;
1928 
1929   sfp = (SegregateFeatPtr) userdata;
1930   if (sfp == NULL || bsp == NULL) return FALSE;
1931 
1932   feat = NULL;
1933   while ((feat = SeqMgrGetNextFeature (bsp, feat, 0, 0, &context)) != NULL)
1934   {
1935   	if (feat->idx.subtype == sfp->segregate_type)
1936   	{
1937   	  return TRUE;
1938   	}
1939   }
1940   return FALSE;
1941 }
1942 
DoesNucProtSetContainFeatureType(BioseqSetPtr bssp,Pointer userdata)1943 static Boolean LIBCALLBACK DoesNucProtSetContainFeatureType (BioseqSetPtr bssp, Pointer userdata)
1944 {
1945   SeqEntryPtr sep;
1946   BioseqPtr   bsp;
1947   SegregateFeatPtr  sfp;
1948 
1949   sfp = (SegregateFeatPtr) userdata;
1950   if (sfp == NULL || bssp == NULL) return FALSE;
1951 
1952   for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
1953     if (IS_Bioseq (sep)) {
1954       bsp = (BioseqPtr) sep->data.ptrvalue;
1955       if (DoesSequenceContainFeatureType (bsp, sfp)) {
1956         return TRUE;
1957       }
1958     }
1959   }
1960   return FALSE;
1961 }
1962 
DoesSequenceContainDescriptorType(BioseqPtr bsp,Pointer userdata)1963 static Boolean LIBCALLBACK DoesSequenceContainDescriptorType (BioseqPtr bsp, Pointer userdata)
1964 {
1965   SeqMgrDescContext context;
1966   SeqDescPtr        desc;
1967   SegregateFeatPtr  sfp;
1968 
1969   sfp = (SegregateFeatPtr) userdata;
1970   if (sfp == NULL || bsp == NULL) return FALSE;
1971 
1972   if((desc = SeqMgrGetNextDescriptor (bsp, NULL, sfp->segregate_type, &context)) != NULL)
1973   {
1974 	return TRUE;
1975   }
1976   return FALSE;
1977 }
1978 
1979 typedef struct checkdescdata {
1980   Uint2   segregate_type;
1981   Boolean found;
1982 } CheckDescData, PNTR CheckDescPtr;
1983 
DoesSetContainDescriptorType_Callback(SeqDescPtr sdp,Pointer userdata)1984 static void DoesSetContainDescriptorType_Callback (SeqDescPtr sdp, Pointer userdata)
1985 {
1986   CheckDescPtr p;
1987 
1988   if (sdp == NULL || userdata == NULL) return;
1989   p = (CheckDescPtr) userdata;
1990   if (p->found) return;
1991   if (sdp->choice == p->segregate_type) p->found = TRUE;
1992 }
1993 
DoesNucProtSetContainDescriptorType(BioseqSetPtr bssp,Pointer userdata)1994 static Boolean LIBCALLBACK DoesNucProtSetContainDescriptorType (BioseqSetPtr bssp, Pointer userdata)
1995 {
1996   CheckDescData d;
1997   SegregateFeatPtr  sfp;
1998 
1999   sfp = (SegregateFeatPtr) userdata;
2000   if (sfp == NULL || bssp == NULL) return FALSE;
2001 
2002   d.found = FALSE;
2003   d.segregate_type = sfp->segregate_type;
2004   VisitDescriptorsInSet (bssp, &d, DoesSetContainDescriptorType_Callback);
2005   return d.found;
2006 }
2007 
2008 /*=========================================================================*/
2009 /*                                                                         */
2010 /* SegregateItemsByFeature () - Given a feature type, move bioseqs         */
2011 /*                        containing those features to a new popset.       */
2012 /*                                                                         */
2013 /*=========================================================================*/
2014 
SegregateItemsByFeatureOrDescriptor(SeqEntryPtr seqlist,SegregateFeatPtr sfp,BioseqSetPtr set1,BioseqSetPtr set2)2015 static void SegregateItemsByFeatureOrDescriptor
2016 (SeqEntryPtr      seqlist,
2017  SegregateFeatPtr sfp,
2018  BioseqSetPtr     set1,
2019  BioseqSetPtr     set2)
2020 {
2021 
2022 
2023   if (sfp == NULL || set1 == NULL || set2 == NULL || seqlist == NULL)
2024     return;
2025 
2026   if (sfp->is_feat)
2027   {
2028   	SegregateItemsRecursor (seqlist, set1, set2,
2029   	                               DoesNucProtSetContainFeatureType,
2030   	                               DoesSequenceContainFeatureType,
2031   	                               (Pointer) sfp);
2032   }
2033   else
2034   {
2035   	SegregateItemsRecursor (seqlist, set1, set2,
2036   	                               DoesNucProtSetContainDescriptorType,
2037   	                               DoesSequenceContainDescriptorType,
2038   	                               (Pointer) sfp);
2039   }
2040 
2041 }
2042 
2043 
2044 /*=========================================================================*/
2045 /*                                                                         */
2046 /* SegregateByFeatureOrDescriptor_Callback () - Segregates sequences that  */
2047 /*                            contain a selected feature.                  */
2048 /*                                                                         */
2049 /*=========================================================================*/
2050 
SegregateByFeatureOrDescriptor_Callback(ButtoN b)2051 static void SegregateByFeatureOrDescriptor_Callback (ButtoN b)
2052 {
2053   SegregateFeatPtr  sfp;
2054   SeqEntryPtr       sep;
2055   UIEnum            val;
2056   BioseqSetPtr      bssp;
2057   SeqEntryPtr       seqlist;
2058   BioseqSetPtr      newset1, newset2;
2059   ObjMgrDataPtr     omdptop;
2060   ObjMgrData        omdata;
2061   Uint2             parenttype;
2062   Pointer           parentptr;
2063   ValNodePtr        vnp;
2064 
2065   /* Check the initial conditions and get the sequence */
2066   sfp = (SegregateFeatPtr) GetObjectExtra (b);
2067   if (sfp == NULL) {
2068     return;
2069   }
2070   if (sfp->input_entityID == 0 || sfp->target_set == NULL) {
2071     Remove (sfp->form);
2072     return;
2073   }
2074 
2075   sep = GetTopSeqEntryForEntityID (sfp->input_entityID);
2076   if (sep == NULL) {
2077     Remove (sfp->form);
2078     return;
2079   }
2080 
2081   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
2082   GetSeqEntryParent (sep, &parentptr, &parenttype);
2083 
2084   bssp = sfp->target_set;
2085   seqlist = bssp->seq_set;
2086   bssp->seq_set = NULL;
2087 
2088   CreateSetsForSegregate (bssp, &newset1, &newset2);
2089 
2090   /* Get the feature to look for */
2091   val = GetValue (sfp->type_popup);
2092   for (vnp = sfp->type_list; vnp != NULL && val > 1; vnp = vnp->next, val--)
2093   {
2094   }
2095   if (vnp == NULL || val != 1)
2096   {
2097     Remove (sfp->form);
2098     return;
2099   }
2100   sfp->segregate_type = vnp->choice;
2101 
2102   /* Display the 'working' cursor */
2103 
2104   WatchCursor ();
2105   Update ();
2106 
2107   /* Do the search and move sequences */
2108   SegregateItemsByFeatureOrDescriptor (seqlist, sfp, newset1, newset2);
2109 
2110   /* Remove the window and update things */
2111   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
2112   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata);
2113   ObjMgrSetDirtyFlag (sfp->input_entityID, TRUE);
2114   ObjMgrSendMsg (OM_MSG_UPDATE, sfp->input_entityID, 0, 0);
2115 
2116   ArrowCursor ();
2117   Update ();
2118   Remove (sfp->form);
2119 
2120   /* Return successfully */
2121   return;
2122 }
2123 
2124 
2125 /*=========================================================================*/
2126 /*                                                                         */
2127 /* CreateSegregateByFeatureWindow () - Creates and then displays the window*/
2128 /*                        for getting segregate by text info from the user.*/
2129 /*                                                                         */
2130 /*=========================================================================*/
2131 
CreateSegregateByFeatureOrDescriptorWindow(Pointer data,Boolean is_feat)2132 static Int2 LIBCALLBACK CreateSegregateByFeatureOrDescriptorWindow (Pointer data, Boolean is_feat)
2133 {
2134   GrouP              c;
2135   SegregateFeatPtr   sfp;
2136   GrouP              g;
2137   GrouP              h;
2138   OMProcControlPtr   ompcp;
2139   StdEditorProcsPtr  sepp;
2140   WindoW             w;
2141   ValNodePtr         vnp;
2142 
2143   /* Check parameters and get a pointer to the current data */
2144 
2145   ompcp = (OMProcControlPtr) data;
2146   if (!OkToSegregate(ompcp)) {
2147     return OM_MSG_RET_ERROR;
2148   }
2149 
2150   /* Create a new window, and a struct */
2151   /* to pass around the data in.       */
2152 
2153   sfp = (SegregateFeatPtr) MemNew (sizeof (SegregateFeatData));
2154   if (sfp == NULL)
2155     return OM_MSG_RET_ERROR;
2156   sfp->is_feat = is_feat;
2157 
2158   if (sfp->is_feat)
2159   {
2160     w = FixedWindow (-50, -33, -10, -10, "Segregate By Feature",
2161 	                 StdCloseWindowProc);
2162   }
2163   else
2164   {
2165     w = FixedWindow (-50, -33, -10, -10, "Segregate By Descriptor",
2166 	                 StdCloseWindowProc);
2167   }
2168 
2169   SetObjectExtra (w, sfp, StdCleanupFormProc);
2170   sfp->form = (ForM) w;
2171 
2172   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2173   if (sepp != NULL) {
2174     SetActivate (w, sepp->activateForm);
2175     sfp->appmessage = sepp->handleMessages;
2176   }
2177 
2178   sfp->input_entityID = ompcp->input_entityID;
2179   sfp->input_itemID = ompcp->input_itemID;
2180   sfp->input_itemtype = ompcp->input_itemtype;
2181   sfp->target_set = (BioseqSetPtr)ompcp->input_data;
2182 
2183   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2184   if (sepp != NULL) {
2185     SetActivate (w, sepp->activateForm);
2186     sfp->appmessage = sepp->handleMessages;
2187   }
2188 
2189   /* Add the popup lists */
2190 
2191   h = HiddenGroup (w, -1, 0, NULL);
2192   SetGroupSpacing (h, 10, 10);
2193 
2194   g = HiddenGroup (h, 3, 0, NULL);
2195 
2196   if (sfp->is_feat)
2197   {
2198     StaticPrompt (g, "Segregate sequences with the feature", 0, dialogTextHeight,
2199 	              programFont, 'l');
2200     sfp->type_list = BuildFeatureValNodeList (TRUE, NULL, 0, TRUE, FALSE);
2201   }
2202   else
2203   {
2204     StaticPrompt (g, "Segregate sequences with the descriptor", 0, dialogTextHeight,
2205 	              programFont, 'l');
2206 	sfp->type_list = BuildDescriptorValNodeList ();
2207   }
2208 
2209   sfp->type_popup = PopupList (g, TRUE, NULL);
2210   SetObjectExtra (sfp->type_popup, sfp, NULL);
2211   for (vnp = sfp->type_list; vnp != NULL; vnp = vnp->next)
2212   {
2213     PopupItem (sfp->type_popup, (CharPtr) vnp->data.ptrvalue);
2214   }
2215   SetValue (sfp->type_popup, 1);
2216 
2217   /* Add Accept and Cancel buttons */
2218 
2219   c = HiddenGroup (h, 4, 0, NULL);
2220   sfp->accept = DefaultButton (c, "Accept", SegregateByFeatureOrDescriptor_Callback);
2221   SetObjectExtra (sfp->accept, sfp, NULL);
2222   PushButton (c, "Cancel", StdCancelButtonProc);
2223 
2224   /* Line things up nicely */
2225 
2226   AlignObjects (ALIGN_LEFT, (HANDLE) g, (HANDLE) c, (HANDLE) h, NULL);
2227 
2228   /* Display the window now */
2229 
2230   RealizeWindow (w);
2231   Show (w);
2232   Select (w);
2233   Select (sfp->accept);
2234   Update ();
2235   return OM_MSG_RET_OK;
2236 }
2237 
CreateSegregateByFeatureWindow(Pointer data)2238 extern Int2 LIBCALLBACK CreateSegregateByFeatureWindow (Pointer data)
2239 {
2240   return CreateSegregateByFeatureOrDescriptorWindow (data, TRUE);
2241 }
2242 
CreateSegregateByDescriptorWindow(Pointer data)2243 extern Int2 LIBCALLBACK CreateSegregateByDescriptorWindow (Pointer data)
2244 {
2245   return CreateSegregateByFeatureOrDescriptorWindow (data, FALSE);
2246 }
2247 
2248 typedef struct segregatemoltypedata
2249 {
2250   FEATURE_FORM_BLOCK
2251 
2252   PopuP        type_popup;
2253   ButtoN       use_mol_type;
2254   PopuP        class_popup;
2255   ButtoN       use_mol_class;
2256   ButtoN       accept;
2257   Uint1        moltype;
2258   Uint1        molclass;
2259   BioseqSetPtr target_set;
2260 } SegregateMolTypeData, PNTR SegregateMolTypePtr;
2261 
ENUM_ALIST(molinfo_biomol_alist)2262 static ENUM_ALIST(molinfo_biomol_alist)
2263   {"Genomic DNA or RNA",     1},
2264   {"Precursor RNA",          2},
2265   {"mRNA [cDNA]",            3},
2266   {"Ribosomal RNA",          4},
2267   {"Transfer RNA",           5},
2268   {"Peptide",                8},
2269   {"Other-Genetic",          9},
2270   {"Genomic-mRNA",          10},
2271   {"cRNA",                  11},
2272   {"Transcribed RNA",       13},
2273   {"Other",                255},
2274 END_ENUM_ALIST
2275 
2276 static ENUM_ALIST(mol_class_alist)
2277 {"DNA",             Seq_mol_dna},
2278 {"RNA",             Seq_mol_rna},
2279 {"Protein",         Seq_mol_aa},
2280 {"Nucleotide",      Seq_mol_na},
2281 {"Other",           Seq_mol_other},
2282 END_ENUM_ALIST
2283 
2284 static Boolean LIBCALLBACK DoesSequenceHaveMoleculeType (BioseqPtr bsp, Pointer userdata)
2285 {
2286   SegregateMolTypePtr  smp;
2287   ValNodePtr           sdp;
2288   MolInfoPtr           mip;
2289 
2290   smp = (SegregateMolTypePtr) userdata;
2291   if (bsp == NULL || smp == NULL) return FALSE;
2292 
2293   if (GetStatus (smp->use_mol_class) && bsp->mol != smp->molclass)
2294   {
2295     return FALSE;
2296   }
2297 
2298   if (GetStatus (smp->use_mol_type))
2299   {
2300     sdp = bsp->descr;
2301     while (sdp != NULL)
2302     {
2303       if (sdp->choice == Seq_descr_molinfo && sdp->data.ptrvalue != NULL)
2304       {
2305         mip = (MolInfoPtr) sdp->data.ptrvalue;
2306         if (mip->biomol == smp->moltype)
2307         {
2308       	  return TRUE;
2309         }
2310       }
2311       sdp = sdp->next;
2312     }
2313     return FALSE;
2314   }
2315   return TRUE;
2316 }
2317 
2318 typedef struct lookformoltype
2319 {
2320   Boolean found;
2321   Uint1   moltype;
2322   Uint1   molclass;
2323 } LookForMolTypeData, PNTR LookForMolTypePtr;
2324 
DoesNucProtSetHaveMoleculeTypeCallback(SeqDescPtr sdp,Pointer userdata)2325 static void DoesNucProtSetHaveMoleculeTypeCallback (SeqDescPtr sdp, Pointer userdata)
2326 {
2327   LookForMolTypePtr l;
2328   MolInfoPtr           mip;
2329 
2330   if (sdp == NULL || userdata == NULL) return;
2331   l = (LookForMolTypePtr) userdata;
2332 
2333   if (sdp->choice == Seq_descr_molinfo && sdp->data.ptrvalue != NULL)
2334   {
2335   	mip = (MolInfoPtr) sdp->data.ptrvalue;
2336   	if (mip->biomol == l->moltype)
2337   	{
2338   	  l->found = TRUE;
2339   	}
2340   }
2341 }
2342 
2343 typedef struct lookformolclass
2344 {
2345   Boolean found;
2346   Uint1   molclass;
2347 } LookForMolClassData, PNTR LookForMolClassPtr;
2348 
FindMolClassCallback(BioseqPtr bsp,Pointer userdata)2349 static void FindMolClassCallback (BioseqPtr bsp, Pointer userdata)
2350 {
2351   LookForMolClassPtr lcp;
2352 
2353   if (bsp == NULL || userdata == NULL) return;
2354   lcp = (LookForMolClassPtr) userdata;
2355 
2356   if (bsp->mol == lcp->molclass)
2357   {
2358     lcp->found = TRUE;
2359   }
2360 }
2361 
DoesNucProtSetHaveMoleculeType(BioseqSetPtr bssp,Pointer userdata)2362 static Boolean LIBCALLBACK DoesNucProtSetHaveMoleculeType (BioseqSetPtr bssp, Pointer userdata)
2363 {
2364   LookForMolTypeData   lm;
2365   LookForMolClassData  lc;
2366   SegregateMolTypePtr  smp;
2367 
2368   if (bssp == NULL || userdata == NULL) return FALSE;
2369   smp = (SegregateMolTypePtr) userdata;
2370 
2371   if (GetStatus (smp->use_mol_class))
2372   {
2373     lc.found = FALSE;
2374     lc.molclass = smp->molclass;
2375     VisitBioseqsInSet (bssp, &lc, FindMolClassCallback);
2376     if (!lc.found) return FALSE;
2377   }
2378 
2379   if (GetStatus (smp->use_mol_type))
2380   {
2381     lm.moltype = smp->moltype;
2382     lm.found = FALSE;
2383     VisitDescriptorsInSet (bssp, &lm, DoesNucProtSetHaveMoleculeTypeCallback);
2384     if (!lm.found) return FALSE;
2385   }
2386   return TRUE;
2387 }
2388 
SegregateByMoleculeType(SeqEntryPtr seqlist,Pointer userdata,BioseqSetPtr set1,BioseqSetPtr set2)2389 static void LIBCALLBACK SegregateByMoleculeType
2390 (SeqEntryPtr  seqlist,
2391  Pointer      userdata,
2392  BioseqSetPtr set1,
2393  BioseqSetPtr set2)
2394 {
2395   SegregateItemsRecursor (seqlist, set1, set2,
2396                           DoesNucProtSetHaveMoleculeType,
2397                           DoesSequenceHaveMoleculeType, userdata);
2398 }
2399 
2400 
2401 /*=========================================================================*/
2402 /*                                                                         */
2403 /* SegregateByMoleculeType_Callback () - Segregates sequences that  */
2404 /*                            have a selected molecule type.                  */
2405 /*                                                                         */
2406 /*=========================================================================*/
2407 
SegregateByMoleculeType_Callback(ButtoN b)2408 static void SegregateByMoleculeType_Callback (ButtoN b)
2409 {
2410   SegregateMolTypePtr  smp;
2411   SeqEntryPtr          sep;
2412   UIEnum               val;
2413 
2414   /* Check the initial conditions and get the sequence */
2415   smp = (SegregateMolTypePtr) GetObjectExtra (b);
2416   if (smp == NULL) {
2417     return;
2418   }
2419   if (smp->input_entityID == 0 || smp->target_set == NULL) {
2420     Remove (smp->form);
2421     return;
2422   }
2423 
2424   sep = GetTopSeqEntryForEntityID (smp->input_entityID);
2425   if (sep == NULL) {
2426     Remove (smp->form);
2427     return;
2428   }
2429 
2430   if (!GetEnumPopup (smp->type_popup, molinfo_biomol_alist, &val))
2431   {
2432     return;
2433   }
2434   smp->moltype = val;
2435   if (!GetEnumPopup (smp->class_popup, mol_class_alist, &val))
2436   {
2437     return;
2438   }
2439   smp->molclass = val;
2440 
2441   SegregateItemsGenericCallback (sep, smp->target_set, smp->input_entityID,
2442                                  (Pointer) smp, SegregateByMoleculeType);
2443 
2444   Remove (smp->form);
2445 
2446   /* Return successfully */
2447   return;
2448 }
2449 
EnableMolInfoPopups(ButtoN b)2450 static void EnableMolInfoPopups (ButtoN b)
2451 {
2452   SegregateMolTypePtr smp;
2453   Boolean             ok_to_accept = FALSE;
2454 
2455   smp = (SegregateMolTypePtr) GetObjectExtra (b);
2456   if (smp == NULL) return;
2457 
2458   if (GetStatus (smp->use_mol_type))
2459   {
2460     Enable (smp->type_popup);
2461     ok_to_accept = TRUE;
2462   }
2463   else
2464   {
2465     Disable (smp->type_popup);
2466   }
2467   if (GetStatus (smp->use_mol_class))
2468   {
2469     Enable (smp->class_popup);
2470     ok_to_accept = TRUE;
2471   }
2472   else
2473   {
2474     Disable (smp->class_popup);
2475   }
2476   if (ok_to_accept)
2477   {
2478     Enable (smp->accept);
2479   }
2480   else
2481   {
2482     Disable (smp->accept);
2483   }
2484 }
2485 
2486 /*=========================================================================*/
2487 /*                                                                         */
2488 /* CreateSegregateByFeatureWindow () - Creates and then displays the window*/
2489 /*                        for getting segregate by text info from the user.*/
2490 /*                                                                         */
2491 /*=========================================================================*/
2492 
CreateSegregateByMoleculeTypeWindow(Pointer data)2493 extern Int2 LIBCALLBACK CreateSegregateByMoleculeTypeWindow (Pointer data)
2494 {
2495   GrouP               c;
2496   SegregateMolTypePtr smp;
2497   GrouP               g, k;
2498   GrouP               h;
2499   OMProcControlPtr    ompcp;
2500   StdEditorProcsPtr   sepp;
2501   WindoW              w;
2502 
2503   /* Check parameters and get a pointer to the current data */
2504 
2505   ompcp = (OMProcControlPtr) data;
2506   if (!OkToSegregate(ompcp)) {
2507     return OM_MSG_RET_ERROR;
2508   }
2509 
2510   /* Create a new window, and a struct */
2511   /* to pass around the data in.       */
2512 
2513   smp = (SegregateMolTypePtr) MemNew (sizeof (SegregateMolTypeData));
2514   if (smp == NULL)
2515     return OM_MSG_RET_ERROR;
2516 
2517   w = FixedWindow (-50, -33, -10, -10, "Segregate By Molecule Type",
2518 	               StdCloseWindowProc);
2519 
2520   SetObjectExtra (w, smp, StdCleanupFormProc);
2521   smp->form = (ForM) w;
2522 
2523   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2524   if (sepp != NULL) {
2525     SetActivate (w, sepp->activateForm);
2526     smp->appmessage = sepp->handleMessages;
2527   }
2528 
2529   smp->input_entityID = ompcp->input_entityID;
2530   smp->input_itemID = ompcp->input_itemID;
2531   smp->input_itemtype = ompcp->input_itemtype;
2532   smp->target_set = (BioseqSetPtr)ompcp->input_data;
2533 
2534   /* Add the popup lists */
2535 
2536   h = HiddenGroup (w, -1, 0, NULL);
2537   SetGroupSpacing (h, 10, 10);
2538 
2539   g = HiddenGroup (h, 1, 0, NULL);
2540 
2541   StaticPrompt (g, "Segregate sequences with:", 0, dialogTextHeight,
2542 	              programFont, 'l');
2543 	k = HiddenGroup (g, 2, 0, NULL);
2544 	smp->use_mol_type = CheckBox (k, "Molecule Type", EnableMolInfoPopups);
2545   SetObjectExtra (smp->use_mol_type, smp, NULL);
2546   smp->type_popup = PopupList (k, TRUE, NULL);
2547   InitEnumPopup (smp->type_popup, molinfo_biomol_alist, NULL);
2548   SetValue (smp->type_popup, 1);
2549   SetStatus (smp->use_mol_type, FALSE);
2550   Disable (smp->type_popup);
2551 	k = HiddenGroup (g, 2, 0, NULL);
2552   smp->use_mol_class = CheckBox (k, "Molecule Class", EnableMolInfoPopups);
2553   SetObjectExtra (smp->use_mol_class, smp, NULL);
2554   smp->class_popup = PopupList (k, TRUE, NULL);
2555   InitEnumPopup (smp->class_popup, mol_class_alist, NULL);
2556   SetValue (smp->class_popup, 1);
2557   SetStatus (smp->use_mol_class, FALSE);
2558   Disable (smp->class_popup);
2559 
2560   /* Add Accept and Cancel buttons */
2561 
2562   c = HiddenGroup (h, 4, 0, NULL);
2563   smp->accept = DefaultButton (c, "Accept", SegregateByMoleculeType_Callback);
2564   SetObjectExtra (smp->accept, smp, NULL);
2565   Disable (smp->accept);
2566   PushButton (c, "Cancel", StdCancelButtonProc);
2567 
2568   /* Line things up nicely */
2569 
2570   AlignObjects (ALIGN_LEFT, (HANDLE) g, (HANDLE) c, (HANDLE) h, NULL);
2571 
2572   /* Display the window now */
2573 
2574   RealizeWindow (w);
2575   Show (w);
2576   Select (w);
2577   Select (smp->accept);
2578   Update ();
2579   return OM_MSG_RET_OK;
2580 }
2581 
DoesSequenceHaveID(BioseqPtr bsp,Pointer userdata)2582 static Boolean LIBCALLBACK DoesSequenceHaveID (BioseqPtr bsp, Pointer userdata)
2583 {
2584   ConvertFormPtr cfp;
2585   Boolean      found = FALSE;
2586   ValNodePtr     vnp;
2587 
2588   cfp = (ConvertFormPtr) userdata;
2589   if (bsp == NULL || cfp == NULL) return FALSE;
2590 
2591   for (vnp = cfp->id_list; vnp != NULL && !found; vnp = vnp->next) {
2592     if (SeqIdIn (vnp->data.ptrvalue, bsp->id)) {
2593       found = TRUE;
2594     }
2595   }
2596   return found;
2597 }
2598 
DoesNucProtSetContainID(BioseqSetPtr bssp,Pointer userdata)2599 static Boolean LIBCALLBACK  DoesNucProtSetContainID (BioseqSetPtr bssp, Pointer userdata)
2600 {
2601   SeqEntryPtr sep;
2602   BioseqPtr   bsp;
2603   ConvertFormPtr cfp;
2604 
2605   if (bssp == NULL) return FALSE;
2606   cfp = (ConvertFormPtr) userdata;
2607   if (cfp == NULL) return FALSE;
2608 
2609   for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
2610     if (IS_Bioseq (sep)) {
2611       bsp = (BioseqPtr) sep->data.ptrvalue;
2612       if (DoesSequenceHaveID (bsp, (Pointer)cfp)) {
2613         return TRUE;
2614       }
2615     }
2616   }
2617   return FALSE;
2618 }
2619 
SegregateItemsById(SeqEntryPtr seqlist,ConvertFormPtr cfp,BioseqSetPtr set1,BioseqSetPtr set2)2620 static void SegregateItemsById
2621 (SeqEntryPtr                     seqlist,
2622  ConvertFormPtr                  cfp,
2623  BioseqSetPtr                    set1,
2624  BioseqSetPtr                    set2)
2625 {
2626   SegregateItemsRecursor (seqlist, set1, set2,
2627                   DoesNucProtSetContainID,
2628                   DoesSequenceHaveID, (Pointer)cfp);
2629 }
2630 
SetSegregateByIDAcceptButton(Pointer data)2631 static void SetSegregateByIDAcceptButton (Pointer data)
2632 
2633 {
2634   ConvertFormPtr  cfp;
2635   CharPtr         id_str;
2636 
2637   cfp = (ConvertFormPtr) data;
2638   if (cfp == NULL)
2639     return;
2640 
2641   id_str = SaveStringFromText (cfp->deleteText);
2642   if (StringHasNoText (id_str)) {
2643     SafeDisable (cfp->accept);
2644   } else {
2645     SafeEnable (cfp->accept);
2646   }
2647 }
2648 
2649 /*=========================================================================*/
2650 /*                                                                         */
2651 /* SegregateByID_Callback () - Finds and deletes all items of a selected */
2652 /*                            type that contain a given text phrase.       */
2653 /*                                                                         */
2654 /*=========================================================================*/
2655 
SegregateById_Callback(ButtoN b)2656 static void SegregateById_Callback (ButtoN b)
2657 {
2658   ConvertFormPtr    cfp;
2659   SeqEntryPtr       sep;
2660   BioseqSetPtr      bssp;
2661   SeqEntryPtr       seqlist;
2662   BioseqSetPtr      newset1, newset2;
2663   ObjMgrDataPtr     omdptop;
2664   ObjMgrData        omdata;
2665   Uint2             parenttype;
2666   Pointer           parentptr;
2667   Boolean           leaveDlgUp = FALSE;
2668   CharPtr           id_str;
2669 
2670   /* Check the initial conditions and get the sequence */
2671   cfp = (ConvertFormPtr) GetObjectExtra (b);
2672   if (cfp == NULL) {
2673     return;
2674   }
2675   if (cfp->input_entityID == 0 || cfp->target_set == NULL) {
2676     Remove (cfp->form);
2677     return;
2678   }
2679 
2680   sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
2681   if (sep == NULL) {
2682     Remove (cfp->form);
2683     return;
2684   }
2685 
2686   if (GetStatus (cfp->leaveDlgUp))
2687   {
2688   	leaveDlgUp = TRUE;
2689   }
2690 
2691   /* Get the string to search for */
2692   id_str = SaveStringFromText(cfp->deleteText);
2693   if (StringHasNoText (id_str)){
2694     if (!leaveDlgUp)
2695     {
2696       Remove (cfp->form);
2697     }
2698     id_str = MemFree (id_str);
2699     return;
2700   }
2701 
2702   cfp->id_list = ParseAccessionNumberListFromString (id_str, SeqMgrGetSeqEntryForData (cfp->target_set));
2703   id_str = MemFree (id_str);
2704   if (cfp->id_list == NULL) {
2705     Message (MSG_ERROR, "No IDs specified!");
2706     return;
2707   }
2708 
2709   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
2710   GetSeqEntryParent (sep, &parentptr, &parenttype);
2711 
2712   bssp = cfp->target_set;
2713   seqlist = bssp->seq_set;
2714   bssp->seq_set = NULL;
2715 
2716   CreateSetsForSegregate (bssp, &newset1, &newset2);
2717 
2718   /* Display the 'working' cursor */
2719 
2720   WatchCursor ();
2721   Update ();
2722 
2723   /* Do the search and move sequences */
2724   SegregateItemsById (seqlist, cfp, newset1, newset2);
2725 
2726   cfp->id_list = FreeSeqIdList (cfp->id_list);
2727   /* Remove the window and update things */
2728   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
2729   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata);
2730   ObjMgrSetDirtyFlag (cfp->input_entityID, TRUE);
2731   ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID, 0, 0);
2732 
2733   ArrowCursor ();
2734   Update ();
2735   if (!leaveDlgUp)
2736   {
2737     Remove (cfp->form);
2738   }
2739 
2740   /* Return successfully */
2741   return;
2742 }
2743 
2744 /*=========================================================================*/
2745 /*                                                                         */
2746 /* CreateSegregateByIdWindow () - Creates and then displays the window   */
2747 /*                        for getting segregate by ID info from the user.*/
2748 /*                                                                         */
2749 /*=========================================================================*/
2750 
CreateSegregateByIdWindow(Pointer data)2751 extern Int2 LIBCALLBACK CreateSegregateByIdWindow (Pointer data)
2752 {
2753   GrouP              c;
2754   ConvertFormPtr     cfp;
2755   GrouP              g;
2756   GrouP              h;
2757   OMProcControlPtr   ompcp;
2758   StdEditorProcsPtr  sepp;
2759   WindoW             w;
2760 
2761   /* Check parameters and get a pointer to the current data */
2762 
2763   ompcp = (OMProcControlPtr) data;
2764   if (!OkToSegregate(ompcp)) {
2765     return OM_MSG_RET_ERROR;
2766   }
2767 
2768   /* Create a new window, and a struct */
2769   /* to pass around the data in.       */
2770 
2771   cfp = ConvertFormNew ();
2772   if (cfp == NULL)
2773     return OM_MSG_RET_ERROR;
2774   cfp->target_set = (BioseqSetPtr)ompcp->input_data;
2775   cfp->set_accept_proc = SetSegregateByIDAcceptButton;
2776 
2777   w = FixedWindow (-50, -33, -10, -10, "Segregate By ID",
2778 		   StdCloseWindowProc);
2779   SetObjectExtra (w, cfp, CleanupSegregatePage);
2780   cfp->form = (ForM) w;
2781 
2782   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2783   if (sepp != NULL) {
2784     SetActivate (w, sepp->activateForm);
2785     cfp->appmessage = sepp->handleMessages;
2786   }
2787 
2788   cfp->input_entityID = ompcp->input_entityID;
2789   cfp->input_itemID = ompcp->input_itemID;
2790   cfp->input_itemtype = ompcp->input_itemtype;
2791 
2792   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2793   if (sepp != NULL) {
2794     SetActivate (w, sepp->activateForm);
2795     cfp->appmessage = sepp->handleMessages;
2796   }
2797 
2798   /* Add the popup lists */
2799 
2800   h = HiddenGroup (w, -1, 0, NULL);
2801   SetGroupSpacing (h, 10, 10);
2802 
2803   g = HiddenGroup (h, 3, 0, NULL);
2804 
2805   StaticPrompt (g, "Segregate sequences with the following IDs", 0, dialogTextHeight,
2806 		programFont, 'l');
2807   cfp->deleteText = DialogText (g, "", 10, ConvertFormTextCallback);
2808   SetObjectExtra (cfp->deleteText, cfp, NULL);
2809 
2810   /* Add Accept and Cancel buttons */
2811 
2812   c = HiddenGroup (h, 4, 0, NULL);
2813   cfp->accept = DefaultButton (c, "Accept", SegregateById_Callback);
2814   SetObjectExtra (cfp->accept, cfp, NULL);
2815   Disable (cfp->accept);
2816   PushButton (c, "Cancel", StdCancelButtonProc);
2817   cfp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
2818 
2819   /* Line things up nicely */
2820 
2821   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
2822 
2823   /* Display the window now */
2824 
2825   RealizeWindow (w);
2826   Show (w);
2827   Select (w);
2828   Select (cfp->accept);
2829   Update ();
2830   return OM_MSG_RET_OK;
2831 }
2832 
2833 
SearchAndExciseTextInside(CharPtr PNTR strptr,ConvertFormPtr cfp)2834 static void SearchAndExciseTextInside (CharPtr PNTR strptr, ConvertFormPtr cfp)
2835 
2836 {
2837   CharPtr  lft = NULL;
2838   CharPtr  rgt = NULL;
2839   CharPtr  string;
2840   CharPtr  next_delete = NULL;
2841   Int4     strLen;
2842 
2843   if (strptr == NULL || cfp == NULL || cfp->textportion == NULL) return;
2844   string = *strptr;
2845   if (string == NULL) return;
2846 
2847   FindTextPortionXInString (string, cfp->textportion, &lft, &strLen);
2848   if (lft == NULL) return;
2849   rgt = lft + strLen;
2850   next_delete = lft;
2851   if (lft < rgt) {  /* No text to delete */
2852     while (*rgt != 0) {
2853       *lft = *rgt;
2854       lft++;
2855       rgt++;
2856     }
2857     *lft = '\0';
2858   }
2859   if (cfp->repeat_remove && next_delete != NULL && *next_delete != 0) {
2860     SearchAndExciseTextInside (&next_delete, cfp);
2861   }
2862 }
2863 
2864 
2865 /*---------------------------------------------------------------------*/
2866 /*                                                                     */
2867 /* RemOutTxt_SearchAndExcise () -- Removes all text from a string that */
2868 /*                                 does not match a specified substring*/
2869 /*                                                                     */
2870 /*---------------------------------------------------------------------*/
2871 
SearchAndExciseTextOutside(CharPtr sourceStr,ConvertFormPtr cfp)2872 static void SearchAndExciseTextOutside (CharPtr sourceStr, ConvertFormPtr cfp)
2873 {
2874   CharPtr  leftEnd = NULL;
2875   CharPtr  rightEnd = NULL;
2876   Int4     strLen;
2877   Int4     i;
2878 
2879   /* Check parameters */
2880 
2881   if (cfp == NULL || cfp->textportion == NULL || sourceStr == NULL)
2882   {
2883     return;
2884   }
2885 
2886   FindTextPortionXInString (sourceStr, cfp->textportion, &leftEnd, &strLen);
2887 
2888   if (leftEnd != NULL)
2889   {
2890     rightEnd = leftEnd + strLen;
2891   }
2892 
2893   if (NULL == leftEnd)  /* String not found */
2894   {
2895     if (DO_NOTHING == cfp->ifNotFound)
2896     {
2897     	return;
2898     }
2899     else
2900     {
2901       sourceStr [0] = '\0';
2902       return;
2903     }
2904   }
2905   else
2906   {
2907     /* End the original string at rightEnd and  */
2908     /* then move everything starting at leftEnd */
2909     /* to the beginning of the original.        */
2910 
2911     rightEnd[0] = '\0';
2912     if (leftEnd == sourceStr)
2913       return;
2914 
2915     strLen = StringLen (leftEnd);
2916 
2917     for (i = 0; i <= strLen; i++)
2918       sourceStr[i] = leftEnd[i];
2919 
2920     sourceStr[i] = '\0';
2921   }
2922 }
2923 
2924 
SearchAndExciseText(CharPtr str,ConvertFormPtr cfp)2925 static void SearchAndExciseText (CharPtr str, ConvertFormPtr cfp)
2926 {
2927   if (str == NULL || cfp == NULL) return;
2928   if (cfp->remove_inside)
2929   {
2930     SearchAndExciseTextInside (&str, cfp);
2931   }
2932   else
2933   {
2934     SearchAndExciseTextOutside (str, cfp);
2935   }
2936 }
2937 
2938 
RemoveAFeatureText(SeqFeatPtr sfp,Pointer mydata)2939 static void RemoveAFeatureText (SeqFeatPtr sfp, Pointer mydata)
2940 {
2941   ConvertFormPtr  cfp;
2942   GBQualPtr       gbqp;
2943   GeneRefPtr      grp;
2944   ProtRefPtr      prp;
2945   RnaRefPtr       rrp;
2946   CharPtr         str;
2947   ValNodePtr      vnp;
2948 
2949   if (sfp == NULL) return;
2950   cfp = (ConvertFormPtr) mydata;
2951   if (cfp == NULL) return;
2952 
2953   if (sfp->data.choice == SEQFEAT_GENE && cfp->type == eFieldTypeGene) {
2954     grp = (GeneRefPtr) sfp->data.value.ptrvalue;
2955     if (grp != NULL) {
2956       switch (cfp->subtype) {
2957         case 1 :
2958           SearchAndExciseText (grp->locus, cfp);
2959           break;
2960         case 2 :
2961           SearchAndExciseText (grp->desc, cfp);
2962           break;
2963         case 3 :
2964           SearchAndExciseText (grp->allele, cfp);
2965           break;
2966         case 4 :
2967           SearchAndExciseText (grp->maploc, cfp);
2968           break;
2969         case 5 :
2970           SearchAndExciseText (grp->locus_tag, cfp);
2971           break;
2972         case 6 :
2973           for (vnp = grp->syn; vnp != NULL; vnp = vnp->next) {
2974             str = (CharPtr) vnp->data.ptrvalue;
2975             SearchAndExciseText (str, cfp);
2976           }
2977           break;
2978         case 7 :
2979           SearchAndExciseText (sfp->comment, cfp);
2980           break;
2981         default :
2982           break;
2983       }
2984     }
2985   } else if (sfp->data.choice == SEQFEAT_CDREGION && cfp->type == eFieldTypeCDS) {
2986     switch (cfp->subtype) {
2987       case CDS_COMMENT :
2988         SearchAndExciseText (sfp->comment, cfp);
2989         break;
2990       case CDS_GENE_XREF :
2991         break;
2992       default :
2993         break;
2994     }
2995   } else if (sfp->data.choice == SEQFEAT_PROT && cfp->type == eFieldTypeProtein) {
2996     prp = (ProtRefPtr) sfp->data.value.ptrvalue;
2997     if (prp != NULL) {
2998       switch (cfp->subtype) {
2999         case 1 :
3000           for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
3001             str = (CharPtr) vnp->data.ptrvalue;
3002             SearchAndExciseText (str, cfp);
3003           }
3004           break;
3005         case 2 :
3006           SearchAndExciseText (prp->desc, cfp);
3007           break;
3008         case 3 :
3009           for (vnp = prp->ec; vnp != NULL; vnp = vnp->next) {
3010             str = (CharPtr) vnp->data.ptrvalue;
3011             SearchAndExciseText (str, cfp);
3012           }
3013           break;
3014         case 4 :
3015           for (vnp = prp->activity; vnp != NULL; vnp = vnp->next) {
3016             str = (CharPtr) vnp->data.ptrvalue;
3017             SearchAndExciseText (str, cfp);
3018           }
3019           break;
3020         case 5 :
3021           SearchAndExciseText (sfp->comment, cfp);
3022           break;
3023         default :
3024           break;
3025       }
3026     }
3027   } else if (sfp->data.choice == SEQFEAT_RNA && cfp->type == eFieldTypeRNA) {
3028     rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
3029     if (rrp != NULL) {
3030       switch (cfp->subtype) {
3031         case 1 :
3032           if (rrp->ext.choice == 0 || rrp->ext.choice == 1) {
3033             rrp->ext.choice = 1;
3034             str = (CharPtr) rrp->ext.value.ptrvalue;
3035             SearchAndExciseText (str, cfp);
3036           }
3037           break;
3038         case 2 :
3039           SearchAndExciseText (sfp->comment, cfp);
3040           break;
3041         case 3 :
3042         default :
3043           break;
3044       }
3045     }
3046   } else if (sfp->data.choice == SEQFEAT_IMP && cfp->type == eFieldTypeImport) {
3047     switch (cfp->subtype) {
3048       case IMPORT_GBQUAL_FIELD :
3049         gbqp = sfp->qual;
3050         while (NULL != gbqp)
3051         {
3052           if (NULL != gbqp->val)
3053             SearchAndExciseText (gbqp->val, cfp);
3054           gbqp = gbqp->next;
3055         }
3056         break;
3057       case IMPORT_COMMENT_FIELD :
3058         SearchAndExciseText (sfp->comment, cfp);
3059         break;
3060       default :
3061         break;
3062     }
3063 	}
3064 }
3065 
3066 
RemoveOrgModText(BioSourcePtr biop,ConvertFormPtr cfp)3067 static void RemoveOrgModText (BioSourcePtr biop, ConvertFormPtr cfp)
3068 {
3069   OrgModPtr mod, prev_mod = NULL, next_mod;
3070 
3071   if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL || cfp == NULL) return;
3072 
3073   mod = biop->org->orgname->mod;
3074   while (mod != NULL) {
3075     next_mod = mod->next;
3076     if (mod->subtype == cfp->subtype) {
3077 	    SearchAndExciseText (mod->subname, cfp);
3078       if (StringHasNoText (mod->subname) && !IsNonTextModifier (GetOrgModQualName (mod->subtype))) {
3079         if (prev_mod == NULL) {
3080           biop->org->orgname->mod = mod->next;
3081         } else {
3082           prev_mod->next = mod->next;
3083         }
3084         mod->next = NULL;
3085         mod = OrgModFree (mod);
3086       } else {
3087         prev_mod = mod;
3088       }
3089     } else {
3090       prev_mod = mod;
3091     }
3092     mod = mod->next;
3093   }
3094 }
3095 
3096 
RemoveSubSourceText(BioSourcePtr biop,ConvertFormPtr cfp)3097 static void RemoveSubSourceText (BioSourcePtr biop, ConvertFormPtr cfp)
3098 {
3099   SubSourcePtr ssp, next_ssp, prev_ssp = NULL;
3100 
3101   if (biop == NULL || cfp == NULL) return;
3102 
3103   ssp = biop->subtype;
3104   while (ssp != NULL) {
3105     next_ssp = ssp->next;
3106     if (ssp->subtype == (cfp->subtype - 1000)) {
3107 	    SearchAndExciseText (ssp->name, cfp);
3108       if (StringHasNoText (ssp->name) && !IsNonTextModifier (GetSubsourceQualName (ssp->subtype))) {
3109         if (prev_ssp == NULL) {
3110           biop->subtype = ssp->next;
3111         } else {
3112           prev_ssp->next = ssp->next;
3113         }
3114         ssp->next = NULL;
3115         ssp = SubSourceFree (ssp);
3116       } else {
3117         prev_ssp = ssp;
3118       }
3119     } else {
3120       prev_ssp = ssp;
3121     }
3122 	  ssp = next_ssp;
3123   }
3124 }
3125 
RemoveASourceText(BioSourcePtr biop,Pointer data)3126 static void RemoveASourceText (BioSourcePtr biop, Pointer data)
3127 {
3128   ConvertFormPtr cfp;
3129   OrgRefPtr      orp;
3130   CharPtr        tmp_str;
3131 
3132   cfp = (ConvertFormPtr) data;
3133   if (biop == NULL || cfp == NULL) return;
3134   switch (cfp->type) {
3135     case eFieldTypeBioSource :
3136       orp = biop->org;
3137       if (orp == NULL) return;
3138       switch (cfp->subtype) {
3139         case ORGREF_SCI_NAME_FIELD :
3140           tmp_str = StringSave (orp->taxname);
3141           SearchAndExciseText (tmp_str, cfp);
3142           if (StringCmp (tmp_str, orp->taxname) == 0) {
3143             /* no change, no need to remove taxref */
3144             tmp_str = MemFree (tmp_str);
3145           } else {
3146             SetTaxNameAndRemoveTaxRef (orp, tmp_str);
3147           }
3148           break;
3149         case ORGREF_COMMON_NAME_FIELD :
3150           SearchAndExciseText (orp->common, cfp);
3151           break;
3152         case ORGREF_LINEAGE_FIELD :
3153           if (orp->orgname != NULL) {
3154             SearchAndExciseText (orp->orgname->lineage, cfp);
3155           }
3156           break;
3157         case ORGREF_DIVISION_FIELD :
3158           if (orp->orgname != NULL) {
3159             SearchAndExciseText (orp->orgname->div, cfp);
3160           }
3161           break;
3162         default:
3163           break;
3164       }
3165       break;
3166     case eFieldTypeOrgModSubSource :
3167       if (cfp->subtype < 1000) {  /* Orgmod Note */
3168         RemoveOrgModText (biop, cfp);
3169       } else {  /* subsource note */
3170         RemoveSubSourceText (biop, cfp);
3171       }
3172       break;
3173     default:
3174       break;
3175   }
3176 }
3177 
3178 
RemoveDescriptorTextCallback(SeqDescrPtr sdp,Pointer userdata)3179 static void RemoveDescriptorTextCallback (SeqDescrPtr sdp, Pointer userdata)
3180 {
3181   ConvertFormPtr    cfp;
3182   CharPtr           title;
3183   ObjValNodePtr     ovp;
3184 
3185   cfp = (ConvertFormPtr) userdata;
3186 
3187   if (sdp == NULL || cfp == NULL) return;
3188 
3189   if (cfp->type == eFieldTypeDefline) {
3190     if (sdp->choice != Seq_descr_title) {
3191       return;
3192     }
3193   } else if (cfp->type == eFieldTypeCommentDescriptor) {
3194     if (sdp->choice != Seq_descr_comment) {
3195       return;
3196     }
3197   } else {
3198     return;
3199   }
3200 
3201   title = (CharPtr) sdp->data.ptrvalue;
3202   SearchAndExciseText (title, cfp);
3203 
3204   if (StringHasNoText (title) && (sdp->extended > 0)) {
3205     ovp = (ObjValNodePtr) sdp;
3206     ovp->idx.deleteme = TRUE;
3207     cfp->isDirty = TRUE;
3208   }
3209 }
3210 
3211 
DoRemoveText(ConvertFormPtr cfp)3212 static void DoRemoveText (ConvertFormPtr cfp)
3213 
3214 {
3215   SeqEntryPtr     sep;
3216   FieldSubfieldPtr f;
3217 
3218   /* Get the current sequence and associated data */
3219 
3220   if (cfp == NULL || cfp->input_entityID == 0)
3221     return;
3222 
3223   sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
3224   if (sep == NULL)
3225     return;
3226 
3227   /* Get the feature and subfeature types */
3228   f = DialogToPointer (cfp->target_dlg);
3229   if (f == NULL || f->field < 0 || (f->subfield < 0 && f->subfield_list == NULL)) {
3230     f = FieldSubfieldFree (f);
3231     return;
3232   }
3233 
3234   cfp->type = f->field;
3235   cfp->subtype = f->subfield;
3236 
3237   f = FieldSubfieldFree (f);
3238 
3239   /* Hide the window and set the 'working' cursor */
3240 
3241   Hide (cfp->form);
3242   WatchCursor ();
3243   Update ();
3244 
3245 
3246   /* get information about text to remove */
3247   cfp->textportion = (TextPortionXPtr) DialogToPointer (cfp->textportion_dlg);
3248 
3249   if (GetValue (cfp->repeat_remove_grp) == 2) {
3250     cfp->repeat_remove = TRUE;
3251   } else {
3252     cfp->repeat_remove = FALSE;
3253   }
3254 
3255   /* Do actual work of removing text */
3256   cfp->isDirty = FALSE;
3257   if (cfp->type == eFieldTypeDefline || cfp->type == eFieldTypeCommentDescriptor) {
3258     VisitDescriptorsInSep (sep, cfp, RemoveDescriptorTextCallback);
3259   }
3260   else if (cfp->type == eFieldTypeBioSource || cfp->type == eFieldTypeOrgModSubSource) {
3261     VisitBioSourcesInSep (sep, cfp, RemoveASourceText);
3262   }
3263   else {
3264     VisitFeaturesInSep (sep, cfp, RemoveAFeatureText);
3265   }
3266 
3267   /* Clean up and exit */
3268 
3269   cfp->textportion = TextPortionXFree (cfp->textportion);
3270 
3271   if (cfp->isDirty) {
3272     DeleteMarkedObjects (cfp->input_entityID, 0, NULL);
3273   }
3274 
3275   ObjMgrSetDirtyFlag (cfp->input_entityID, TRUE);
3276   ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID, 0, 0);
3277   if (GetStatus (cfp->leaveDlgUp))
3278   {
3279   	Show (cfp->form);
3280   }
3281   else
3282   {
3283     Remove (cfp->form);
3284   }
3285   ArrowCursor ();
3286   Update ();
3287 }
3288 
ConvertMessageProc(ForM f,Int2 mssg)3289 static void ConvertMessageProc (ForM f, Int2 mssg)
3290 
3291 {
3292   StdEditorProcsPtr  sepp;
3293 
3294   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3295   if (sepp != NULL) {
3296     if (sepp->handleMessages != NULL) {
3297       sepp->handleMessages (f, mssg);
3298     }
3299   }
3300 }
3301 
3302 
3303 /* gather information specific ro remove inside text, then call common removetext function */
DoRemoveInsideText(ButtoN b)3304 static void DoRemoveInsideText (ButtoN b)
3305 {
3306   ConvertFormPtr cfp;
3307 
3308   cfp = (ConvertFormPtr) GetObjectExtra (b);
3309   if (cfp == NULL) return;
3310 
3311   if (GetValue (cfp->repeat_remove_grp) == 2) {
3312     cfp->repeat_remove = TRUE;
3313   } else {
3314     cfp->repeat_remove = FALSE;
3315   }
3316 
3317   DoRemoveText (cfp);
3318 }
3319 
3320 
3321 /*-------------------------------------------------------------------------*/
3322 /*                                                                         */
3323 /* SetRemoveTextAcceptButton () -- Enable/Disable the Accept button depending */
3324 /*                              on the condition of other window objects.  */
3325 /*                                                                         */
3326 /*-------------------------------------------------------------------------*/
3327 
SetRemoveTextAcceptButton(Pointer data)3328 static void SetRemoveTextAcceptButton (Pointer data)
3329 
3330 {
3331   ConvertFormPtr   cfp;
3332   FieldSubfieldPtr f;
3333   Boolean          ok_to_accept = FALSE;
3334   TextPortionXPtr   tp;
3335 
3336   cfp = (ConvertFormPtr) data;
3337   if (cfp == NULL) return;
3338 
3339   f = DialogToPointer (cfp->target_dlg);
3340   if (f != NULL && f->field >= 0 && (f->subfield >= 0 || f->subfield_list != NULL)) {
3341     if (f->field == eFieldTypeFeatureNote) {
3342       if (f->subfield_list != NULL) {
3343         ok_to_accept = TRUE;
3344       }
3345     } else {
3346       ok_to_accept = TRUE;
3347     }
3348   }
3349   f = FieldSubfieldFree (f);
3350   if (ok_to_accept) {
3351     tp = (TextPortionXPtr) DialogToPointer (cfp->textportion_dlg);
3352     if (tp == NULL || (StringHasNoText (tp->start_text) && StringHasNoText (tp->end_text))) {
3353       ok_to_accept = FALSE;
3354     }
3355     tp = TextPortionXFree (tp);
3356   }
3357   if (ok_to_accept) {
3358     SafeEnable (cfp->accept);
3359   } else {
3360     SafeDisable (cfp->accept);
3361   }
3362   f = FieldSubfieldFree (f);
3363 }
3364 
3365 
3366 
RemoveTextInsideStringBaseForm(BaseFormPtr bfp)3367 extern void RemoveTextInsideStringBaseForm (BaseFormPtr bfp)
3368 {
3369   GrouP              c;
3370   ConvertFormPtr     cfp;
3371   GrouP              h;
3372   PrompT             ppt, ppt2;
3373   SeqEntryPtr        sep;
3374   StdEditorProcsPtr  sepp;
3375   WindoW             w;
3376   Boolean            allowed[eFieldType_Max];
3377 
3378   if (bfp == NULL) return;
3379   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3380   if (sep == NULL) return;
3381   cfp = ConvertFormNew ();
3382   if (cfp == NULL) return;
3383 
3384   cfp->set_accept_proc = SetRemoveTextAcceptButton;
3385   cfp->remove_inside = TRUE;
3386 
3387   w = FixedWindow (-50, -33, -10, -10, "Remove Text Inside String", StdCloseWindowProc);
3388   SetObjectExtra (w, cfp, StdCleanupFormProc);
3389   cfp->form = (ForM) w;
3390   cfp->formmessage = ConvertMessageProc;
3391 
3392   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3393   if (sepp != NULL) {
3394     SetActivate (w, sepp->activateForm);
3395     cfp->appmessage = sepp->handleMessages;
3396   }
3397 
3398   cfp->input_entityID = bfp->input_entityID;
3399   cfp->input_itemID = bfp->input_itemID;
3400   cfp->input_itemtype = bfp->input_itemtype;
3401 
3402   h = HiddenGroup (w, -1, 0, NULL);
3403   SetGroupSpacing (h, 10, 10);
3404 
3405   ppt = StaticPrompt (h, "Remove Text", 0, popupMenuHeight, programFont, 'c');
3406   cfp->textportion_dlg = TextPortionXDialogEx (h, TRUE, SetRemoveTextAcceptButton, cfp);
3407 
3408   cfp->repeat_remove_grp = HiddenGroup (h, 2, 0, NULL);
3409   RadioButton (cfp->repeat_remove_grp, "Remove first instance in each string");
3410   RadioButton (cfp->repeat_remove_grp, "Remove all instances");
3411   SetValue (cfp->repeat_remove_grp, 1);
3412 
3413   ppt2 = StaticPrompt (h, "Perform excision in", 0, popupMenuHeight, programFont, 'c');
3414 
3415   MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
3416   allowed[eFieldTypeCommentDescriptor] = TRUE;
3417   allowed[eFieldTypeFeatureNote] = FALSE;
3418   allowed[eFieldTypePublication] = FALSE;
3419   cfp->target_dlg = CreateFieldSubfieldDlg (h, allowed, ChangeTargetFields, cfp);
3420 
3421   c = HiddenGroup (h, 4, 0, NULL);
3422   cfp->accept = DefaultButton (c, "Accept", DoRemoveInsideText);
3423   SetObjectExtra (cfp->accept, cfp, NULL);
3424   Disable (cfp->accept);
3425   PushButton (c, "Cancel", StdCancelButtonProc);
3426   cfp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
3427 
3428 
3429   AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) cfp->textportion_dlg, (HANDLE) cfp->repeat_remove_grp, (HANDLE) ppt2, (HANDLE) cfp->target_dlg, (HANDLE) c, NULL);
3430   RealizeWindow (w);
3431   Show (w);
3432   Select (w);
3433   Select (cfp->textportion_dlg);
3434   Update ();
3435 }
3436 
3437 
RemoveTextInsideString(IteM i)3438 extern void RemoveTextInsideString (IteM i)
3439 {
3440   BaseFormPtr        bfp;
3441 
3442 #ifdef WIN_MAC
3443   bfp = currentFormDataPtr;
3444 #else
3445   bfp = GetObjectExtra (i);
3446 #endif
3447   RemoveTextInsideStringBaseForm (bfp);
3448 }
3449 
3450 
3451 /* AAForCodon is extern in seqport.c */
3452 /* NLM_EXTERN Uint1 AAForCodon (Uint1Ptr codon, CharPtr codes); */
3453 
3454 /*
3455 static Boolean CorrectStartCodonCallback (GatherContextPtr gcp)
3456 
3457 {
3458   Uint1           aa;
3459   Boolean         bad_base;
3460   CodeBreakPtr    cbp;
3461   Uint1           codon [3];
3462   CharPtr         codes;
3463   CdRegionPtr     crp;
3464   GeneticCodePtr  gc;
3465   Int2            i;
3466   Uint1           residue;
3467   SeqEntryPtr     sep;
3468   SeqFeatPtr      sfp;
3469   SeqLocPtr       slp;
3470   SeqPntPtr       spntp;
3471   SeqPortPtr      spp;
3472   ValNodePtr      vnp;
3473 
3474   if (gcp == NULL) return TRUE;
3475   sep = (SeqEntryPtr) gcp->userdata;
3476   if (sep == NULL ) return TRUE;
3477   if (gcp->thistype != OBJ_SEQFEAT) return TRUE;
3478   sfp = (SeqFeatPtr) gcp->thisitem;
3479   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return TRUE;
3480   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
3481   if (crp == NULL) return TRUE;
3482 
3483   if (crp->code_break != NULL) return TRUE;
3484 
3485 	gc = NULL;
3486 	if (crp->genetic_code != NULL)
3487 	{
3488 		vnp = (ValNodePtr)(crp->genetic_code->data.ptrvalue);
3489 		while ((vnp != NULL) && (gcp == NULL))
3490 		{
3491 			switch (vnp->choice)
3492 			{
3493 			case 1:
3494 				gc = GeneticCodeFind(0, (CharPtr)vnp->data.ptrvalue);
3495 				break;
3496 			case 2:
3497 				gc = GeneticCodeFind(vnp->data.intvalue, NULL);
3498 				break;
3499 			case 3:
3500 			case 6:
3501 			case 4:
3502 			case 5:
3503 			case 7:
3504 			case 8:
3505 			default:
3506 				break;
3507 			}
3508 			vnp = vnp->next;
3509 		}
3510 	}
3511 	if (gc == NULL)
3512 		gc = GeneticCodeFind(1, NULL);
3513 	if (gc == NULL) return TRUE;
3514 
3515 	codes = NULL;
3516 	for (vnp = (ValNodePtr)gc->data.ptrvalue; vnp != NULL; vnp = vnp->next)
3517 	{
3518 		if (vnp->choice == 3)
3519 			codes = (CharPtr)vnp->data.ptrvalue;
3520 	}
3521 	if (codes == NULL) return TRUE;
3522 
3523   if (crp->frame == 2 || crp->frame == 3) return TRUE;
3524 
3525   spp = SeqPortNewByLoc (sfp->location, Seq_code_ncbi4na);
3526   if (spp == NULL) return TRUE;
3527   bad_base = FALSE;
3528   for (i = 0; i < 3; i++) {
3529     residue = SeqPortGetResidue (spp);
3530     if (residue == SEQPORT_EOF)
3531       break;
3532     if (residue == INVALID_RESIDUE)
3533       bad_base = TRUE;
3534     codon[i] = residue;
3535   }
3536   SeqPortFree (spp);
3537   if (i != 3 || bad_base) return TRUE;
3538   aa = AAForCodon (codon, codes);
3539 
3540   spp = SeqPortNewByLoc (sfp->product, Seq_code_ncbieaa);
3541   if (spp == NULL) return TRUE;
3542   residue = SeqPortGetResidue (spp);
3543   SeqPortFree (spp);
3544   if (residue == SEQPORT_EOF || residue == INVALID_RESIDUE) return TRUE;
3545 
3546   if (residue != aa) {
3547     cbp = CodeBreakNew ();
3548     if (cbp != NULL) {
3549       spntp = SeqPntNew ();
3550       slp = ValNodeNew (NULL);
3551       slp->choice = SEQLOC_PNT;
3552       slp->data.ptrvalue = (Pointer) spntp;
3553       spntp->point = (Int4) 0;
3554       spntp->id = SeqIdStripLocus (SeqIdDup (SeqLocId (sfp->product)));
3555       cbp->loc = slp;
3556       slp = aaLoc_to_dnaLoc (sfp, cbp->loc);
3557       cbp->loc = SeqLocFree (cbp->loc);
3558       cbp->loc = slp;
3559       cbp->aa.value.intvalue = aa;
3560       cbp->aa.choice = 1;
3561       cbp->next = crp->code_break;
3562       crp->code_break = cbp;
3563     }
3564   }
3565 
3566   return TRUE;
3567 }
3568 
3569 static void CorrectStartCodon (SeqEntryPtr sep, Uint2 entityID)
3570 
3571 {
3572   BioseqSetPtr  bssp;
3573   GatherScope   gs;
3574 
3575   if (sep == NULL) return;
3576   if (IS_Bioseq_set (sep)) {
3577     bssp = (BioseqSetPtr) sep->data.ptrvalue;
3578     if (bssp != NULL && (bssp->_class == 7 || bssp->_class == 13 ||
3579                          bssp->_class == 14 || bssp->_class == 15)) {
3580       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
3581         CorrectStartCodon (sep, entityID);
3582       }
3583       return;
3584     }
3585   }
3586   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
3587   gs.seglevels = 1;
3588   gs.get_feats_location = FALSE;
3589   MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
3590   gs.ignore[OBJ_BIOSEQ] = FALSE;
3591   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
3592   gs.ignore[OBJ_SEQFEAT] = FALSE;
3593   gs.ignore[OBJ_SEQANNOT] = FALSE;
3594   gs.scope = sep;
3595   GatherEntity (entityID, (Pointer) sep, CorrectStartCodonCallback, &gs);
3596 }
3597 
3598 extern void CorrectCDSStartCodon (IteM i);
3599 extern void CorrectCDSStartCodon (IteM i)
3600 
3601 {
3602   BaseFormPtr  bfp;
3603   SeqEntryPtr  sep;
3604 
3605 #ifdef WIN_MAC
3606   bfp = currentFormDataPtr;
3607 #else
3608   bfp = GetObjectExtra (i);
3609 #endif
3610   if (bfp == NULL) return;
3611   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3612   if (sep == NULL) return;
3613   CorrectStartCodon (sep, bfp->input_entityID);
3614   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3615   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3616 }
3617 */
3618 
3619 
3620 typedef struct applyformdata {
3621   FEATURE_FORM_BLOCK
3622 
3623   Int2           type;
3624   Int2           errcount;
3625   ValNodePtr     ambigList;
3626   Boolean        noLeft;
3627   Boolean        noRight;
3628   ButtoN         applyToParts;
3629   ButtoN         partial5;
3630   ButtoN         partial3;
3631   TexT           onlyThisPart;
3632   GrouP          all_or_some_grp;
3633   TexT           accession_list_txt;
3634 
3635   DialoG         feature_details_dlg;
3636 
3637   BatchApplyFeatureDetailsPtr feature_details_data;
3638 
3639   GrouP          strand_group;
3640   GrouP          use_whole_interval;
3641   TexT           left_end;
3642   TexT           right_end;
3643   ButtoN         add_to_seq_with_like_feature;
3644   ButtoN         also_add_mRNA_btn;
3645   ButtoN         accept;
3646   ButtoN         leaveDlgUp;
3647 
3648   GetSamplePtr   gsp;
3649   ExistingTextPtr etp;
3650 } ApplyFormData, PNTR ApplyFormPtr;
3651 
3652 typedef struct alreadyhas {
3653   Boolean        rsult;
3654   Uint1          featchoice;
3655   Uint1          descchoice;
3656   Uint1          rnatype;
3657 } AlreadyHas, PNTR AlreadyHasPtr;
3658 
SeeIfAlreadyHasGatherFunc(GatherContextPtr gcp)3659 static Boolean SeeIfAlreadyHasGatherFunc (GatherContextPtr gcp)
3660 
3661 {
3662   AlreadyHasPtr  ahp;
3663   RnaRefPtr      rrp;
3664   ValNodePtr     sdp;
3665   SeqFeatPtr     sfp;
3666 
3667   if (gcp == NULL) return TRUE;
3668 
3669   ahp = (AlreadyHasPtr) gcp->userdata;
3670   if (ahp == NULL ) return TRUE;
3671 
3672   if (gcp->thistype == OBJ_SEQFEAT && ahp->featchoice != 0) {
3673     sfp = (SeqFeatPtr) gcp->thisitem;
3674     if (sfp != NULL && sfp->data.choice == ahp->featchoice && sfp->data.value.ptrvalue != NULL) {
3675       if (sfp->data.choice == SEQFEAT_RNA) {
3676         rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
3677         if (rrp->type != ahp->rnatype) return TRUE;
3678       }
3679       ahp->rsult = TRUE;
3680       return FALSE;
3681     }
3682   } else if (gcp->thistype == OBJ_SEQDESC && ahp->descchoice != 0) {
3683     sdp = (ValNodePtr) gcp->thisitem;
3684     if (sdp != NULL && sdp->choice == ahp->descchoice && sdp->data.ptrvalue != NULL) {
3685       ahp->rsult = TRUE;
3686       return FALSE;
3687     }
3688   }
3689   return TRUE;
3690 }
3691 
AlreadyHasFeatOrDesc(SeqEntryPtr sep,Uint1 featchoice,Uint1 descchoice,Uint1 rnatype)3692 static Boolean AlreadyHasFeatOrDesc (SeqEntryPtr sep, Uint1 featchoice, Uint1 descchoice, Uint1 rnatype)
3693 
3694 {
3695   AlreadyHas   ah;
3696   BioseqPtr    bsp;
3697   GatherScope  gs;
3698   SeqEntryPtr  nsep;
3699   SeqIdPtr     sip;
3700   SeqLocPtr    slp;
3701 
3702   ah.rsult = FALSE;
3703   ah.featchoice = featchoice;
3704   ah.descchoice = descchoice;
3705   ah.rnatype = rnatype;
3706   if (sep == NULL) return FALSE;
3707   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
3708   gs.seglevels = 1;
3709   gs.get_feats_location = TRUE;
3710   MemSet ((Pointer) (gs.ignore), (int)(TRUE), (size_t) (OBJ_MAX * sizeof(Boolean)));
3711   gs.ignore[OBJ_BIOSEQ] = FALSE;
3712   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
3713   gs.ignore[OBJ_SEQFEAT] = FALSE;
3714   gs.ignore[OBJ_SEQDESC] = FALSE;
3715   gs.ignore[OBJ_SEQANNOT] = FALSE;
3716   gs.scope = sep;
3717   if (descchoice != 0) {
3718     nsep = FindNucSeqEntry (sep);
3719     if (nsep != NULL && IS_Bioseq (nsep)) {
3720       bsp = (BioseqPtr) nsep->data.ptrvalue;
3721       if (bsp != NULL) {
3722         slp = ValNodeNew (NULL);
3723         slp->choice = SEQLOC_WHOLE;
3724         sip = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
3725         slp->data.ptrvalue = sip;
3726         gs.target = slp;
3727       }
3728     }
3729   }
3730   GatherSeqEntry (sep, (Pointer) (&ah), SeeIfAlreadyHasGatherFunc, &gs);
3731   gs.target = SeqLocFree (gs.target);
3732   return ah.rsult;
3733 }
3734 
3735 
3736 typedef struct hasimpfeatdata {
3737     Boolean has_it;
3738     CharPtr key;
3739 
3740 } HasImpFeatData, PNTR HasImpFeatPtr;
3741 
3742 
AlreadyHasImpFeatCallback(SeqFeatPtr sfp,Pointer data)3743 static void AlreadyHasImpFeatCallback(SeqFeatPtr sfp, Pointer data)
3744 {
3745     ImpFeatPtr imp;
3746     HasImpFeatPtr h;
3747 
3748     if (sfp != NULL && sfp->data.choice == SEQFEAT_IMP
3749         && (imp = (ImpFeatPtr) sfp->data.value.ptrvalue) != NULL
3750         && (h = (HasImpFeatPtr) data) != NULL
3751         && StringICmp (imp->key, h->key) == 0) {
3752         h->has_it = TRUE;
3753     }
3754 }
3755 
3756 
AlreadyHasImpFeat(SeqEntryPtr sep,CharPtr key)3757 static Boolean AlreadyHasImpFeat(SeqEntryPtr sep, CharPtr key)
3758 {
3759     HasImpFeatData h;
3760 
3761     h.has_it = FALSE;
3762     h.key = key;
3763 
3764     VisitFeaturesInSep (sep, &h, AlreadyHasImpFeatCallback);
3765     return h.has_it;
3766 }
3767 
3768 
setSeqFeatStrand(SeqFeatPtr sfp,Uint1 strand)3769 static void setSeqFeatStrand(SeqFeatPtr sfp, Uint1 strand)
3770 {
3771   SeqIntPtr          sqip;
3772 
3773   if (sfp == NULL) return;
3774   if (sfp->location == NULL) return;
3775   if (sfp->location->choice != SEQLOC_INT) return;
3776   sqip = (SeqIntPtr) sfp->location->data.ptrvalue;
3777   if (sqip != NULL)
3778   {
3779     sqip->strand = Seq_strand_minus;
3780   }
3781 }
3782 
3783 /* must be called after partials and strand are set*/
AdjustSeqLocForApply(SeqFeatPtr sfp,ApplyFormPtr afp)3784 static void AdjustSeqLocForApply (SeqFeatPtr sfp, ApplyFormPtr afp)
3785 {
3786   BioseqPtr bsp;
3787   SeqLocPtr slp;
3788   SeqIntPtr sip;
3789   CharPtr   num_str;
3790   Int4      from;
3791   Int4      to;
3792   Int4      tmp;
3793   Boolean   partial3, partial5;
3794   Boolean   is_caret = FALSE;
3795   Uint1     strand;
3796 
3797   if (sfp == NULL || afp == NULL) return;
3798 
3799   bsp = BioseqFindFromSeqLoc (sfp->location);
3800   if (bsp == NULL) return;
3801 
3802   num_str = SaveStringFromText (afp->left_end);
3803   if (num_str == NULL) return;
3804   from = atoi (num_str);
3805   tmp = StringLen (num_str);
3806   if (tmp > 1 && num_str[tmp - 1] == '^')
3807   {
3808     is_caret = TRUE;
3809   }
3810   num_str = MemFree (num_str);
3811   num_str = SaveStringFromText (afp->right_end);
3812   if (num_str == NULL) return;
3813   if (num_str[0] == '^') {
3814     is_caret = TRUE;
3815     to = atoi (num_str + 1);
3816   } else {
3817     to = atoi (num_str);
3818   }
3819   num_str = MemFree (num_str);
3820   if (from > to)
3821   {
3822   	tmp = from;
3823   	from = to;
3824   	to = tmp;
3825   }
3826   if (from < 1)
3827   {
3828   	from = 1;
3829   }
3830   if (to < 1)
3831   {
3832     if (to == 0 && is_caret) {
3833       to = from + 1;
3834     } else {
3835   	  to = 1;
3836   	}
3837   }
3838   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
3839   strand = SeqLocStrand (sfp->location);
3840   if (to > bsp->length)
3841   {
3842   	to = bsp->length;
3843   	partial3 = TRUE;
3844   }
3845 
3846   if (is_caret && to != from + 1) {
3847     is_caret = FALSE;
3848   }
3849 
3850   slp = NULL;
3851   if (is_caret) {
3852     AddSeqLocPoint (&slp, SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0))),
3853                     from, FALSE, TRUE, strand);
3854   } else {
3855     slp = ValNodeNew (NULL);
3856     if (slp != NULL) {
3857       sip = SeqIntNew ();
3858       if (sip != NULL) {
3859         sip->from = from - 1;
3860         sip->to = to - 1;
3861         sip->strand = strand;
3862         sip->id = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
3863         slp->choice = SEQLOC_INT;
3864         slp->data.ptrvalue = (Pointer) sip;
3865         SetSeqLocPartial (slp, partial5, partial3);
3866       }
3867     }
3868   }
3869 
3870   sfp->location = SeqLocFree (sfp->location);
3871   sfp->location = slp;
3872 
3873   if (partial5 || partial3)
3874   {
3875   	sfp->partial = TRUE;
3876   }
3877 
3878 }
3879 
SetApplyFeatureLocation(SeqFeatPtr sfp,ApplyFormPtr afp)3880 static void SetApplyFeatureLocation (SeqFeatPtr sfp, ApplyFormPtr afp)
3881 {
3882   if (sfp == NULL || afp == NULL)
3883   {
3884     return;
3885   }
3886 
3887   if (GetValue (afp->strand_group) == 2)
3888   {
3889     /* reverse strand direction - strand direction is plus by default */
3890     setSeqFeatStrand (sfp, Seq_strand_minus);
3891   }
3892 
3893   SetSeqLocPartial (sfp->location, afp->noLeft, afp->noRight);
3894 
3895   if (afp->use_whole_interval != NULL
3896       && GetValue (afp->use_whole_interval) != 1)
3897   {
3898     /* adjust location to match coordinates from user */
3899     AdjustSeqLocForApply (sfp, afp);
3900   }
3901 
3902   sfp->partial = (afp->noLeft || afp->noRight);
3903 }
3904 
AddGeneXrefToFeat(SeqFeatPtr sfp,CharPtr str)3905 static void AddGeneXrefToFeat (SeqFeatPtr sfp, CharPtr str)
3906 {
3907   SeqFeatXrefPtr    xref;
3908   GeneRefPtr        grp;
3909 
3910   if (sfp == NULL || StringHasNoText (str)) return;
3911 
3912   /* add gene xref to feature */
3913   xref = SeqFeatXrefNew ();
3914   if (xref != NULL)
3915   {
3916     grp = CreateNewGeneRef (str, NULL, NULL, FALSE);
3917     if (grp != NULL)
3918     {
3919       xref->data.choice = SEQFEAT_GENE;
3920       xref->data.value.ptrvalue = grp;
3921       xref->next = sfp->xref;
3922       sfp->xref = xref;
3923     }
3924   }
3925 }
3926 
ApplyGene(CharPtr str,ApplyFormPtr afp,SeqEntryPtr gene_sep,SeqFeatPtr sfp)3927 static SeqFeatPtr ApplyGene (CharPtr str, ApplyFormPtr afp, SeqEntryPtr gene_sep, SeqFeatPtr sfp)
3928 {
3929   GeneRefPtr        grp;
3930   SeqFeatPtr        gene_sfp;
3931   SeqFeatXrefPtr    xref;
3932   SeqMgrFeatContext fcontext;
3933   BioseqPtr         bsp = NULL;
3934   SeqFeatPtr        other_feat;
3935   SeqFeatPtr        overlap_gene;
3936   Boolean           added_xrefs = FALSE;
3937   SeqFeatPtr        misc_feat = NULL;
3938   SeqLocPtr         overlap_loc;
3939   CharPtr           gene_desc = NULL;
3940 
3941   if (afp == NULL || gene_sep == NULL
3942 	  || (StringHasNoText (str)
3943 	      && (afp->feature_details_data == NULL
3944 		      || StringHasNoText (afp->feature_details_data->geneDesc))))
3945   {
3946     return NULL;
3947   }
3948 
3949   if (afp != NULL && afp->feature_details_data != NULL)
3950   {
3951     gene_desc = afp->feature_details_data->geneDesc;
3952   }
3953 
3954   /* we need a location to use when we're checking for feature-stealing genes */
3955   if (sfp != NULL)
3956   {
3957     overlap_loc = sfp->location;
3958   }
3959   else
3960   {
3961     misc_feat = CreateNewFeature (gene_sep, NULL, SEQFEAT_COMMENT, NULL);
3962     if (NULL == misc_feat)
3963     return NULL;
3964 
3965     SetApplyFeatureLocation (misc_feat, afp);
3966 
3967     overlap_loc = misc_feat->location;
3968   }
3969 
3970   /* first, add gene xrefs to all features on bioseq that are contained in the location */
3971   /* maintain list of features that had xrefs before, should not remove them later */
3972   if (IS_Bioseq (gene_sep))
3973   {
3974     bsp = (BioseqPtr) gene_sep->data.ptrvalue;
3975   }
3976   else if (sfp != NULL)
3977   {
3978     bsp = BioseqFindFromSeqLoc (sfp->location);
3979   }
3980   if (bsp != NULL)
3981   {
3982     other_feat = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
3983     while (other_feat != NULL)
3984     {
3985       if (other_feat != sfp && other_feat->data.choice != SEQFEAT_GENE)
3986       {
3987         for (xref = other_feat->xref;
3988              xref != NULL && xref->data.choice != SEQFEAT_GENE;
3989              xref = xref->next)
3990         {}
3991         if (xref == NULL
3992             && SeqLocCompare (other_feat->location, overlap_loc) == SLC_A_EQ_B)
3993         {
3994           overlap_gene = SeqMgrGetOverlappingGene (other_feat->location, &fcontext);
3995           if (overlap_gene != NULL)
3996           {
3997             AddGeneXrefToFeat (other_feat, fcontext.label);
3998             added_xrefs = TRUE;
3999           }
4000         }
4001       }
4002       other_feat = SeqMgrGetNextFeature (bsp, other_feat, 0, 0, &fcontext);
4003     }
4004   }
4005 
4006   if (misc_feat != NULL)
4007   {
4008     misc_feat->idx.deleteme = TRUE;
4009     DeleteMarkedObjects (0, OBJ_SEQENTRY, gene_sep);
4010   }
4011 
4012   grp = CreateNewGeneRef (str, NULL, gene_desc, FALSE);
4013   if (NULL == grp)
4014     return NULL;
4015 
4016   gene_sfp = CreateNewFeature (gene_sep, NULL, SEQFEAT_GENE, NULL);
4017   if (NULL == gene_sfp)
4018     return NULL;
4019 
4020   gene_sfp->data.value.ptrvalue = (Pointer) grp;
4021 
4022   SetApplyFeatureLocation (gene_sfp, afp);
4023 
4024   if (added_xrefs && sfp != NULL)
4025   {
4026     /* add gene xref to feature */
4027     AddGeneXrefToFeat (sfp, str);
4028   }
4029 
4030   return gene_sfp;
4031 }
4032 
4033 
4034 typedef struct adjustfeatforgapdialog {
4035   DIALOG_MESSAGE_BLOCK
4036   DialoG feature_select;
4037   ButtoN unknown_gaps;
4038   ButtoN known_gaps;
4039   GrouP  partial_grp;
4040   ButtoN trim_ends;
4041   ButtoN split_internal;
4042   ButtoN split_in_intron;
4043 
4044   Nlm_ChangeNotifyProc     change_notify;
4045   Pointer                  change_userdata;
4046 } AdjustFeatForGapDialogData, PNTR AdjustFeatForGapDialogPtr;
4047 
4048 
AdjustFeaturesForGapToDialog(DialoG d,Pointer udata)4049 static void AdjustFeaturesForGapToDialog (DialoG d, Pointer udata)
4050 {
4051   AdjustFeatForGapDialogPtr dlg;
4052   AdjustFeatForGapPtr       data;
4053 
4054   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (d);
4055   data = (AdjustFeatForGapPtr) udata;
4056 
4057   if (dlg == NULL) return;
4058 
4059   if (data == NULL) {
4060     PointerToDialog (dlg->feature_select, NULL);
4061     SetStatus (dlg->unknown_gaps, FALSE);
4062     SetStatus (dlg->known_gaps, FALSE);
4063     SetStatus (dlg->trim_ends, FALSE);
4064     SetStatus (dlg->split_internal, FALSE);
4065     SetStatus (dlg->split_in_intron, FALSE);
4066     Disable (dlg->split_in_intron);
4067     SetValue (dlg->partial_grp, 2);
4068   } else {
4069     PointerToDialog (dlg->feature_select, data->feature_list);
4070     SetStatus (dlg->unknown_gaps, data->options & eAdjustFeatForGap_unknown_gaps);
4071     SetStatus (dlg->known_gaps, data->options & eAdjustFeatForGap_known_gaps);
4072     SetStatus (dlg->split_internal, data->options & eAdjustFeatForGap_split_internal);
4073     SetStatus (dlg->split_in_intron, data->options & eAdjustFeatForGap_split_in_intron);
4074     if (!(data->options & eAdjustFeatForGap_split_internal)) {
4075       Disable (dlg->split_in_intron);
4076     }
4077     SetStatus (dlg->trim_ends, data->options & eAdjustFeatForGap_trim_ends);
4078 
4079     if ((data->options & eAdjustFeatForGap_make_partial) && (data->options & eAdjustFeatForGap_partial_for_pseudo)) {
4080       SetValue (dlg->partial_grp, 1);
4081     } else if ((data->options & eAdjustFeatForGap_make_partial) && !(data->options & eAdjustFeatForGap_partial_for_pseudo)) {
4082       SetValue (dlg->partial_grp, 2);
4083     } else {
4084       SetValue (dlg->partial_grp, 3);
4085     }
4086   }
4087 }
4088 
4089 
AdjustFeaturesForGapToPointer(DialoG d)4090 static Pointer AdjustFeaturesForGapToPointer (DialoG d)
4091 {
4092   AdjustFeatForGapDialogPtr dlg;
4093   AdjustFeatForGapPtr       data;
4094   Int4                      grp_val;
4095 
4096   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (d);
4097 
4098   if (dlg == NULL) return NULL;
4099 
4100   data = (AdjustFeatForGapPtr) MemNew (sizeof (AdjustFeatForGapData));
4101 
4102   /* get list of feature types to ask on */
4103   data->feature_list = (ValNodePtr) DialogToPointer (dlg->feature_select);
4104   data->features_in_gap = NULL;
4105 
4106   if (GetStatus (dlg->unknown_gaps)) {
4107     data->options |= eAdjustFeatForGap_unknown_gaps;
4108   }
4109   if (GetStatus (dlg->known_gaps)) {
4110     data->options |= eAdjustFeatForGap_known_gaps;
4111   }
4112 
4113   grp_val = GetValue (dlg->partial_grp);
4114   switch (grp_val) {
4115     case 1:
4116       data->options |= eAdjustFeatForGap_make_partial | eAdjustFeatForGap_partial_for_pseudo;
4117       break;
4118     case 2:
4119       data->options |= eAdjustFeatForGap_make_partial;
4120       break;
4121     case 3:
4122       /* both false */
4123       break;
4124   }
4125 
4126   if (GetStatus (dlg->split_internal)) {
4127     data->options |= eAdjustFeatForGap_split_internal;
4128     if (GetStatus (dlg->split_in_intron)) {
4129       data->options |= eAdjustFeatForGap_split_in_intron;
4130     }
4131   }
4132   if (GetStatus (dlg->trim_ends)) {
4133     data->options |= eAdjustFeatForGap_trim_ends;
4134   }
4135 
4136   return (Pointer) data;
4137 }
4138 
4139 
TestAdjustForGapsDialog(DialoG d)4140 static ValNodePtr TestAdjustForGapsDialog (DialoG d)
4141 {
4142   AdjustFeatForGapDialogPtr dlg;
4143   AdjustFeatForGapPtr       data;
4144   ValNodePtr                err_list = NULL;
4145 
4146   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (d);
4147   if (dlg == NULL)
4148   {
4149     ValNodeAddPointer (&err_list, 0, "No dialog");
4150     return err_list;
4151   }
4152 
4153   data = (AdjustFeatForGapPtr) DialogToPointer (d);
4154   if (data == NULL)
4155   {
4156     ValNodeAddPointer (&err_list, 0, "No data");
4157     return err_list;
4158   }
4159 
4160   if (data->feature_list == NULL)
4161   {
4162     ValNodeAddPointer (&err_list, 0, "No features");
4163   }
4164 
4165   if (!(data->options & eAdjustFeatForGap_unknown_gaps) && !(data->options & eAdjustFeatForGap_known_gaps))
4166   {
4167     ValNodeAddPointer (&err_list, 0, "No gaps");
4168   }
4169 
4170   if (!(data->options & eAdjustFeatForGap_split_internal) && !(data->options & eAdjustFeatForGap_trim_ends))
4171   {
4172     ValNodeAddPointer (&err_list, 0, "No action");
4173   }
4174 
4175   data = AdjustFeatForGapFree (data);
4176 
4177   return err_list;
4178 }
4179 
4180 
AdjustFeaturesForGapsChangeNotifyButton(ButtoN b)4181 static void AdjustFeaturesForGapsChangeNotifyButton (ButtoN b)
4182 {
4183   AdjustFeatForGapDialogPtr dlg;
4184 
4185   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (b);
4186   if (GetStatus (dlg->split_internal)) {
4187     Enable (dlg->split_in_intron);
4188   } else {
4189     Disable (dlg->split_in_intron);
4190   }
4191   if (dlg != NULL && dlg->change_notify != NULL) {
4192     (dlg->change_notify) (dlg->change_userdata);
4193   }
4194 }
4195 
4196 
AdjustFeaturesForGapsChangeNotifyGroup(GrouP g)4197 static void AdjustFeaturesForGapsChangeNotifyGroup (GrouP g)
4198 {
4199   AdjustFeatForGapDialogPtr dlg;
4200 
4201   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (g);
4202   if (dlg != NULL && dlg->change_notify != NULL) {
4203     (dlg->change_notify) (dlg->change_userdata);
4204   }
4205 }
4206 
4207 
AdjustFeaturesForGapDialog(GrouP h,Uint2 entityID,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)4208 static DialoG AdjustFeaturesForGapDialog (GrouP h, Uint2 entityID, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
4209 {
4210   AdjustFeatForGapDialogPtr dlg;
4211   GrouP                     p, g, g2;
4212   SeqEntryPtr               sep;
4213 
4214   dlg = (AdjustFeatForGapDialogPtr) MemNew (sizeof (AdjustFeatForGapDialogData));
4215   if (dlg == NULL) return NULL;
4216 
4217   p = HiddenGroup (h, -1, 0, NULL);
4218   SetObjectExtra (p, dlg, StdCleanupExtraProc);
4219   SetGroupSpacing (p, 10, 10);
4220 
4221   dlg->dialog = (DialoG) p;
4222   dlg->todialog = AdjustFeaturesForGapToDialog;
4223   dlg->fromdialog = AdjustFeaturesForGapToPointer;
4224   dlg->dialogmessage = NULL;
4225   dlg->testdialog = TestAdjustForGapsDialog;
4226   dlg->change_notify = change_notify;
4227   dlg->change_userdata = change_userdata;
4228 
4229   sep = GetTopSeqEntryForEntityID (entityID);
4230   dlg->feature_select = FeatureSelectionDialogEx (p, TRUE, sep,
4231                                                   change_notify,
4232                                                   change_userdata);
4233 
4234   g = HiddenGroup (p, 2, 0, NULL);
4235   dlg->unknown_gaps = CheckBox (g, "Unknown length gaps", AdjustFeaturesForGapsChangeNotifyButton);
4236   SetObjectExtra (dlg->unknown_gaps, dlg, NULL);
4237   dlg->known_gaps = CheckBox (g, "Known length gaps", AdjustFeaturesForGapsChangeNotifyButton);
4238   SetObjectExtra (dlg->known_gaps, dlg, NULL);
4239 
4240   dlg->partial_grp = NormalGroup (p, 3, 0, "Make truncated ends partial", programFont, AdjustFeaturesForGapsChangeNotifyGroup);
4241   SetObjectExtra (dlg->partial_grp, dlg, NULL);
4242   RadioButton (dlg->partial_grp, "Always");
4243   RadioButton (dlg->partial_grp, "Unless pseudo");
4244   RadioButton (dlg->partial_grp, "Never");
4245   SetValue (dlg->partial_grp, 2);
4246 
4247   g2 = HiddenGroup (p, 3, 0, NULL);
4248   dlg->trim_ends = CheckBox (g2, "Trim ends in gaps", AdjustFeaturesForGapsChangeNotifyButton);
4249   SetObjectExtra (dlg->trim_ends, dlg, NULL);
4250   dlg->split_internal = CheckBox (g2, "Split for internal gaps", AdjustFeaturesForGapsChangeNotifyButton);
4251   SetObjectExtra (dlg->split_internal, dlg, NULL);
4252   dlg->split_in_intron = CheckBox (g2, "(Even when gaps are in introns)", AdjustFeaturesForGapsChangeNotifyButton);
4253   SetObjectExtra (dlg->split_in_intron, dlg, NULL);
4254   Disable (dlg->split_in_intron);
4255 
4256   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_select, (HANDLE) g, (HANDLE) dlg->partial_grp, (HANDLE) g2, NULL);
4257   return (DialoG) p;
4258 }
4259 
4260 typedef struct adjustfeatforgapform {
4261   FORM_MESSAGE_BLOCK
4262 
4263   DialoG dlg;
4264   DialoG clickable_list;
4265   ButtoN accept_btn;
4266 
4267   ValNodePtr feat_list;
4268 } AdjustFeatforGapFormData, PNTR AdjustFeatForGapFormPtr;
4269 
4270 
4271 typedef struct featforadjust {
4272   AdjustFeatForGapPtr afgp;
4273   ValNodePtr          features_to_adjust;
4274   ValNodePtr          features_contain_gap;
4275   ValNodePtr          features_in_gap;
4276 } FeatForAdjustData, PNTR FeatForAdjustPtr;
4277 
4278 
FindFeaturesToBeAdjustedForGapsCallback(SeqFeatPtr sfp,Pointer data)4279 static void FindFeaturesToBeAdjustedForGapsCallback (SeqFeatPtr sfp, Pointer data)
4280 {
4281   FeatForAdjustPtr faap;
4282   BioseqPtr   gapped_bioseq;
4283   Boolean     terminal_gaps = FALSE;
4284   Boolean     entirely_in_gap = FALSE;
4285   Boolean     internal_gaps = FALSE;
4286 
4287   if (sfp == NULL || data == NULL) return;
4288 
4289   faap = (FeatForAdjustPtr) data;
4290   if (faap->afgp == NULL) return;
4291 
4292   if (!FeatureOkForFeatureList(sfp, faap->afgp->feature_list)) return;
4293 
4294   gapped_bioseq = BioseqFind (SeqLocId (sfp->location));
4295 
4296   LocationContainsGaps (sfp->location, gapped_bioseq, faap->afgp->options, &terminal_gaps, &internal_gaps, &entirely_in_gap);
4297   if (entirely_in_gap)
4298   {
4299     ValNodeAddPointer (&(faap->features_in_gap), OBJ_SEQFEAT, sfp);
4300   }
4301 
4302   if (internal_gaps)
4303   {
4304     ValNodeAddPointer (&(faap->features_contain_gap), OBJ_SEQFEAT, sfp);
4305   }
4306 
4307   if (((faap->afgp->options & eAdjustFeatForGap_split_internal) && internal_gaps)
4308       || ((faap->afgp->options & eAdjustFeatForGap_trim_ends) && terminal_gaps))
4309   {
4310     ValNodeAddPointer (&(faap->features_to_adjust), OBJ_SEQFEAT, sfp);
4311   }
4312 }
4313 
4314 
AdjustFeaturesForGapsChangeNotify(Pointer data)4315 static void AdjustFeaturesForGapsChangeNotify (Pointer data)
4316 {
4317   AdjustFeatForGapFormPtr dlg;
4318   FeatForAdjustData       ffad;
4319   ValNodePtr              err_list;
4320   SeqEntryPtr             sep;
4321   ClickableItemPtr        cip;
4322 
4323   dlg = (AdjustFeatForGapFormPtr) data;
4324 
4325   if (dlg == NULL) return;
4326 
4327   err_list = TestDialog (dlg->dlg);
4328   if (err_list == NULL)
4329   {
4330     Enable (dlg->accept_btn);
4331   }
4332   else
4333   {
4334     err_list = ValNodeFree (err_list);
4335     Disable (dlg->accept_btn);
4336   }
4337 
4338   /* clear clickable list display */
4339   PointerToDialog (dlg->clickable_list, NULL);
4340   /* re-create list of features */
4341   dlg->feat_list = FreeClickableList (dlg->feat_list);
4342 
4343   ffad.afgp = DialogToPointer (dlg->dlg);
4344   ffad.features_contain_gap = NULL;
4345   ffad.features_in_gap = NULL;
4346   ffad.features_to_adjust = NULL;
4347 
4348   if (ffad.afgp->feature_list != NULL)
4349   {
4350     sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
4351     VisitFeaturesInSep (sep, &(ffad), FindFeaturesToBeAdjustedForGapsCallback);
4352   }
4353 
4354   if (ffad.features_to_adjust != NULL) {
4355     cip = NewClickableItem (0, "%d features will be adjusted", ffad.features_to_adjust);
4356     ValNodeAddPointer (&(dlg->feat_list), 0, cip);
4357   }
4358   if (ffad.features_in_gap != NULL) {
4359     cip = NewClickableItem (0, "%d features are completely contained in gaps and will be deleted", ffad.features_in_gap);
4360     ValNodeAddPointer (&(dlg->feat_list), 0, cip);
4361   }
4362   if (ffad.features_contain_gap != NULL) {
4363     cip = NewClickableItem (0, "%d features contain internal gaps", ffad.features_contain_gap);
4364     ValNodeAddPointer (&(dlg->feat_list), 0, cip);
4365   }
4366 
4367   /* pass list of features to clickable list display */
4368   PointerToDialog (dlg->clickable_list, dlg->feat_list);
4369 
4370 }
4371 
4372 
DoAdjustFeaturesForGaps(ButtoN b)4373 static void DoAdjustFeaturesForGaps (ButtoN b)
4374 {
4375   AdjustFeatForGapFormPtr dlg;
4376   AdjustFeatForGapPtr     data;
4377   SeqEntryPtr             sep;
4378 
4379   dlg = (AdjustFeatForGapFormPtr) GetObjectExtra (b);
4380 
4381   if (dlg == NULL) return;
4382 
4383   data = (AdjustFeatForGapPtr) DialogToPointer (dlg->dlg);
4384 
4385   sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
4386   VisitFeaturesInSep (sep, data, AdjustFeatureForGapsCallback);
4387 
4388   /* remove features entirely in the gap */
4389   MarkFeaturesInGapsForDeletion (data);
4390   DeleteMarkedObjects (dlg->input_entityID, 0, NULL);
4391   RenormalizeNucProtSets (sep, TRUE);
4392 
4393   ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
4394   ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
4395 
4396   data = AdjustFeatForGapFree(data);
4397 
4398   Remove (dlg->form);
4399 }
4400 
4401 
MakeGapFeatureReport(ButtoN b)4402 static void MakeGapFeatureReport (ButtoN b)
4403 {
4404   FILE                    *fp;
4405   Char                    path [PATH_MAX];
4406   AdjustFeatForGapFormPtr dlg;
4407   Int4                    num_disc = 0;
4408   Boolean                 show_all = FALSE;
4409 
4410 
4411   dlg = (AdjustFeatForGapFormPtr) GetObjectExtra (b);
4412 
4413   if (dlg == NULL) return;
4414 
4415   num_disc = CountChosenDiscrepancies (dlg->feat_list, FALSE);
4416 
4417   if (num_disc == 0)
4418   {
4419     if (ANS_CANCEL == Message (MSG_OKC, "No items selected!  Export all?"))
4420     {
4421       return;
4422     }
4423     else
4424     {
4425       show_all = TRUE;
4426     }
4427   }
4428 
4429   path [0] = '\0';
4430   if (GetOutputFileName (path, sizeof (path), NULL)) {
4431 #ifdef WIN_MAC
4432     fp = FileOpen (path, "r");
4433     if (fp != NULL) {
4434       FileClose (fp);
4435     } else {
4436       FileCreate (path, "TEXT", "ttxt");
4437     }
4438 #endif
4439     fp = FileOpen (path, "w");
4440     if (fp != NULL) {
4441       WriteClickableListReport (fp, dlg->feat_list, show_all, FALSE);
4442       FileClose (fp);
4443       return;
4444     }
4445   }
4446 }
4447 
4448 
AdjustFeaturesForGaps(IteM i)4449 extern void AdjustFeaturesForGaps (IteM i)
4450 {
4451   BaseFormPtr             bfp;
4452   AdjustFeatForGapFormPtr dlg;
4453   WindoW                  w;
4454   GrouP                   h, c;
4455   ButtoN                  b;
4456 
4457 #ifdef WIN_MAC
4458   bfp = currentFormDataPtr;
4459 #else
4460   bfp = GetObjectExtra (i);
4461 #endif
4462   if (bfp == NULL) return;
4463 
4464   dlg = (AdjustFeatForGapFormPtr) MemNew (sizeof (AdjustFeatforGapFormData));
4465   if (dlg == NULL) return;
4466 
4467   w = FixedWindow (-50, -33, -10, -10, "Adjust Features for Gaps", StdCloseWindowProc);
4468   SetObjectExtra (w, dlg, StdCleanupFormProc);
4469   dlg->form = (ForM) w;
4470   dlg->input_entityID = bfp->input_entityID;
4471   h = HiddenGroup (w, -1, 0, NULL);
4472   SetGroupSpacing (h, 10, 10);
4473 
4474   dlg->clickable_list =  CreateClickableListDialogEx (h, "", "Features", NULL, NULL,
4475                                                       ScrollToDiscrepancyItem, EditDiscrepancyItem, NULL,
4476                                                       GetDiscrepancyItemText,
4477                                                       stdCharWidth * 15,
4478                                                       stdCharWidth * 30,
4479                                                       TRUE, TRUE);
4480 
4481   dlg->dlg = AdjustFeaturesForGapDialog (h, bfp->input_entityID, AdjustFeaturesForGapsChangeNotify, dlg);
4482 
4483   c = HiddenGroup (h, 3, 0, NULL);
4484   SetGroupSpacing (c, 10, 10);
4485   dlg->accept_btn = PushButton (c, "Accept", DoAdjustFeaturesForGaps);
4486   SetObjectExtra (dlg->accept_btn, dlg, NULL);
4487   PushButton (c, "Cancel", StdCancelButtonProc);
4488   b = PushButton (c, "Make Report", MakeGapFeatureReport);
4489   SetObjectExtra (b, dlg, NULL);
4490   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->clickable_list,
4491                               (HANDLE) dlg->dlg,
4492                               (HANDLE) c,
4493                               NULL);
4494   RealizeWindow (w);
4495   AdjustFeaturesForGapsChangeNotify (dlg);
4496   Show (w);
4497   Select (w);
4498 }
4499 
4500 
FreeLocList(ValNodePtr vnp)4501 static ValNodePtr FreeLocList(ValNodePtr vnp)
4502 {
4503   ValNodePtr vnp_next;
4504 
4505   while (vnp != NULL) {
4506     vnp_next = vnp->next;
4507     vnp->next = NULL;
4508     vnp->data.ptrvalue = SeqLocFree(vnp->data.ptrvalue);
4509     vnp = ValNodeFree (vnp);
4510     vnp = vnp_next;
4511   }
4512   return vnp;
4513 }
4514 
4515 
FrameFromShiftAndStart(Int4 shift,Int4 start)4516 static Int4 FrameFromShiftAndStart(Int4 shift, Int4 start)
4517 {
4518     Int4 rval = 0;
4519     switch (start) {
4520       case 0:
4521       case 1:
4522         switch (shift % 3) {
4523           case 0:
4524             rval = 1;
4525             break;
4526           case 1:
4527             rval = 3;
4528             break;
4529           case 2:
4530             rval = 2;
4531             break;
4532           default:
4533             break;
4534         }
4535         break;
4536       case 2:
4537         switch (shift % 3) {
4538           case 0:
4539             rval = 2;
4540             break;
4541           case 1:
4542             rval = 1;
4543             break;
4544           case 2:
4545             rval = 3;
4546             break;
4547           default:
4548             break;
4549         }
4550         break;
4551       case 3:
4552         switch (shift % 3) {
4553           case 0:
4554             rval = 3;
4555             break;
4556           case 1:
4557             rval = 2;
4558             break;
4559           case 2:
4560             rval = 1;
4561             break;
4562           default:
4563             break;
4564         }
4565         break;
4566     }
4567     return rval;
4568 }
4569 
4570 
TrimCodingRegionsFoNsCallback(BioseqPtr bsp,Pointer userdata)4571 static void TrimCodingRegionsFoNsCallback(BioseqPtr bsp, Pointer userdata)
4572 {
4573   SeqMgrFeatContext  fcontext;
4574   SeqFeatPtr         cds, gene;
4575   SeqIdPtr           sip;
4576   SeqLocPtr          slp, sp, cut;
4577   Boolean            partial5, partial3, is_start;
4578   ValNodePtr         vnp, s_vnp, cut_list_5, cut_list_3;
4579   Int4               len, n_start_len, n_end_len, offset;
4580   CharPtr            bases;
4581   SeqIntPtr          sintp;
4582   Int4               start, stop;
4583   Uint1              strand;
4584   CdRegionPtr        crp;
4585   Boolean            any_cut;
4586 
4587   if (bsp == NULL) {
4588     return;
4589   }
4590   for (cds = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &fcontext);
4591        cds != NULL;
4592        cds = SeqMgrGetNextFeature (bsp, cds, SEQFEAT_CDREGION, 0, &fcontext))
4593   {
4594       gene = GetGeneForFeature(cds);
4595       CheckSeqLocForPartial (cds->location, &partial5, &partial3);
4596 
4597       /* trim leading Ns, adjust frame */
4598       cut_list_5 = NULL;
4599       cut_list_3 = NULL;
4600       is_start = TRUE;
4601       n_start_len = 0;
4602       n_end_len = 0;
4603       for (sp = SeqLocFindNext(cds->location, NULL);
4604            sp != NULL;
4605            sp = sp->next) {
4606         sip = SeqLocId (sp);
4607         if (sip == NULL) {
4608           continue;
4609         }
4610         len = SeqLocLen(sp);
4611         bases = (CharPtr) MemNew (sizeof (Char) * len + 1);
4612         MemSet (bases, 0, len + 1);
4613         SeqPortStreamLoc (sp, STREAM_EXPAND_GAPS, (Pointer) bases, NULL);
4614         if (is_start) {
4615           offset = StrSpn(bases, "N");
4616           if (offset > 0) {
4617             /* add piece to cut_list_5 to be removed later */
4618             sintp = SeqIntNew();
4619             sintp->id = SeqIdDup(sip);
4620             start = SeqLocStart(sp);
4621             stop = SeqLocStop(sp);
4622             strand = SeqLocStrand(sp);
4623             if (strand == Seq_strand_minus) {
4624               sintp->to = stop;
4625               sintp->from = stop - offset + 1;
4626               sintp->strand = Seq_strand_minus;
4627             } else {
4628               sintp->from = start;
4629               sintp->to = start + offset - 1;
4630             }
4631             vnp = ValNodeNew(NULL);
4632             vnp->choice = SEQLOC_INT;
4633             vnp->data.ptrvalue = sintp;
4634             ValNodeAddPointer(&cut_list_5, 0, vnp);
4635             n_start_len += offset;
4636           }
4637           if (offset < len) {
4638             is_start = FALSE;
4639           }
4640         }
4641 
4642         if (!is_start) {
4643           /* look for Ns at the right end. Will remove prior list if this interval is not all Ns */
4644           offset = 0;
4645           while (offset < len && bases[len - offset - 1] == 'N') {
4646             offset++;
4647           }
4648           if (offset < len) {
4649             cut_list_3 = FreeLocList(cut_list_3);
4650             n_end_len = 0;
4651           }
4652           if (offset > 0) {
4653             /* add piece to cut_list_3 to be removed later */
4654             sintp = SeqIntNew();
4655             sintp->id = SeqIdDup(sip);
4656             start = SeqLocStart(sp);
4657             stop = SeqLocStop(sp);
4658             strand = SeqLocStrand(sp);
4659             if (strand == Seq_strand_minus) {
4660               sintp->from = start;
4661               sintp->to = start + offset - 1;
4662               sintp->strand = Seq_strand_minus;
4663             } else {
4664               sintp->to = stop;
4665               sintp->from = stop - offset + 1;
4666             }
4667             vnp = ValNodeNew(NULL);
4668             vnp->choice = SEQLOC_INT;
4669             vnp->data.ptrvalue = sintp;
4670             /* add cut to front of list so we can remove in reverse order */
4671             s_vnp = ValNodeNew (NULL);
4672             s_vnp->data.ptrvalue = vnp;
4673             s_vnp->next = cut_list_3;
4674             cut_list_3 = s_vnp;
4675             n_end_len += offset;
4676           }
4677         }
4678         bases = MemFree (bases);
4679       }
4680       any_cut = FALSE;
4681       if (n_start_len > 0) {
4682         any_cut = TRUE;
4683         partial5 = TRUE;
4684         /* adjust cds frame */
4685         crp = (CdRegionPtr) cds->data.value.ptrvalue;
4686         crp->frame = FrameFromShiftAndStart(n_start_len, crp->frame);
4687         /* trim from front */
4688         for (vnp = cut_list_5; vnp != NULL; vnp = vnp->next) {
4689           cds->location = SeqLocSubtract(cds->location, vnp->data.ptrvalue);
4690         }
4691       }
4692       if (n_end_len > 0) {
4693         any_cut = TRUE;
4694         partial3 = TRUE;
4695         /* trim from back */
4696         for (vnp = cut_list_3; vnp != NULL; vnp = vnp->next) {
4697           cds->location = SeqLocSubtract(cds->location, vnp->data.ptrvalue);
4698         }
4699       }
4700       if (cds->location == NULL) {
4701         cds->location = ValNodeNew(NULL);
4702         cds->location->choice = SEQLOC_NULL;
4703         cds->idx.deleteme = TRUE;
4704       } else if (any_cut) {
4705         SetSeqLocPartial (cds->location, partial5, partial3);
4706         cds->partial = partial5 || partial3;
4707         SetStringValue (&(cds->comment), "nucleotide span adjusted for sequencing gap", ExistingTextOption_append_semi);
4708         /* also adjust gene feature */
4709         if (gene) {
4710           gene->location = SeqLocFree(gene->location);
4711           gene->location = SeqLocMerge (bsp, cds->location, NULL, TRUE, FALSE, FALSE);
4712         }
4713       }
4714       cut_list_5 = FreeLocList(cut_list_5);
4715       cut_list_3 = FreeLocList(cut_list_3);
4716     }
4717 
4718 }
4719 
4720 
TrimCodingRegionsForNs(IteM i)4721 extern void TrimCodingRegionsForNs (IteM i)
4722 {
4723   BaseFormPtr             bfp;
4724   SeqEntryPtr             sep;
4725 
4726 #ifdef WIN_MAC
4727   bfp = currentFormDataPtr;
4728 #else
4729   bfp = GetObjectExtra (i);
4730 #endif
4731   if (bfp == NULL) return;
4732 
4733   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4734   if (sep == NULL) return;
4735 
4736   VisitBioseqsInSep (sep, NULL, TrimCodingRegionsFoNsCallback);
4737   DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
4738   RetranslateCdRegionsEx (bfp->input_entityID, TRUE, TRUE);
4739   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
4740   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
4741 }
4742 
4743 
GapLocationsFromNs(BioseqPtr bsp,Int4Ptr gap_sizes)4744 static ValNodePtr GapLocationsFromNs (BioseqPtr bsp, Int4Ptr gap_sizes)
4745 
4746 {
4747   CharPtr     bases, txt;
4748   Char        ch;
4749   Int4        len;
4750   ValNodePtr  seq_ext;
4751   Boolean     unknown_greater_than_or_equal = FALSE;
4752   Boolean     known_greater_than_or_equal = FALSE;
4753   Int4        unknown_gap_size = 0;
4754   Int4        known_gap_size = 0;
4755   Int4        gap_len;
4756   Boolean     make_unknown_size;
4757   GapLocInfoPtr glip;
4758   ValNodePtr  result_list = NULL;
4759   Int4        start_pos = 0;
4760 
4761 
4762   if (bsp == NULL || bsp->repr != Seq_repr_raw || ISA_aa (bsp->mol))
4763   {
4764     return NULL;
4765   }
4766 
4767   if (gap_sizes == NULL)
4768   {
4769     known_greater_than_or_equal = TRUE;
4770   }
4771   else
4772   {
4773     unknown_gap_size = gap_sizes[0];
4774     known_gap_size = gap_sizes[1];
4775     if (unknown_gap_size < 0)
4776     {
4777       unknown_greater_than_or_equal = TRUE;
4778       unknown_gap_size = 0 - unknown_gap_size;
4779     }
4780     if (known_gap_size < 0)
4781     {
4782       known_greater_than_or_equal = TRUE;
4783       known_gap_size = 0 - known_gap_size;
4784     }
4785   }
4786 
4787   bases = GetSequenceByBsp (bsp);
4788   if (bases == NULL) return NULL;
4789 
4790   for (txt = bases, ch = *txt; ch != '\0'; txt++, ch = *txt) {
4791     if (ch == 'N') break;
4792   }
4793   if (ch != 'N') {
4794     MemFree (bases);
4795     return NULL;
4796   }
4797 
4798   seq_ext = NULL;
4799   len = 0;
4800 
4801   txt = bases;
4802   ch = *txt;
4803 
4804   gap_len = 0;
4805   while (ch != '\0') {
4806 
4807     if (ch == 'N') {
4808       gap_len = StringSpn (txt, "N");
4809       if (gap_len == unknown_gap_size
4810           || (gap_len > unknown_gap_size && unknown_greater_than_or_equal)
4811           || gap_len == known_gap_size
4812           || (gap_len > known_gap_size && known_greater_than_or_equal))
4813       {
4814         make_unknown_size = FALSE;
4815         if (gap_len == 0)
4816         {
4817           make_unknown_size = FALSE;
4818         }
4819         else if (gap_len == unknown_gap_size)
4820         {
4821           make_unknown_size = TRUE;
4822         }
4823         else if (gap_len == known_gap_size)
4824         {
4825           make_unknown_size = FALSE;
4826         }
4827         else if (gap_len > unknown_gap_size && unknown_greater_than_or_equal)
4828         {
4829           if (!known_greater_than_or_equal)
4830           {
4831           	make_unknown_size = TRUE;
4832           }
4833           else if (unknown_gap_size > known_gap_size)
4834           {
4835           	make_unknown_size = TRUE;
4836           }
4837           else if (gap_len < known_gap_size)
4838           {
4839           	make_unknown_size = TRUE;
4840           }
4841         }
4842 
4843         /* Add Location to List */
4844         glip = (GapLocInfoPtr) MemNew (sizeof (GapLocInfoData));
4845         if (glip != NULL)
4846         {
4847           glip->start_pos = start_pos;
4848           glip->is_known = ! make_unknown_size;
4849           glip->length = gap_len;
4850           glip->replace = TRUE;
4851           ValNodeAddPointer (&result_list, 0, glip);
4852         }
4853       }
4854       txt += gap_len;
4855       start_pos += gap_len;
4856       ch = *txt;
4857       gap_len = 0;
4858     } else {
4859       gap_len = StringCSpn (txt, "N");
4860       txt+=gap_len;
4861       start_pos += gap_len;
4862       ch = *txt;
4863       gap_len = 0;
4864     }
4865   }
4866 
4867   MemFree (bases);
4868   return result_list;
4869 }
4870 
4871 static SeqLocPtr
RemoveGapLocationsFromSeqLoc(SeqLocPtr slp,ValNodePtr gap_locs,BioseqPtr bsp,BoolPtr loc_changed,Boolean set_partial_ends,Boolean reverse_list)4872 RemoveGapLocationsFromSeqLoc
4873 (SeqLocPtr  slp,
4874  ValNodePtr gap_locs,
4875  BioseqPtr  bsp,
4876  BoolPtr    loc_changed,
4877  Boolean    set_partial_ends,
4878  Boolean    reverse_list)
4879 {
4880   ValNodePtr    gap_vnp;
4881   GapLocInfoPtr glip;
4882   SeqLocPtr   loc_list = NULL, prev_loc = NULL;
4883   SeqIdPtr    sip, before_sip, after_sip;
4884   Boolean     changed, partial5, partial3;
4885   SeqLocPtr   before = NULL, after = NULL;
4886 
4887   if (loc_changed != NULL)
4888   {
4889     *loc_changed = FALSE;
4890   }
4891 
4892   if (slp == NULL || gap_locs == NULL || bsp == NULL)
4893   {
4894     return slp;
4895   }
4896 
4897   sip = SeqLocId (slp);
4898   if (sip == NULL)
4899   {
4900     return slp;
4901   }
4902 
4903   CheckSeqLocForPartial (slp, &partial5, &partial3);
4904 
4905   before = SeqLocCopy (slp);
4906   loc_list = before;
4907 
4908   for (gap_vnp = gap_locs;
4909        gap_vnp != NULL;
4910        gap_vnp = gap_vnp->next)
4911   {
4912     glip = (GapLocInfoPtr) gap_vnp->data.ptrvalue;
4913     if (glip == NULL || glip->is_known)
4914     {
4915       continue;
4916     }
4917     if (GapInLocation (glip->start_pos, glip->length, before))
4918     {
4919       if (loc_changed != NULL)
4920       {
4921         *loc_changed = TRUE;
4922       }
4923       /* we make a copy of the original location */
4924       after = SeqLocCopy (before);
4925 
4926       /* note - we need to use duplicates of the SeqID returned by
4927        * SeqLocId, just in case the first location in a mixed location
4928        * is deleted, which would free the result from SeqLocId
4929        */
4930       after_sip = SeqIdDup (SeqLocId (after));
4931       before_sip = SeqIdDup (SeqLocId (before));
4932       /* in the "after" location, we free everything before the
4933        * end of the gap.
4934        */
4935       after = SeqLocDeleteEx (after, after_sip,
4936                               0, glip->start_pos + glip->length - 1,
4937                               FALSE, &changed, &partial5, &partial3);
4938 
4939       /* in the "before" location, we free everything after the
4940        * beginning of the gap.
4941        */
4942       before = SeqLocDeleteEx (before, before_sip,
4943                                glip->start_pos, bsp->length,
4944                                FALSE, &changed, &partial5, &partial3);
4945 
4946       SetPartialsAfterSplittingAtGap(before, after, set_partial_ends, partial5, partial3);
4947 
4948       /* we're done with these IDs now */
4949       after_sip = SeqIdFree (after_sip);
4950       before_sip = SeqIdFree (before_sip);
4951 
4952       if (before == NULL)
4953       {
4954         if (prev_loc == NULL)
4955         {
4956           loc_list = after;
4957         }
4958         else
4959         {
4960           prev_loc->next = after;
4961         }
4962       }
4963       else
4964       {
4965         before->next = after;
4966         prev_loc = before;
4967       }
4968       before = after;
4969     }
4970   }
4971 
4972   slp = SeqLocFree (slp);
4973 
4974   if (reverse_list) {
4975     ValNodeReverse (&loc_list);
4976   }
4977 
4978   return loc_list;
4979 }
4980 
4981 
ClearGeneXrefsAndFeatIDs(SeqFeatPtr sfp)4982 static void ClearGeneXrefsAndFeatIDs (SeqFeatPtr sfp)
4983 
4984 {
4985   SeqFeatXrefPtr       curr, next;
4986   SeqFeatXrefPtr PNTR  last;
4987 
4988   if (sfp == NULL) return;
4989 
4990   ClearFeatIDs (sfp);
4991   ClearFeatIDXrefs (sfp);
4992 
4993   last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
4994   curr = sfp->xref;
4995   while (curr != NULL) {
4996     next = curr->next;
4997     if (curr->data.choice == SEQFEAT_GENE) {
4998       *last = next;
4999       curr->next = NULL;
5000       SeqFeatXrefFree (curr);
5001     } else {
5002       last = &(curr->next);
5003     }
5004     curr = next;
5005   }
5006 }
5007 
ClearIDsOnNewProtFeats(SeqFeatPtr sfp,Pointer userdata)5008 static void ClearIDsOnNewProtFeats (SeqFeatPtr sfp, Pointer userdata)
5009 
5010 {
5011   ClearGeneXrefsAndFeatIDs (sfp);
5012 }
5013 
AppendFirstToGeneralID(SeqIdPtr sip,Pointer userdata)5014 static void AppendFirstToGeneralID (SeqIdPtr sip, Pointer userdata)
5015 
5016 {
5017   DbtagPtr     dbt, gnl;
5018   ObjectIdPtr  oipd, oipg;
5019   size_t       len;
5020   CharPtr      str;
5021 
5022   if (sip == NULL || sip->choice != SEQID_GENERAL) return;
5023 
5024   dbt = (DbtagPtr) userdata;
5025   gnl = (DbtagPtr) sip->data.ptrvalue;
5026   if (dbt == NULL || gnl == NULL) return;
5027   if (StringCmp (gnl->db, dbt->db) != 0) return;
5028 
5029   oipd = dbt->tag;
5030   oipg = gnl->tag;
5031   if (oipd == NULL || oipg == NULL) return;
5032 
5033   if (oipd->str != NULL && oipg->str != NULL) {
5034     if (StringCmp (oipd->str, oipg->str) != 0) return;
5035     len = StringLen (oipd->str) + 5;
5036     str = (CharPtr) MemNew (sizeof (Char) * len);
5037     if (str != NULL) {
5038       StringCpy (str, oipd->str);
5039       StringCat (str, "_1");
5040       oipg->str = MemFree (oipg->str);
5041       oipg->str = str;
5042     }
5043   }
5044 }
5045 
AppendFirstToFeat(SeqFeatPtr sfp,Pointer userdata)5046 static void AppendFirstToFeat (SeqFeatPtr sfp, Pointer userdata)
5047 
5048 {
5049   if (sfp == NULL || userdata == NULL) return;
5050   VisitSeqIdsInSeqFeat (sfp, userdata, AppendFirstToGeneralID);
5051 }
5052 
5053 static BioseqPtr
SqnAddProteinSequenceCopy(BioseqPtr protbsp,BioseqPtr featbsp,SeqFeatPtr new_sfp,Int4 count,Uint2 entityID)5054 SqnAddProteinSequenceCopy
5055 (BioseqPtr  protbsp,
5056  BioseqPtr  featbsp,
5057  SeqFeatPtr new_sfp,
5058  Int4       count,
5059  Uint2      entityID)
5060 {
5061   Char        str [128], sfx [16];
5062   SeqIdPtr    new_id = NULL;
5063   BioseqPtr   new_protbsp;
5064   SeqEntryPtr prot_sep, parent_sep;
5065   SeqFeatPtr  prot_sfp, prot_cpy;
5066   SeqAnnotPtr sap;
5067   SeqIdPtr    sip;
5068   SeqLocPtr   slp;
5069   DbtagPtr    dbt;
5070 
5071   if (protbsp == NULL || featbsp == NULL || new_sfp == NULL)
5072   {
5073     return NULL;
5074   }
5075 
5076   parent_sep = GetBestTopParentForData (entityID, featbsp);
5077   if (parent_sep == NULL
5078       || !IS_Bioseq_set (parent_sep)
5079       || parent_sep->data.ptrvalue == NULL)
5080   {
5081     return NULL;
5082   }
5083 
5084   str [0] = '\0';
5085   for (sip = protbsp->id; sip != NULL; sip = sip->next) {
5086     if (sip->choice != SEQID_GENERAL) continue;
5087     dbt = (DbtagPtr) sip->data.ptrvalue;
5088     if (dbt == NULL) continue;
5089     if (IsSkippableDbtag (dbt)) continue;
5090     SeqIdWrite (sip, str, PRINTID_FASTA_GENERAL, sizeof (str) - 1);
5091     if (count > 0) {
5092       sprintf (sfx, "_%ld", (long) count);
5093       StringCat (str, sfx);
5094       new_id = MakeSeqID (str);
5095     }
5096   }
5097 
5098   if (StringHasNoText (str)) {
5099     SeqIdWrite (protbsp->id, str, PRINTID_REPORT, sizeof (str) - 1);
5100     if (count > 0) {
5101       sprintf (sfx, "_%ld", (long) count);
5102       StringCat (str, sfx);
5103       new_id = MakeSeqID (str);
5104     }
5105   }
5106 
5107   if (new_id == NULL) {
5108     new_id = MakeUniqueSeqID (str);
5109   }
5110   new_protbsp = BioseqCopyEx (new_id, protbsp, 0, protbsp->length - 1,
5111                                       Seq_strand_plus, TRUE);
5112   ValNodeLink (&(new_protbsp->descr),
5113                AsnIoMemCopy ((Pointer) protbsp->descr,
5114                              (AsnReadFunc) SeqDescrAsnRead,
5115                              (AsnWriteFunc) SeqDescrAsnWrite));
5116 
5117   prot_sep = SeqEntryNew ();
5118   if (prot_sep != NULL)
5119   {
5120     prot_sep->choice = 1;
5121     prot_sep->data.ptrvalue = new_protbsp;
5122     SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) new_protbsp, prot_sep);
5123     AddSeqEntryToSeqEntry (parent_sep, prot_sep, TRUE);
5124   }
5125 
5126   SeqMgrAddToBioseqIndex (new_protbsp);
5127   new_sfp->product = SeqLocWholeNew (new_protbsp);
5128 
5129   if (new_protbsp->annot == NULL) {
5130     for (sap = protbsp->annot; sap != NULL; sap = sap->next) {
5131       if (sap->type == 1) {
5132         for (prot_sfp = sap->data; prot_sfp != NULL; prot_sfp = prot_sfp->next) {
5133           slp = SeqLocCopy (prot_sfp->location);
5134           slp = SeqLocReplaceID (slp, new_protbsp->id);
5135           prot_cpy = CreateNewFeatureOnBioseq (new_protbsp, SEQFEAT_PROT, slp);
5136           prot_cpy->data.value.ptrvalue = AsnIoMemCopy (prot_sfp->data.value.ptrvalue, (AsnReadFunc) ProtRefAsnRead, (AsnWriteFunc) ProtRefAsnWrite);
5137         }
5138       }
5139     }
5140   }
5141   SeqMgrIndexFeatures (entityID, NULL);
5142   return new_protbsp;
5143 }
5144 
CreateMultipleFeaturesFromGappedLocs(SeqFeatPtr sfp,BioseqPtr bsp,BioseqPtr protbsp,Boolean partial5,Boolean partial3)5145 static void CreateMultipleFeaturesFromGappedLocs (SeqFeatPtr sfp, BioseqPtr bsp, BioseqPtr protbsp, Boolean partial5, Boolean partial3)
5146 {
5147   SeqFeatPtr  new_sfp;
5148   Uint1       choice;
5149   Int4        count = 0;
5150   CdRegionPtr crp;
5151   GBQualPtr   gbq;
5152   GeneRefPtr  grp;
5153   size_t      len;
5154   RnaRefPtr   rrp;
5155   SeqLocPtr   slp, nxt;
5156   CharPtr     str;
5157   Char        tmp [16];
5158   BioseqPtr   new_protbsp = NULL;
5159   Uint2       entityID;
5160   Boolean     isFirst, isLast;
5161 
5162   if (sfp == NULL || sfp->location == NULL || sfp->location->next == NULL || bsp == NULL) {
5163     return;
5164   }
5165   entityID = bsp->idx.entityID;
5166   choice = sfp->data.choice;
5167 
5168   if (choice == SEQFEAT_CDREGION) {
5169     if (protbsp == NULL) return;
5170   }
5171 
5172   /* make new feature from each interval */
5173   isFirst = TRUE;
5174   isLast = FALSE;
5175   for (slp = sfp->location; slp != NULL; slp = slp->next) {
5176     count++;
5177 
5178     if (slp->next == NULL) {
5179       isLast = TRUE;
5180     }
5181 
5182     nxt = slp->next;
5183     slp->next = NULL;
5184     new_sfp = CreateNewFeatureOnBioseq (bsp, choice, slp);
5185     slp->next = nxt;
5186     if (new_sfp == NULL) return;
5187 
5188     if (choice == SEQFEAT_CDREGION) {
5189 	    /* create copy of coding region data */
5190 	    crp = (CdRegionPtr) AsnIoMemCopy ((CdRegionPtr) sfp->data.value.ptrvalue,
5191 	                                       (AsnReadFunc) CdRegionAsnRead,
5192 	                                       (AsnWriteFunc) CdRegionAsnWrite);
5193       new_sfp->data.value.ptrvalue = crp;
5194     } else if (choice == SEQFEAT_GENE) {
5195       /* create copy of gene data */
5196       grp = (GeneRefPtr) AsnIoMemCopy ((GeneRefPtr) sfp->data.value.ptrvalue,
5197                                        (AsnReadFunc) GeneRefAsnRead,
5198                                        (AsnWriteFunc) GeneRefAsnWrite);
5199       new_sfp->data.value.ptrvalue = grp;
5200     } else if (choice == SEQFEAT_RNA) {
5201       /* create copy of RNA data */
5202       rrp = (RnaRefPtr) AsnIoMemCopy ((RnaRefPtr) sfp->data.value.ptrvalue,
5203                                       (AsnReadFunc) RnaRefAsnRead,
5204                                       (AsnWriteFunc) RnaRefAsnWrite);
5205       new_sfp->data.value.ptrvalue = rrp;
5206     }
5207 
5208     new_sfp->comment = StringSave (sfp->comment);
5209     new_sfp->qual = (GBQualPtr) AsnIoMemCopy ((GBQualPtr) sfp->qual,
5210                                               (AsnReadFunc) GBQualAsnRead,
5211                                               (AsnWriteFunc) GBQualAsnWrite);
5212 
5213     for (gbq = new_sfp->qual; gbq != NULL; gbq = gbq->next) {
5214       if (StringICmp (gbq->qual, "protein_id") != 0 &&
5215           StringICmp (gbq->qual, "orig_protein_id") != 0 &&
5216           StringICmp (gbq->qual, "transcript_id") != 0 &&
5217           StringICmp (gbq->qual, "orig_transcript_id") != 0) {
5218         continue;
5219       }
5220       if (StringNICmp (gbq->val, "gnl|", 4) != 0) continue;
5221       len = StringLen (gbq->val) + 16;
5222       str = (CharPtr) MemNew (sizeof (Char) * len);
5223       if (str != NULL) {
5224         sprintf (tmp, "_%ld", (long) count);
5225         StringCpy (str, gbq->val);
5226         StringCat (str, tmp);
5227         gbq->val = MemFree (gbq->val);
5228         gbq->val = str;
5229       }
5230     }
5231 
5232     /* set partials on new feature */
5233     if (isFirst) {
5234       SetSeqLocPartial (new_sfp->location, partial5, TRUE);
5235     } else if (isLast) {
5236       SetSeqLocPartial (new_sfp->location, TRUE, partial3);
5237     } else {
5238       SetSeqLocPartial (new_sfp->location, TRUE, TRUE);
5239     }
5240 
5241     if (choice == SEQFEAT_CDREGION) {
5242       new_protbsp = SqnAddProteinSequenceCopy (protbsp, bsp, new_sfp, count, entityID);
5243       if (new_protbsp == NULL) return;
5244 
5245       VisitFeaturesOnBsp (new_protbsp, NULL, ClearIDsOnNewProtFeats);
5246 
5247       /* adjust frame */
5248       AdjustFrame (sfp, new_protbsp);
5249 
5250       /* retranslate coding region */
5251       SeqEdTranslateOneCDS (new_sfp, bsp, entityID, Sequin_GlobalAlign2Seq);
5252 
5253       /* set partials on product */
5254       if (isFirst) {
5255         SetProductSequencePartials (new_protbsp, partial5, TRUE);
5256       } else if (isLast) {
5257         SetProductSequencePartials (new_protbsp, TRUE, partial3);
5258       } else {
5259         SetProductSequencePartials (new_protbsp, TRUE, TRUE);
5260       }
5261     }
5262 
5263     isFirst = FALSE;
5264   }
5265 
5266   /* delete originals */
5267   sfp->idx.deleteme = TRUE;
5268   if (protbsp != NULL) {
5269     protbsp->idx.deleteme = TRUE;
5270   }
5271 }
5272 
AdjustCodingRegionLocationsForGapLocations(BioseqPtr bsp,ValNodePtr gap_list)5273 static void AdjustCodingRegionLocationsForGapLocations (BioseqPtr bsp, ValNodePtr gap_list)
5274 
5275 {
5276   SeqFeatPtr         cds, gene, mrna;
5277   Uint2              entityID;
5278   SeqMgrFeatContext  fcontext, mcontext;
5279   Boolean            loc_changed, partial5, partial3, reverse_list;
5280   BioseqPtr          protbsp;
5281 
5282   if (bsp == NULL || gap_list == NULL) return;
5283 
5284   entityID = bsp->idx.entityID;
5285 
5286   for (cds = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &fcontext);
5287        cds != NULL;
5288        cds = SeqMgrGetNextFeature (bsp, cds, SEQFEAT_CDREGION, 0, &fcontext))
5289   {
5290     loc_changed = FALSE;
5291     gene = GetGeneForFeature (cds);
5292     mrna = SeqMgrGetOverlappingmRNA (cds->location, &mcontext);
5293 
5294     CheckSeqLocForPartial (cds->location, &partial5, &partial3);
5295     reverse_list = (Boolean) (SeqLocStrand (cds->location) == Seq_strand_minus);
5296     cds->location = RemoveGapLocationsFromSeqLoc (cds->location, gap_list, bsp, &loc_changed, TRUE, reverse_list);
5297     if (!loc_changed) {
5298         continue;
5299     }
5300 
5301     ClearGeneXrefsAndFeatIDs (cds);
5302     AddCDSGapComment (cds);
5303     protbsp = BioseqFindFromSeqLoc (cds->product);
5304     CreateMultipleFeaturesFromGappedLocs(cds, bsp, protbsp, partial5, partial3);
5305 
5306     if (gene != NULL) {
5307       ClearGeneXrefsAndFeatIDs (gene);
5308       /*
5309       CheckSeqLocForPartial (gene->location, &partial5, &partial3);
5310       reverse_list = (Boolean) (SeqLocStrand (gene->location) == Seq_strand_minus);
5311       gene->location = RemoveGapLocationsFromSeqLoc (gene->location, gap_list, bsp, &loc_changed, FALSE, reverse_list);
5312       CreateMultipleFeaturesFromGappedLocs(gene, bsp, NULL, partial5, partial3);
5313       */
5314     }
5315     if (mrna != NULL) {
5316       ClearGeneXrefsAndFeatIDs (mrna);
5317       CheckSeqLocForPartial (mrna->location, &partial5, &partial3);
5318       reverse_list = (Boolean) (SeqLocStrand (mrna->location) == Seq_strand_minus);
5319       mrna->location = RemoveGapLocationsFromSeqLoc (mrna->location, gap_list, bsp, &loc_changed, FALSE, reverse_list);
5320       CreateMultipleFeaturesFromGappedLocs(mrna, bsp, NULL, partial5, partial3);
5321     }
5322   }
5323 
5324   DeleteMarkedObjects (entityID, 0, NULL);
5325   SeqMgrClearFeatureIndexes (entityID, NULL);
5326   SeqMgrIndexFeatures (entityID, NULL);
5327 }
5328 
5329 extern void
PrepareCodingRegionLocationsForDeltaConversionCallback(BioseqPtr bsp,Pointer userdata)5330 PrepareCodingRegionLocationsForDeltaConversionCallback
5331 (BioseqPtr bsp, Pointer userdata)
5332 {
5333   Int4Ptr gap_sizes;
5334   ValNodePtr gap_locations;
5335 
5336   if (bsp == NULL)
5337   {
5338     return;
5339   }
5340 
5341   gap_sizes = (Int4Ptr) userdata;
5342 
5343   gap_locations = GapLocationsFromNs (bsp, gap_sizes);
5344 
5345   AdjustCodingRegionLocationsForGapLocations (bsp, gap_locations);
5346 
5347   gap_locations = ValNodeFreeData (gap_locations);
5348 }
5349 
5350 static Int4
CalculateGapCoverage(BioseqPtr bsp,SeqLocPtr slp,SeqMgrFeatContext context,Boolean include_terminal_gaps)5351 CalculateGapCoverage
5352 (BioseqPtr         bsp,
5353  SeqLocPtr         slp,
5354  SeqMgrFeatContext context,
5355  Boolean           include_terminal_gaps)
5356 {
5357   DeltaSeqPtr       dsp;
5358   SeqLocPtr         loc;
5359   SeqLitPtr         slip;
5360   Int4              seq_offset = 0;
5361   Int4              covered = 0;
5362   Int4              k, start, stop;
5363 
5364   if (slp == NULL
5365       || bsp == NULL || !ISA_na (bsp->mol)
5366       || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4)
5367   {
5368     return 0;
5369   }
5370 
5371   dsp = (DeltaSeqPtr) bsp->seq_ext;
5372   while (dsp != NULL && seq_offset < context.right)
5373   {
5374     if (dsp->choice == 1)
5375     {
5376       loc = (SeqLocPtr) dsp->data.ptrvalue;
5377       if (loc != NULL)
5378       {
5379         seq_offset += SeqLocLen (loc);
5380       }
5381     }
5382     else if (dsp->choice == 2)
5383     {
5384       slip = (SeqLitPtr) dsp->data.ptrvalue;
5385       if (slip != NULL)
5386       {
5387         if (IsDeltaSeqKnownGap (dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp))
5388         {
5389           if (seq_offset <= context.left && seq_offset + slip->length >= context.right)
5390           {
5391             /* gap covers entire location */
5392             return SeqLocLen (slp);
5393           }
5394           else if (include_terminal_gaps ||
5395                    (seq_offset > context.left
5396                     && seq_offset + slip->length < context.right))
5397           {
5398             /* we only count internal gaps */
5399             for (k = 0; k < 2 * context.numivals; k += 2)
5400             {
5401               start = context.ivals [k];
5402               stop = context.ivals [k + 1];
5403               if (seq_offset <= start && seq_offset + slip->length > stop)
5404               {
5405                 /* gap covers entire interval */
5406                 covered += stop - start;
5407               }
5408               else if (seq_offset > start && seq_offset + slip->length < stop)
5409               {
5410                 /* interval covers entire gap */
5411                 covered += slip->length;
5412               }
5413               else if (seq_offset < start && seq_offset + slip->length > start)
5414               {
5415                 /* gap covers left end of interval */
5416                 covered += seq_offset + slip->length - start;
5417               }
5418               else if (seq_offset < stop && seq_offset + slip->length > stop)
5419               {
5420                 /* gap covers right end of interval */
5421                 covered += stop - seq_offset;
5422               }
5423             }
5424           }
5425         }
5426         seq_offset += slip->length;
5427       }
5428     }
5429     dsp = dsp->next;
5430   }
5431 
5432   return covered;
5433 
5434 }
5435 
5436 
TrailingNLength(CharPtr seq)5437 static Int4 TrailingNLength (CharPtr seq)
5438 {
5439   Int4 seq_len = StringLen (seq);
5440   Int4 trailing_ns = 0;
5441   CharPtr cp;
5442 
5443   if (seq == NULL) {
5444     return 0;
5445   }
5446   cp = seq + seq_len - 1;
5447   while (cp > seq && *cp == 'N') {
5448     cp--;
5449     trailing_ns++;
5450   }
5451   if (*cp == 'N') {
5452     trailing_ns++;
5453   }
5454   return trailing_ns;
5455 }
5456 
5457 
5458 static SeqLocPtr
RemoveTerminalNsFromLocation(SeqLocPtr slp)5459 RemoveTerminalNsFromLocation
5460 (SeqLocPtr slp)
5461 {
5462   SeqLocPtr         loc = NULL, slp_copy;
5463   Int4              start, stop;
5464   Boolean           first = TRUE;
5465   BioseqPtr         bsp;
5466   SeqIdPtr          sip;
5467   Boolean           changed = FALSE, partial5, partial3, tmp5, tmp3;
5468   CharPtr           buffer = NULL;
5469   Int4              buflen = 0;
5470   Int4              leading_ns;
5471   Int4              trailing_n_start = -1, this_ns;
5472   Int4              loc_len;
5473   Uint1             strand;
5474 
5475   if (slp == NULL)
5476   {
5477     return NULL;
5478   }
5479 
5480   bsp = BioseqFindFromSeqLoc (slp);
5481   if (bsp == NULL) {
5482     return NULL;
5483   }
5484   CheckSeqLocForPartial (slp, &partial5, &partial3);
5485 
5486   slp_copy = (SeqLocPtr) AsnIoMemCopy (slp,
5487                                        (AsnReadFunc) SeqLocAsnRead,
5488                                        (AsnWriteFunc) SeqLocAsnWrite);
5489   if (!ISA_na (bsp->mol))
5490   {
5491     return slp_copy;
5492   }
5493 
5494   while ((loc = SeqLocFindNext (slp, loc)) != NULL) {
5495     start = SeqLocStart (loc);
5496     stop = SeqLocStop (loc);
5497     strand = SeqLocStrand (loc);
5498     loc_len = stop - start + 1;
5499     if (buflen < loc_len + 1) {
5500       buffer = MemFree (buffer);
5501       buflen = loc_len + 1;
5502       buffer = (CharPtr) MemNew (sizeof (Char) * buflen);
5503     }
5504     SeqPortStreamInt (bsp, start, stop, strand, EXPAND_GAPS_TO_DASHES, (Pointer) (buffer), NULL);
5505     leading_ns = 0;
5506     if (first) {
5507       leading_ns = StringSpn (buffer, "N");
5508       if (leading_ns > 0) {
5509         sip = SeqIdDup (SeqLocId (slp_copy));
5510         tmp5 = FALSE;
5511         tmp3 = FALSE;
5512         if (strand == Seq_strand_minus) {
5513           slp_copy = SeqLocDeleteEx (slp_copy, sip,
5514                                      stop - leading_ns + 1, stop,
5515                                      FALSE, &changed, &tmp5, &tmp3);
5516         } else {
5517           slp_copy = SeqLocDeleteEx (slp_copy, sip,
5518                             start, start + leading_ns - 1,
5519                             FALSE, &changed, &tmp5, &tmp3);
5520         }
5521         partial5 |= tmp5;
5522         partial3 |= tmp3;
5523         sip = SeqIdFree (sip);
5524       }
5525     }
5526 
5527     if (!first || leading_ns != loc_len) {
5528       this_ns = TrailingNLength (buffer);
5529       if (this_ns > 0) {
5530         if (this_ns == loc_len && trailing_n_start > -1) {
5531           /* add to existing trailing Ns */
5532         } else {
5533           if (strand == Seq_strand_minus) {
5534             trailing_n_start = start + this_ns - 1;
5535           } else {
5536             trailing_n_start = stop - this_ns + 1;
5537           }
5538         }
5539       }
5540     } else {
5541       trailing_n_start = -1;
5542     }
5543 
5544     if (first && leading_ns != loc_len) {
5545       first = FALSE;
5546     }
5547   }
5548 
5549   if (trailing_n_start > -1) {
5550     sip = SeqIdDup (SeqLocId (slp_copy));
5551     tmp5 = FALSE;
5552     tmp3 = FALSE;
5553     if (strand == Seq_strand_minus) {
5554       slp_copy = SeqLocDeleteEx (slp_copy, sip,
5555                               start, trailing_n_start,
5556                               FALSE, &changed, &tmp5, &tmp3);
5557     } else {
5558       slp_copy = SeqLocDeleteEx (slp_copy, sip,
5559                               trailing_n_start, stop,
5560                               FALSE, &changed, &tmp5, &tmp3);
5561     }
5562     partial5 |= tmp5;
5563     partial3 |= tmp3;
5564     sip = SeqIdFree (sip);
5565   }
5566 
5567   if (slp_copy != NULL)
5568   {
5569     SetSeqLocPartial (slp_copy, partial5, partial3);
5570   }
5571 
5572   buffer = MemFree (buffer);
5573 
5574   return slp_copy;
5575 }
5576 
5577 
5578 typedef struct cdstomiscfeatform
5579 {
5580   FEATURE_FORM_BLOCK
5581 
5582   GrouP  all_or_percent_grp;
5583   DialoG string_constraint_dlg;
5584 
5585   Boolean             convert_all;
5586   FilterSetPtr        fsp;
5587   StringConstraintXPtr scp;
5588   BioseqPtr           bsp;
5589 } CDSToMiscFeatFormData, PNTR CDSToMiscFeatFormPtr;
5590 
ConvertCDSToMiscFeatFeatureCallback(SeqFeatPtr sfp,Pointer userdata,FilterSetPtr fsp)5591 static void ConvertCDSToMiscFeatFeatureCallback (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr fsp)
5592 {
5593   CDSToMiscFeatFormPtr cmffp;
5594   Int4                 orig_len, covered_len;
5595   SeqMgrFeatContext    context;
5596   SeqEntryPtr          oldscope;
5597   CDStoMiscFeatData    cmfd;
5598 
5599   cmffp = (CDSToMiscFeatFormPtr) userdata;
5600 
5601   if (sfp == NULL || cmffp == NULL || cmffp->bsp == NULL)
5602   {
5603     return;
5604   }
5605 
5606   sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, cmffp->bsp, sfp->idx.itemID, 0, sfp, &context);
5607   if (sfp == NULL)
5608   {
5609     return;
5610   }
5611 
5612   oldscope = SeqEntrySetScope (NULL);
5613 
5614   orig_len = SeqLocLen (sfp->location);
5615   covered_len = CalculateGapCoverage (cmffp->bsp, sfp->location, context, cmffp->convert_all);
5616   if (covered_len >= orig_len / 2 || (cmffp->convert_all && covered_len > 0))
5617   {
5618     cmfd.must_have_stops = FALSE;
5619     cmfd.viral = FALSE;
5620     cmfd.opts = NULL;
5621     ConvertCDSToMiscFeat (sfp, &cmfd);
5622   }
5623 
5624   SeqEntrySetScope (oldscope);
5625 }
5626 
ConvertGappedCodingRegionsToMiscFeatBioseqCallback(BioseqPtr bsp,Pointer userdata)5627 static void ConvertGappedCodingRegionsToMiscFeatBioseqCallback (BioseqPtr bsp, Pointer userdata)
5628 {
5629   CDSToMiscFeatFormPtr cmffp;
5630   SeqEntryPtr          sep;
5631 
5632   if (bsp == NULL || !ISA_na (bsp->mol)
5633       || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4
5634       || userdata == NULL)
5635   {
5636     return;
5637   }
5638 
5639   sep = SeqMgrGetSeqEntryForData (bsp);
5640 
5641   cmffp = (CDSToMiscFeatFormPtr) userdata;
5642   cmffp->bsp = bsp;
5643 
5644   OperateOnSeqEntryConstrainedObjects (sep, cmffp->fsp,
5645                                        ConvertCDSToMiscFeatFeatureCallback,
5646                                        NULL, SEQFEAT_CDREGION, FEATDEF_CDS, 0, cmffp);
5647 
5648 }
5649 
AcceptCDSToMiscFeat(ButtoN b)5650 static void AcceptCDSToMiscFeat (ButtoN b)
5651 {
5652   CDSToMiscFeatFormPtr cmffp;
5653   SeqEntryPtr          sep;
5654 
5655   cmffp = (CDSToMiscFeatFormPtr) GetObjectExtra (b);
5656   if (cmffp == NULL)
5657   {
5658     return;
5659   }
5660 
5661   if (GetValue (cmffp->all_or_percent_grp) == 2)
5662   {
5663     cmffp->convert_all = TRUE;
5664   }
5665   else
5666   {
5667     cmffp->convert_all = FALSE;
5668   }
5669 
5670   cmffp->fsp = FilterSetNew();
5671   cmffp->fsp->scp = DialogToPointer (cmffp->string_constraint_dlg);
5672 
5673   sep = GetTopSeqEntryForEntityID (cmffp->input_entityID);
5674   if (sep == NULL) return;
5675 
5676   VisitBioseqsInSep (sep, cmffp, ConvertGappedCodingRegionsToMiscFeatBioseqCallback);
5677   DeleteMarkedObjects (cmffp->input_entityID, 0, NULL);
5678   RenormalizeNucProtSets (sep, TRUE);
5679   ObjMgrSetDirtyFlag (cmffp->input_entityID, TRUE);
5680   ObjMgrSendMsg (OM_MSG_UPDATE, cmffp->input_entityID, 0, 0);
5681   Remove (cmffp->form);
5682 }
5683 
ConvertCodingRegionsWithInternalKnownGapToMiscFeat(IteM i)5684 extern void ConvertCodingRegionsWithInternalKnownGapToMiscFeat (IteM i)
5685 {
5686   BaseFormPtr          bfp;
5687   CDSToMiscFeatFormPtr cmffp;
5688   WindoW               w;
5689   GrouP                h, c;
5690   ButtoN               b;
5691 
5692 #ifdef WIN_MAC
5693   bfp = currentFormDataPtr;
5694 #else
5695   bfp = GetObjectExtra (i);
5696 #endif
5697   if (bfp == NULL) return;
5698 
5699   cmffp = (CDSToMiscFeatFormPtr) MemNew (sizeof (CDSToMiscFeatFormData));
5700   if (cmffp == NULL) return;
5701 
5702   w = FixedWindow (-50, -33, -10, -10, "Convert Coding Regions With Gaps to Misc_Feat", StdCloseWindowProc);
5703   SetObjectExtra (w, cmffp, StdCleanupFormProc);
5704   cmffp->form = (ForM) w;
5705   cmffp->input_entityID = bfp->input_entityID;
5706   h = HiddenGroup (w, -1, 0, NULL);
5707   SetGroupSpacing (h, 10, 10);
5708 
5709   cmffp->all_or_percent_grp = HiddenGroup (h, 0, 2, NULL);
5710   SetGroupSpacing (cmffp->all_or_percent_grp, 10, 10);
5711   RadioButton (cmffp->all_or_percent_grp, "Convert only when internal gap covers 50% or more of the coding region");
5712   RadioButton (cmffp->all_or_percent_grp, "Convert all coding regions with gaps (both terminal and internal)");
5713   SetValue (cmffp->all_or_percent_grp, 1);
5714 
5715   cmffp->string_constraint_dlg = StringConstraintDialogX (h, "Where feature text", FALSE);
5716 
5717   c = HiddenGroup (h, 2, 0, NULL);
5718   SetGroupSpacing (c, 10, 10);
5719   b = PushButton (c, "Accept", AcceptCDSToMiscFeat);
5720   SetObjectExtra (b, cmffp, NULL);
5721   PushButton (c, "Cancel", StdCancelButtonProc);
5722   AlignObjects (ALIGN_CENTER, (HANDLE) cmffp->all_or_percent_grp,
5723                               (HANDLE) cmffp->string_constraint_dlg,
5724                               (HANDLE) c,
5725                               NULL);
5726   RealizeWindow (w);
5727   Show (w);
5728   Select (w);
5729 }
5730 
5731 
5732 /*---------------------------------------------------------------------*/
5733 /*                                                                     */
5734 /* Apply_AddCDS () --                                                  */
5735 /*                                                                     */
5736 /*---------------------------------------------------------------------*/
5737 
Apply_AddCDS(Uint2 entityID,SeqEntryPtr sep,SeqEntryPtr nsep,ApplyFormPtr afp,Boolean suppressDups)5738 static void Apply_AddCDS (Uint2        entityID,
5739 			  SeqEntryPtr  sep,
5740 			  SeqEntryPtr  nsep,
5741 			  ApplyFormPtr afp,
5742 			  Boolean      suppressDups)
5743 {
5744   ByteStorePtr       bs;
5745   BioseqPtr          bsp;
5746   Char               ch;
5747   CdRegionPtr        crp;
5748   RnaRefPtr          rrp;
5749   ValNodePtr         descr;
5750   Int2               genCode;
5751   Int2               i;
5752   MolInfoPtr         mip;
5753   SeqEntryPtr        old;
5754   CharPtr            prot;
5755   ProtRefPtr         prp;
5756   SeqEntryPtr        psep;
5757   CharPtr            ptr;
5758   SeqFeatPtr         sfp;
5759   SeqIdPtr           sip;
5760   Char               str [128];
5761   ValNodePtr         vnp;
5762   SeqEntryPtr        parent_sep;
5763   SeqEntryPtr        gene_sep;
5764   SeqFeatPtr         prot_sfp, mRNA_sfp;
5765 
5766   /* If necessary then check for duplication before adding */
5767 
5768   if (suppressDups &&
5769       entityID > 0 &&
5770       AlreadyHasFeatOrDesc (sep, SEQFEAT_CDREGION, 0, 0))
5771     return;
5772 
5773   /* determine the parent of this sequence (for use when segmented) */
5774   parent_sep = NULL;
5775   if (IS_Bioseq (sep))
5776   {
5777     parent_sep = GetBestTopParentForData (entityID, sep->data.ptrvalue);
5778   }
5779   if (parent_sep == NULL)
5780   {
5781     parent_sep = sep;
5782   }
5783 
5784   /*Create a new CDS feature */
5785 
5786   genCode = SeqEntryToGeneticCode (parent_sep, NULL, NULL, 0);
5787   crp = CreateNewCdRgn (1, FALSE, genCode);
5788   if (NULL == crp)
5789     return;
5790 
5791   sfp = CreateNewFeature (nsep, NULL, SEQFEAT_CDREGION, NULL);
5792 
5793   if (NULL == sfp)
5794     return;
5795 
5796   sfp->data.value.ptrvalue = (Pointer) crp;
5797 
5798   /* set the comment */
5799   if (afp->feature_details_data->featcomment != NULL) {
5800       sfp->comment = StringSave (afp->feature_details_data->featcomment);
5801   }
5802 
5803   /* adjust the location of the new feature */
5804   SetApplyFeatureLocation (sfp, afp);
5805 
5806   /* Fill in the fields of the new CDS feature */
5807   if (afp->feature_details_data->reading_frame < 1
5808       || afp->feature_details_data->reading_frame > 3)
5809   {
5810     if (!SetBestFrameByLocation (sfp)) {
5811       str [0] = '\0';
5812       if (IS_Bioseq (nsep)) {
5813         bsp = (BioseqPtr) nsep->data.ptrvalue;
5814         if (bsp != NULL) {
5815           sip = SeqIdFindBest (bsp->id, 0);
5816           SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str) - 1);
5817         }
5818       }
5819       (afp->errcount)++;
5820       ValNodeCopyStr (&(afp->ambigList), 0, str);
5821     }
5822   }
5823   else
5824   {
5825     crp->frame = afp->feature_details_data->reading_frame;
5826   }
5827 
5828   /* Create corresponding protein sequence data for the CDS */
5829 
5830   bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
5831   if (NULL == bs)
5832     return;
5833 
5834   prot = BSMerge (bs, NULL);
5835   bs = BSFree (bs);
5836   if (NULL == prot)
5837     return;
5838 
5839   ptr = prot;
5840   ch = *ptr;
5841   while (ch != '\0') {
5842     *ptr = TO_UPPER (ch);
5843     ptr++;
5844     ch = *ptr;
5845   }
5846   i = (Int2) StringLen (prot);
5847   if (i > 0 && prot [i - 1] == '*') {
5848     prot [i - 1] = '\0';
5849   }
5850   bs = BSNew (1000);
5851   if (bs != NULL) {
5852     ptr = prot;
5853     BSWrite (bs, (VoidPtr) ptr, (Int4) StringLen (ptr));
5854   }
5855 
5856   /* Create the product protein Bioseq */
5857 
5858   bsp = BioseqNew ();
5859   if (NULL == bsp)
5860     return;
5861 
5862   bsp->repr = Seq_repr_raw;
5863   bsp->mol = Seq_mol_aa;
5864   bsp->seq_data_type = Seq_code_ncbieaa;
5865   bsp->seq_data = (SeqDataPtr) bs;
5866   bsp->length = BSLen (bs);
5867   bs = NULL;
5868   old = SeqEntrySetScope (sep);
5869   bsp->id = MakeNewProteinSeqId (sfp->location, NULL);
5870   SeqMgrAddToBioseqIndex (bsp);
5871   SeqEntrySetScope (old);
5872 
5873   /* Create a new SeqEntry for the Prot Bioseq */
5874 
5875   psep = SeqEntryNew ();
5876   if (NULL == psep)
5877     return;
5878 
5879   psep->choice = 1;
5880   psep->data.ptrvalue = (Pointer) bsp;
5881   SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, psep);
5882 
5883   /* Add a descriptor to the protein Bioseq */
5884 
5885   mip = MolInfoNew ();
5886   if (NULL == mip)
5887     return;
5888 
5889   mip->biomol = 8;
5890   mip->tech = 8;
5891   if (afp->noLeft && afp->noRight) {
5892     mip->completeness = 5;
5893   } else if (afp->noLeft) {
5894     mip->completeness = 3;
5895   } else if (afp->noRight) {
5896     mip->completeness = 4;
5897   }
5898   vnp = CreateNewDescriptor (psep, Seq_descr_molinfo);
5899   if (NULL == vnp)
5900     return;
5901 
5902   vnp->data.ptrvalue = (Pointer) mip;
5903 
5904   /**/
5905 
5906   descr = ExtractBioSourceAndPubs (parent_sep);
5907 
5908   AddSeqEntryToSeqEntry (parent_sep, psep, TRUE);
5909   nsep = FindNucSeqEntry (parent_sep);
5910   ReplaceBioSourceAndPubs (parent_sep, descr);
5911   SetSeqFeatProduct (sfp, bsp);
5912 
5913   /* create a full-length protein feature for the new protein sequence */
5914   if (! StringHasNoText (afp->feature_details_data->protName)
5915       && ! StringHasNoText (afp->feature_details_data->protDesc))
5916   {
5917     prp = CreateNewProtRef (afp->feature_details_data->protName,
5918                             afp->feature_details_data->protDesc,
5919                             NULL, NULL);
5920   }
5921   else if (!StringHasNoText (afp->feature_details_data->protName))
5922   {
5923     prp = CreateNewProtRef (afp->feature_details_data->protName, NULL, NULL, NULL);
5924   }
5925   else if (!StringHasNoText (afp->feature_details_data->protDesc))
5926   {
5927     prp = CreateNewProtRef (NULL, afp->feature_details_data->protDesc, NULL, NULL);
5928   }
5929   else
5930   {
5931     prp = ProtRefNew ();
5932   }
5933 
5934   if (prp != NULL) {
5935     prot_sfp = CreateNewFeature (psep, NULL, SEQFEAT_PROT, NULL);
5936     if (prot_sfp != NULL) {
5937       prot_sfp->data.value.ptrvalue = (Pointer) prp;
5938       SetSeqLocPartial (prot_sfp->location, afp->noLeft, afp->noRight);
5939       prot_sfp->partial = (afp->noLeft || afp->noRight);
5940     }
5941   }
5942 
5943   /* after the feature has been created, then adjust it for gaps */
5944   /* Note - this step may result in multiple coding regions being created. */
5945   AdjustCDSLocationsForUnknownGapsCallback (sfp, NULL);
5946 
5947   /* if requested, also add mRNA feature */
5948   if (afp->also_add_mRNA_btn != NULL && GetStatus(afp->also_add_mRNA_btn)) {
5949     mRNA_sfp = CreateNewFeature (nsep, NULL, SEQFEAT_RNA, NULL);
5950     rrp = RnaRefNew ();
5951     if (rrp != NULL) {
5952       rrp->type = 2;
5953       if (!StringHasNoText(afp->feature_details_data->protName)) {
5954           rrp->ext.choice = 1;
5955           rrp->ext.value.ptrvalue = StringSave (afp->feature_details_data->protName);
5956       }
5957     }
5958 	mRNA_sfp->data.value.ptrvalue = rrp;
5959     SetApplyFeatureLocation (mRNA_sfp, afp);
5960     AdjustCDSLocationsForUnknownGapsCallback (mRNA_sfp, NULL);
5961   }
5962 
5963   /* Create a Gene ref feature on the nuc seq or segment */
5964   /* we can only create a feature where the sep->choice is 1 */
5965   if (sep->choice == 1)
5966   {
5967     gene_sep = sep;
5968   }
5969   else
5970   {
5971     gene_sep = nsep;
5972   }
5973 
5974   if (! StringHasNoText (afp->feature_details_data->geneName)) {
5975     if (entityID > 0
5976         && suppressDups
5977         && AlreadyHasFeatOrDesc (gene_sep, SEQFEAT_GENE, 0, 0))
5978     {
5979       return;
5980     }
5981 
5982     ApplyGene (afp->feature_details_data->geneName, afp, gene_sep, sfp);
5983   }
5984 }
5985 
CheckTitle(SeqEntryPtr sep,GetSamplePtr gsp)5986 static void CheckTitle (SeqEntryPtr sep, GetSamplePtr gsp)
5987 {
5988   BioseqPtr         bsp;
5989   BioseqSetPtr      bssp = NULL, part_set;
5990   SeqDescrPtr       sdp;
5991 
5992   if (sep == NULL || sep->data.ptrvalue == NULL
5993       || gsp == NULL)
5994   {
5995     return;
5996   }
5997 
5998   if (IS_Bioseq_set (sep)) {
5999     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6000     if (bssp != NULL
6001         && bssp->_class == BioseqseqSet_class_nuc_prot
6002         && bssp->seq_set != NULL)
6003     {
6004       sep = bssp->seq_set;
6005     }
6006   }
6007 
6008   if (IS_Bioseq_set (sep))
6009   {
6010     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6011     if (bssp != NULL
6012         && bssp->_class == BioseqseqSet_class_segset
6013         && bssp->seq_set != NULL)
6014     {
6015       /* first do parts */
6016       if (bssp->seq_set->next != NULL
6017           && IS_Bioseq_set (bssp->seq_set->next)
6018           && bssp->seq_set->next->data.ptrvalue != NULL)
6019       {
6020         part_set = (BioseqSetPtr) bssp->seq_set->next->data.ptrvalue;
6021         if (part_set->_class == BioseqseqSet_class_parts)
6022         {
6023           for (sep = part_set->seq_set; sep != NULL; sep = sep->next)
6024           {
6025             CheckTitle (sep, gsp);
6026           }
6027         }
6028       }
6029 
6030       /* now do master */
6031       sep = bssp->seq_set;
6032     }
6033   }
6034 
6035   if (!IS_Bioseq (sep))
6036   {
6037     return;
6038   }
6039 
6040   bsp = (BioseqPtr) sep->data.ptrvalue;
6041   sdp = bsp->descr;
6042   while (sdp != NULL && sdp->choice != Seq_descr_title)
6043   {
6044     sdp = sdp->next;
6045   }
6046   if (sdp != NULL)
6047   {
6048     gsp->num_found ++;
6049     if (gsp->sample_text == NULL)
6050     {
6051       gsp->sample_text = StringSave (sdp->data.ptrvalue);
6052     }
6053     else if (StringCmp (gsp->sample_text, sdp->data.ptrvalue) != 0)
6054     {
6055       gsp->all_same = FALSE;
6056     }
6057   }
6058 
6059 
6060 }
6061 
ApplyOneTitle(SeqEntryPtr sep,ExistingTextPtr etp,CharPtr defline)6062 static void ApplyOneTitle (SeqEntryPtr sep, ExistingTextPtr etp, CharPtr defline)
6063 {
6064   BioseqPtr         bsp;
6065   BioseqSetPtr      bssp, part_set;
6066   SeqDescrPtr       sdp;
6067 
6068   if (sep == NULL || sep->data.ptrvalue == NULL
6069       || StringHasNoText (defline))
6070   {
6071     return;
6072   }
6073 
6074   if (IS_Bioseq_set (sep)) {
6075     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6076     if (bssp != NULL
6077         && bssp->_class == BioseqseqSet_class_nuc_prot
6078         && bssp->seq_set != NULL)
6079     {
6080       sep = bssp->seq_set;
6081     }
6082   }
6083 
6084   if (IS_Bioseq_set (sep))
6085   {
6086     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6087     if (bssp != NULL
6088         && bssp->_class == BioseqseqSet_class_segset
6089         && bssp->seq_set != NULL)
6090     {
6091       /* first do parts */
6092       if (bssp->seq_set->next != NULL
6093           && IS_Bioseq_set (bssp->seq_set->next)
6094           && bssp->seq_set->next->data.ptrvalue != NULL)
6095       {
6096         part_set = (BioseqSetPtr) bssp->seq_set->next->data.ptrvalue;
6097         if (part_set->_class == BioseqseqSet_class_parts)
6098         {
6099           for (sep = part_set->seq_set; sep != NULL; sep = sep->next)
6100           {
6101             ApplyOneTitle (sep, etp, defline);
6102           }
6103         }
6104       }
6105 
6106       /* now do master */
6107       sep = bssp->seq_set;
6108     }
6109   }
6110 
6111   if (!IS_Bioseq (sep))
6112   {
6113     return;
6114   }
6115 
6116   bsp = (BioseqPtr) sep->data.ptrvalue;
6117   sdp = bsp->descr;
6118   while (sdp != NULL && sdp->choice != Seq_descr_title)
6119   {
6120     sdp = sdp->next;
6121   }
6122 
6123   if (sdp == NULL)
6124   {
6125     sdp = CreateNewDescriptor (sep, Seq_descr_title);
6126   }
6127 
6128   if (sdp != NULL) {
6129     sdp->data.ptrvalue = HandleExistingText (sdp->data.ptrvalue,
6130                                              StringSave (defline), etp);
6131   }
6132   RemoveAutodefObjects(sep);
6133 }
6134 
6135 
6136 /*---------------------------------------------------------------------*/
6137 /*                                                                     */
6138 /* RealApplyBioFeatToAll () --                                         */
6139 /*                                                                     */
6140 /*---------------------------------------------------------------------*/
6141 
RealApplyBioFeatToAll(Uint2 entityID,SeqEntryPtr sep,SeqEntryPtr nsep,ApplyFormPtr afp,Boolean suppressDups)6142 static void RealApplyBioFeatToAll (Uint2        entityID,
6143 				                           SeqEntryPtr  sep,
6144 				                           SeqEntryPtr  nsep,
6145                                    ApplyFormPtr afp,
6146 				                           Boolean      suppressDups)
6147 
6148 {
6149   ImpFeatPtr         ifp;
6150   SeqFeatPtr         sfp = NULL;
6151   SeqFeatPtr         gene_sfp;
6152   Boolean            put_comment_on_gene = FALSE;
6153 
6154   /* Check parameters */
6155 
6156   if (sep == NULL || nsep == NULL || afp == NULL)
6157     return;
6158 
6159   /* Add a title feature */
6160 
6161   if (afp->type == CHECK_TITLE)
6162   {
6163     CheckTitle (sep, afp->gsp);
6164     return;
6165   }
6166   else if (afp->type == ADD_TITLE)
6167   {
6168     if (entityID == 0 && SeqEntryGetTitle (sep) != NULL)
6169     {
6170       return;
6171     }
6172     ApplyOneTitle (sep, afp->etp, afp->feature_details_data->defline);
6173     return;
6174   }
6175 
6176   /* Add a CDS feature */
6177 
6178   else if (afp->type == ADD_CDS)
6179     Apply_AddCDS (entityID, sep, nsep, afp, suppressDups);
6180 
6181   /* Add an rRNA feature */
6182 
6183   else if (afp->type == ADD_RRNA) {
6184     if (suppressDups && entityID > 0
6185         && AlreadyHasRNA (sep, afp->feature_details_data->rnaType)) {
6186       return;
6187     }
6188 
6189     sfp = CreateNewFeature (nsep, NULL, SEQFEAT_RNA, NULL);
6190     ApplyRnaTypeToSeqFeat (sfp, afp->feature_details_data->rnaType);
6191     if (! StringHasNoText (afp->feature_details_data->rnaName)) {
6192       ApplyProductToRNA (sfp, afp->feature_details_data->rnaName);
6193     }
6194 
6195     SetApplyFeatureLocation (sfp, afp);
6196     AddToComment (sfp, afp->feature_details_data->featcomment);
6197 
6198     if (! StringHasNoText (afp->feature_details_data->geneName)) {
6199       if (entityID > 0
6200         && suppressDups
6201 	      && AlreadyHasFeatOrDesc (sep, SEQFEAT_GENE, 0, 0))
6202       {
6203 	       return;
6204       }
6205       ApplyGene (afp->feature_details_data->geneName, afp, nsep, sfp);
6206 
6207     }
6208   }
6209 
6210   /* Add an Import feature */
6211 
6212   else if (afp->type == ADD_IMP) {
6213     if (afp->feature_details_data->featdef_choice == FEATDEF_GENE)
6214     {
6215       put_comment_on_gene = TRUE;
6216     }
6217     else
6218     {
6219       if (AlreadyHasImpFeat (sep, afp->feature_details_data->featdef_name) && suppressDups)
6220       {
6221 	       return;
6222       }
6223 
6224       ifp = ImpFeatNew ();
6225       if (ifp != NULL) {
6226         ifp->key = StringSave (afp->feature_details_data->featdef_name);
6227         sfp = CreateNewFeature (nsep, NULL, SEQFEAT_IMP, NULL);
6228         if (sfp != NULL) {
6229           sfp->data.value.ptrvalue = (Pointer) ifp;
6230           SetApplyFeatureLocation (sfp, afp);
6231           if (! StringHasNoText (afp->feature_details_data->featcomment))
6232           {
6233             sfp->comment = StringSave (afp->feature_details_data->featcomment);
6234           }
6235           sfp->qual = DialogToPointer (afp->gbquals);
6236         }
6237       }
6238     }
6239     if (! StringHasNoText (afp->feature_details_data->geneName)
6240 		|| ! StringHasNoText (afp->feature_details_data->geneDesc))
6241     {
6242       if (entityID > 0
6243           && suppressDups
6244 	        && AlreadyHasFeatOrDesc (sep, SEQFEAT_GENE, 0, 0))
6245       {
6246 	      return;
6247       }
6248       gene_sfp = ApplyGene (afp->feature_details_data->geneName, afp, nsep, sfp);
6249 
6250       if (gene_sfp != NULL && ! StringHasNoText (afp->feature_details_data->featcomment) && put_comment_on_gene)
6251       {
6252         gene_sfp->comment = StringSave (afp->feature_details_data->featcomment);
6253       }
6254     }
6255   }
6256 }
6257 
6258 /*---------------------------------------------------------------------*/
6259 /*                                                                     */
6260 /* ApplyBioFeatToRaw () --                                             */
6261 /*                                                                     */
6262 /*---------------------------------------------------------------------*/
6263 
ApplyBioFeatToRaw(Uint2 entityID,SeqEntryPtr parentSep,SeqEntryPtr sep,ApplyFormPtr afp,Int2 onlythis)6264 static void ApplyBioFeatToRaw (Uint2        entityID,
6265 			       SeqEntryPtr  parentSep,
6266 			       SeqEntryPtr  sep,
6267 			       ApplyFormPtr afp,
6268 			       Int2         onlythis)
6269 
6270 {
6271   BioseqPtr     bsp;
6272   BioseqSetPtr  bssp;
6273   Int2          count;
6274   SeqEntryPtr   nucSep;
6275 
6276   /* Check parameters */
6277 
6278   if (sep == NULL || afp == NULL)
6279     return;
6280 
6281   /* If it is a set then recurse until we get to the raw Bioseq */
6282 
6283   if (IS_Bioseq_set (sep)) {
6284     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6285     if (bssp != NULL) {
6286       if (onlythis != 0 && bssp->_class == BioseqseqSet_class_parts) {
6287         for (sep = bssp->seq_set, count = 1;
6288              sep != NULL && count != onlythis;
6289              sep = sep->next, count++)
6290 	  continue;
6291         if (sep != NULL) {
6292           ApplyBioFeatToRaw (entityID, parentSep, sep, afp, onlythis);
6293         }
6294       } else {
6295         for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
6296           ApplyBioFeatToRaw (entityID, parentSep, sep, afp, onlythis);
6297         }
6298       }
6299       return;
6300     }
6301   }
6302 
6303   /* Get the nucleotide Bioseq */
6304 
6305   nucSep = FindNucSeqEntry (sep);
6306   if (nucSep == NULL)
6307     return;
6308 
6309   bsp = (BioseqPtr) nucSep->data.ptrvalue;
6310   if (bsp == NULL)
6311     return;
6312 
6313   /* If we've got a raw Bioseq then do the apply */
6314 
6315   if (bsp->repr == Seq_repr_raw) {
6316     RealApplyBioFeatToAll (entityID, nucSep, nucSep, afp, FALSE);
6317     /*
6318     RealApplyBioFeatToAll (entityID, parentSep, nucSep, afp, FALSE);
6319     */
6320   }
6321 }
6322 
6323 /*---------------------------------------------------------------------*/
6324 /*                                                                     */
6325 /* ApplyBioFeatToAll () --                                             */
6326 /*                                                                     */
6327 /*---------------------------------------------------------------------*/
6328 
ApplyBioFeatToAll(Uint2 entityID,SeqEntryPtr sep,ApplyFormPtr afp)6329 static void ApplyBioFeatToAll (Uint2        entityID,
6330 			       SeqEntryPtr  sep,
6331 			       ApplyFormPtr afp)
6332 
6333 {
6334   BioseqSetPtr  bssp;
6335   SeqEntryPtr   nsep;
6336   Int2          onlythis;
6337   Char          str [32];
6338   Boolean       suppressDups = FALSE;
6339 
6340   /* Check parameters */
6341 
6342   if (sep == NULL || afp == NULL)
6343     return;
6344 
6345   if (afp->add_to_seq_with_like_feature != NULL)
6346   {
6347     suppressDups = ! GetStatus (afp->add_to_seq_with_like_feature);
6348   }
6349 
6350   /* If it is a set then recurse until we get to a Bioseq */
6351 
6352   if (IS_Bioseq_set (sep)) {
6353     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6354     if (bssp != NULL) {
6355       if (bssp->_class == BioseqseqSet_class_genbank || IsPopPhyEtcSet (bssp->_class)) {
6356         for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
6357           ApplyBioFeatToAll (entityID, sep, afp);
6358         }
6359         return;
6360       } else if (bssp->_class == BioseqseqSet_class_gen_prod_set) {
6361         /* just the first item */
6362         ApplyBioFeatToAll (entityID, bssp->seq_set, afp);
6363         return;
6364       }
6365     }
6366   }
6367 
6368   /* Get the nucleotide Bioseq */
6369 
6370   nsep = FindNucSeqEntry (sep);
6371   if (nsep == NULL)
6372     return;
6373 
6374   /* Apply the feature */
6375 
6376   if (afp->applyToParts != NULL && GetStatus (afp->applyToParts)) {
6377     GetTitle (afp->onlyThisPart, str, sizeof (str));
6378     if (! StrToInt (str, &onlythis)) {
6379       onlythis = 0;
6380     }
6381     ApplyBioFeatToRaw (entityID, sep, sep, afp, onlythis);
6382   } else {
6383     RealApplyBioFeatToAll (entityID, sep, nsep, afp, suppressDups);
6384   }
6385 }
6386 
6387 /*---------------------------------------------------------------------*/
6388 /*                                                                     */
6389 /* ApplyBioFeatToAll () --                                             */
6390 /*                                                                     */
6391 /*---------------------------------------------------------------------*/
6392 
ApplyBioFeatToList(Uint2 entityID,SeqEntryPtr sep,ApplyFormPtr afp,ValNodePtr id_list)6393 static void ApplyBioFeatToList (Uint2        entityID,
6394 			       SeqEntryPtr  sep,
6395 			       ApplyFormPtr afp,
6396 			       ValNodePtr   id_list)
6397 
6398 {
6399   BioseqPtr     bsp;
6400   SeqEntryPtr   nsep, oldscope;
6401   Int2          onlythis;
6402   Char          str [32];
6403   Boolean       suppressDups = FALSE;
6404   ValNodePtr    vnp;
6405 
6406   /* Check parameters */
6407 
6408   if (sep == NULL || afp == NULL || id_list == NULL)
6409     return;
6410 
6411   if (afp->add_to_seq_with_like_feature != NULL)
6412   {
6413     suppressDups = ! GetStatus (afp->add_to_seq_with_like_feature);
6414   }
6415 
6416   oldscope = SeqEntrySetScope (sep);
6417   for (vnp = id_list; vnp != NULL; vnp = vnp->next) {
6418      bsp = BioseqFind (vnp->data.ptrvalue);
6419      if (bsp != NULL) {
6420        sep = SeqMgrGetSeqEntryForData (bsp);
6421 
6422        /* Get the nucleotide Bioseq */
6423        nsep = FindNucSeqEntry (sep);
6424        if (nsep == NULL)
6425          continue;
6426 
6427        /* Apply the feature */
6428 
6429        if (afp->applyToParts != NULL && GetStatus (afp->applyToParts)) {
6430          GetTitle (afp->onlyThisPart, str, sizeof (str));
6431          if (! StrToInt (str, &onlythis)) {
6432            onlythis = 0;
6433          }
6434          ApplyBioFeatToRaw (entityID, sep, sep, afp, onlythis);
6435        } else {
6436          RealApplyBioFeatToAll (entityID, sep, nsep, afp, suppressDups);
6437        }
6438     }
6439   }
6440 }
6441 
6442 
ApplyAnnotationToAll(Int2 type,SeqEntryPtr sep,ButtoN partialLft,ButtoN partialRgt,TexT geneName,TexT protName,TexT protDesc,TexT rnaName,TexT featcomment,TexT defline)6443 Int2 ApplyAnnotationToAll (Int2 type, SeqEntryPtr sep,
6444                            ButtoN partialLft, ButtoN partialRgt,
6445                            TexT geneName, TexT protName,
6446                            TexT protDesc, TexT rnaName,
6447                            TexT featcomment, TexT defline)
6448 
6449 {
6450   ApplyFormData  afd;
6451   RnaTypeData    rtd;
6452 
6453   MemSet ((Pointer) (&afd), 0, sizeof (ApplyFormData));
6454   afd.type = type;
6455   afd.errcount = 0;
6456   afd.ambigList = NULL;
6457   afd.partial5 = partialLft;
6458   afd.partial3 = partialRgt;
6459   afd.noLeft = GetStatus (afd.partial5);
6460   afd.noRight = GetStatus (afd.partial3);
6461   afd.feature_details_data = BatchApplyFeatureDetailsNew ();
6462   if (afd.feature_details_data == NULL)
6463   {
6464     return 1;
6465   }
6466 
6467   if (ADD_RRNA == type)
6468   {
6469     rtd.ncrna_class = NULL;
6470     rtd.rna_featdef = FEATDEF_rRNA;
6471     afd.feature_details_data->rnaType = &rtd;
6472   }
6473 
6474   if (geneName != NULL && ! TextHasNoText (geneName))
6475     afd.feature_details_data->geneName = SaveStringFromText (geneName);
6476   if (protName != NULL && ! TextHasNoText (protName))
6477     afd.feature_details_data->protName = SaveStringFromText (protName);
6478   if (protDesc != NULL && ! TextHasNoText (protDesc))
6479     afd.feature_details_data->protDesc = SaveStringFromText (protDesc);
6480   if (rnaName != NULL && ! TextHasNoText (rnaName))
6481     afd.feature_details_data->rnaName = SaveStringFromText (rnaName);
6482   if (featcomment != NULL && ! TextHasNoText (featcomment))
6483     afd.feature_details_data->featcomment = SaveStringFromText (featcomment);
6484   if (defline != NULL && ! TextHasNoText (defline))
6485     afd.feature_details_data->defline = SaveStringFromText (defline);
6486   ApplyBioFeatToAll (0, sep, &afd);
6487   if (afd.type == ADD_CDS) {
6488     return afd.errcount;
6489   }
6490   return 0;
6491 }
6492 
6493 static void CommonApplyToAllProcBfpInfo (Uint2 entityID,
6494                                          Uint4 itemID,
6495                                          Uint2 itemtype,
6496                                          Int2 type);
6497 
NowReadyToApplyToAll(ApplyFormPtr afp,DialoG gbquals)6498 static void NowReadyToApplyToAll (ApplyFormPtr afp, DialoG gbquals)
6499 
6500 {
6501   Uint2        parenttype;
6502   Pointer      parentptr;
6503   CharPtr      plural;
6504   SeqEntryPtr  sep;
6505   CharPtr      tmp;
6506   SeqEntryPtr  top;
6507   ValNodePtr   vnp;
6508   Char         path [PATH_MAX];
6509   FILE         *fp;
6510   ValNodePtr   id_list = NULL;
6511 
6512   if (afp == NULL) return;
6513   afp->gbquals = gbquals;
6514   sep = GetTopSeqEntryForEntityID (afp->input_entityID);
6515   if (sep == NULL) return;
6516   Hide (afp->form);
6517   WatchCursor ();
6518   Update ();
6519   afp->noLeft = GetStatus (afp->partial5);
6520   afp->noRight = GetStatus (afp->partial3);
6521   top = sep;
6522   if (afp->type == ADD_CDS) {
6523     GetSeqEntryParent (top, &parentptr, &parenttype);
6524   }
6525 
6526   if (afp->all_or_some_grp != NULL && GetValue (afp->all_or_some_grp) == 2) {
6527     tmp = SaveStringFromText (afp->accession_list_txt);
6528     id_list = ParseAccessionNumberListFromString(tmp, sep);
6529     tmp = MemFree (tmp);
6530     if (id_list == NULL) {
6531       ArrowCursor();
6532       Update();
6533       Show (afp->form);
6534       return;
6535     }
6536     ApplyBioFeatToList (afp->input_entityID, sep, afp, id_list);
6537     id_list = FreeSeqIdList (id_list);
6538     tmp = MemFree (tmp);
6539   } else {
6540     ApplyBioFeatToAll (afp->input_entityID, sep, afp);
6541   }
6542   ArrowCursor ();
6543   Update ();
6544   if (afp->errcount > 0 && afp->type == ADD_CDS) {
6545     TmpNam (path);
6546     fp = FileOpen (path, "w");
6547     if (fp != NULL) {
6548       if (afp->errcount > 1) {
6549         plural = "records";
6550       } else {
6551         plural = "record";
6552       }
6553       fprintf (fp, "Possible ambiguous frames detected in %d %s\n",
6554                (int) afp->errcount, plural);
6555       for (vnp = afp->ambigList; vnp != NULL; vnp = vnp->next) {
6556         tmp = (CharPtr) vnp->data.ptrvalue;
6557         fprintf (fp, "%s\n", tmp);
6558       }
6559       FileClose (fp);
6560       LaunchGeneralTextViewer (path, "Ambiguous Frames");
6561       FileRemove (path);
6562     }
6563   }
6564   ObjMgrSetDirtyFlag (afp->input_entityID, TRUE);
6565   ObjMgrSendMsg (OM_MSG_UPDATE, afp->input_entityID, 0, 0);
6566   if (GetStatus (afp->leaveDlgUp))
6567   {
6568     afp->ambigList = ValNodeFreeData (afp->ambigList);
6569     Show (afp->form);
6570   }
6571   else
6572   {
6573     Remove (afp->form);
6574   }
6575 }
6576 
6577 typedef struct qualsform {
6578   FEATURE_FORM_BLOCK
6579 
6580   ApplyFormPtr  afp;
6581 } QualsForm, PNTR QualsFormPtr;
6582 
CallNowReady(ButtoN b)6583 static void CallNowReady (ButtoN b)
6584 
6585 {
6586   QualsFormPtr  qfp;
6587 
6588   qfp = (QualsFormPtr) GetObjectExtra (b);
6589   if (qfp == NULL) return;
6590   Hide (qfp->form);
6591   NowReadyToApplyToAll (qfp->afp, qfp->gbquals);
6592   Remove (qfp->form);
6593 }
6594 
6595 
DoTheApplyToAllProc(ButtoN b)6596 static void DoTheApplyToAllProc (ButtoN b)
6597 
6598 {
6599   ApplyFormPtr       afp;
6600   CharPtr            name;
6601   QualsFormPtr       qfp;
6602   WindoW             w;
6603 
6604   afp = GetObjectExtra (b);
6605   if (afp == NULL) {
6606     Remove (ParentWindow (b));
6607     return;
6608   }
6609 
6610   afp->feature_details_data = DialogToPointer (afp->feature_details_dlg);
6611 
6612   if (afp->type == ADD_IMP) {
6613     /* if gene, do not collect quals */
6614     if (afp->feature_details_data->featdef_choice != FEATDEF_GENE)
6615     {
6616       qfp = (QualsFormPtr) MemNew (sizeof (QualsForm));
6617       if (qfp != NULL) {
6618         Hide (afp->form);
6619         Update ();
6620         name = afp->feature_details_data->featdef_name;
6621         qfp->afp = afp;
6622         w = FixedWindow (-50, -33, -10, -10, "Qualifiers", StdCloseWindowProc);
6623         SetObjectExtra (w, qfp, StdCleanupFormProc);
6624         qfp->form = (ForM) w;
6625         CreateStandardEditMenu (w);
6626         qfp->gbquals = NewCreateImportFields (w, name, NULL, FALSE);
6627         b = PushButton (w, "Okay", CallNowReady);
6628         SetObjectExtra (b, qfp, NULL);
6629         AlignObjects (ALIGN_CENTER, (HANDLE) qfp->gbquals, (HANDLE) b, NULL);
6630         RealizeWindow (w);
6631         Show (w);
6632         Select (w);
6633       }
6634     } else {
6635       NowReadyToApplyToAll (afp, NULL);
6636     }
6637   }
6638   else if (afp->type == ADD_TITLE)
6639   {
6640     if (StringHasNoText(afp->feature_details_data->defline)) {
6641         /* do nothing, no defline text */
6642         ObjMgrSetDirtyFlag(afp->input_entityID, TRUE);
6643         ObjMgrSendMsg(OM_MSG_UPDATE, afp->input_entityID, 0, 0);
6644         Remove(afp->form);
6645     } else if (Message(MSG_OKC, "%s", kDoNotEditTitle) == ANS_CANCEL) {
6646         /* do nothing */
6647     } else {
6648         afp->gsp = GetSampleNew();
6649         afp->type = CHECK_TITLE;
6650         NowReadyToApplyToAll(afp, NULL);
6651         afp->etp = GetExistingTextHandlerInfo(afp->gsp == NULL ? 0 : afp->gsp->num_found, FALSE);
6652         afp->gsp = GetSampleFree(afp->gsp);
6653         afp->type = ADD_TITLE;
6654         if (afp->etp == NULL
6655             || afp->etp->existing_text_choice != eExistingTextChoiceCancel)
6656         {
6657             NowReadyToApplyToAll(afp, NULL);
6658         }
6659         afp->etp = MemFree(afp->etp);
6660     }
6661   } else {
6662     NowReadyToApplyToAll (afp, NULL);
6663   }
6664 }
6665 
ApplyToPartsProc(ButtoN b)6666 static void ApplyToPartsProc (ButtoN b)
6667 
6668 {
6669   ApplyFormPtr  afp;
6670 
6671   afp = (ApplyFormPtr) GetObjectExtra (b);
6672   if (afp == NULL) return;
6673   if (GetStatus (b)) {
6674     SafeEnable (afp->onlyThisPart);
6675   } else {
6676     SafeDisable (afp->onlyThisPart);
6677   }
6678 }
6679 
LookForParts(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)6680 static void LookForParts (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
6681 
6682 {
6683   BioseqSetPtr  bssp;
6684   BoolPtr       rsult;
6685 
6686   if (IS_Bioseq_set (sep)) {
6687     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6688     if (bssp != NULL && bssp->_class == BioseqseqSet_class_parts) {
6689       rsult = (BoolPtr) mydata;
6690       if (rsult != NULL) {
6691         *rsult = TRUE;
6692       }
6693     }
6694   }
6695 }
6696 
6697 extern Boolean HasPartsSet (SeqEntryPtr sep);
HasPartsSet(SeqEntryPtr sep)6698 extern Boolean HasPartsSet (SeqEntryPtr sep)
6699 
6700 {
6701   Boolean  rsult = FALSE;
6702 
6703   SeqEntryExplore (sep, (Pointer) (&rsult), LookForParts);
6704   return rsult;
6705 }
6706 
EnableApplyCdsCoords(GrouP g)6707 static void EnableApplyCdsCoords (GrouP g)
6708 {
6709   ApplyFormPtr afp;
6710 
6711   afp = (ApplyFormPtr) GetObjectExtra (g);
6712   if (afp == NULL) return;
6713   if (GetValue (g) == 1)
6714   {
6715   	Disable (afp->left_end);
6716   	Disable (afp->right_end);
6717   }
6718   else
6719   {
6720   	Enable (afp->left_end);
6721   	Enable (afp->right_end);
6722   }
6723 }
6724 
ApplyMessageProc(ForM f,Int2 mssg)6725 static void ApplyMessageProc (ForM f, Int2 mssg)
6726 
6727 {
6728   ApplyFormPtr  afp;
6729 
6730   afp = (ApplyFormPtr) GetObjectExtra (f);
6731   if (afp != NULL) {
6732     if (afp->appmessage != NULL) {
6733       afp->appmessage (f, mssg);
6734     }
6735   }
6736 }
6737 
CleanupApplyToAllForm(GraphiC g,VoidPtr data)6738 static void CleanupApplyToAllForm (GraphiC g, VoidPtr data)
6739 
6740 {
6741   ApplyFormPtr  afp;
6742 
6743   afp = (ApplyFormPtr) data;
6744   if (afp != NULL) {
6745     afp->feature_details_data = BatchApplyFeatureDetailsFree (afp->feature_details_data);
6746     ValNodeFreeData (afp->ambigList);
6747   }
6748   StdCleanupFormProc (g, data);
6749 }
6750 
ChangeAllOrSome(GrouP g)6751 static void ChangeAllOrSome (GrouP g)
6752 {
6753   ApplyFormPtr       afp;
6754 
6755   afp = (ApplyFormPtr) GetObjectExtra (g);
6756   if (afp != NULL) {
6757     if (GetValue(g) == 1) {
6758       Disable (afp->accession_list_txt);
6759     } else {
6760       Enable (afp->accession_list_txt);
6761     }
6762   }
6763 }
6764 
6765 
EnableApplyFeatureAccept(Pointer data)6766 static void EnableApplyFeatureAccept (Pointer data)
6767 {
6768   ApplyFormPtr afp;
6769 
6770   afp = (ApplyFormPtr) data;
6771   if (afp == NULL) return;
6772 
6773   if (OkToAcceptBatchApplyFeatureDetails (afp->feature_details_dlg))
6774   {
6775     Enable (afp->accept);
6776   }
6777   else
6778   {
6779     Disable (afp->accept);
6780   }
6781 }
6782 
6783 
CommonApplyToAllProcBfpInfo(Uint2 entityID,Uint4 itemID,Uint2 itemtype,Int2 type)6784 static void CommonApplyToAllProcBfpInfo (Uint2 entityID,
6785                                          Uint4 itemID,
6786                                          Uint2 itemtype,
6787                                          Int2 type)
6788 {
6789   ApplyFormPtr       afp;
6790   GrouP              c;
6791   GrouP              g = NULL;
6792   GrouP              h;
6793   GrouP              r2, r3, r4;
6794   SeqEntryPtr        sep;
6795   StdEditorProcsPtr  sepp;
6796   WindoW             w;
6797   GrouP              x;
6798   GrouP              parts_group = NULL;
6799   GrouP              feature_details = NULL;
6800   GrouP              indexer_only_group = NULL;
6801 
6802   sep = GetTopSeqEntryForEntityID (entityID);
6803   if (sep == NULL) return;
6804   afp = (ApplyFormPtr) MemNew (sizeof (ApplyFormData));
6805   if (afp == NULL) return;
6806   w = FixedWindow (-50, -33, -10, -10, "Automatic Processing", StdCloseWindowProc);
6807   SetObjectExtra (w, afp, CleanupApplyToAllForm);
6808   afp->form = (ForM) w;
6809   afp->formmessage = ApplyMessageProc;
6810 
6811   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
6812   if (sepp != NULL) {
6813     SetActivate (w, sepp->activateForm);
6814     afp->appmessage = sepp->handleMessages;
6815   }
6816 
6817   afp->input_entityID = entityID;
6818   afp->input_itemID = itemID;
6819   afp->input_itemtype = itemtype;
6820 
6821   h = HiddenGroup (w, -1, 0, NULL);
6822   SetGroupSpacing (h, 10, 10);
6823 
6824   afp->type = type;
6825   afp->errcount = 0;
6826 
6827   if (HasPartsSet (sep)) {
6828     parts_group = HiddenGroup (h, 1, 0, NULL);
6829     afp->applyToParts = CheckBox (parts_group, "Apply to segmented parts, not segmented sequence", ApplyToPartsProc);
6830     SetObjectExtra (afp->applyToParts, afp, NULL);
6831     x = HiddenGroup (parts_group, 2, 0, NULL);
6832     StaticPrompt (x, "Apply only to particular numbered segment", 0, dialogTextHeight, programFont, 'l');
6833     afp->onlyThisPart = DialogText (x, "", 4, NULL);
6834     Disable (afp->onlyThisPart);
6835   }
6836 
6837   afp->strand_group = NULL;
6838   afp->add_to_seq_with_like_feature = NULL;
6839   afp->also_add_mRNA_btn = NULL;
6840 
6841   if (type == ADD_CDS || type == ADD_RRNA || type == ADD_IMP) {
6842     /* create group to hold feature details */
6843     feature_details = HiddenGroup (h, -1, 0, NULL);
6844 
6845     /* group for feature completeness */
6846     g = HiddenGroup (feature_details, 2, 0, NULL);
6847     afp->partial5 = CheckBox (g, "Incomplete at 5' end", NULL);
6848     afp->partial3 = CheckBox (g, "Incomplete at 3' end", NULL);
6849 
6850     /* group for strand */
6851     afp->strand_group = HiddenGroup (feature_details, 2, 0, NULL);
6852     SetObjectExtra (afp->strand_group, afp, NULL);
6853     RadioButton (afp->strand_group, "Plus Strand");
6854     RadioButton (afp->strand_group, "Minus Strand");
6855     SetValue (afp->strand_group, 1);
6856 
6857     /* coordinates */
6858     if (indexerVersion)
6859     {
6860       indexer_only_group = HiddenGroup (feature_details, -1, 0, NULL);
6861       r2 = HiddenGroup (indexer_only_group, 5, 0, NULL);
6862       afp->use_whole_interval = HiddenGroup (r2, 0, 2, EnableApplyCdsCoords);
6863       SetObjectExtra (afp->use_whole_interval, afp, NULL);
6864       RadioButton (afp->use_whole_interval, "Use Whole Sequence Interval");
6865       RadioButton (afp->use_whole_interval, "Use these coordinates:");
6866       r3 = HiddenGroup (r2, 0, 2, NULL);
6867       StaticPrompt (r3, "", 0, dialogTextHeight, programFont, 'l');
6868       r4 = HiddenGroup (r3, 4, 0, NULL);
6869       StaticPrompt (r4, "From", 0, dialogTextHeight, programFont, 'l');
6870       afp->left_end = DialogText (r4, "1", 5, NULL);
6871       StaticPrompt (r4, "To", 0, dialogTextHeight, programFont, 'l');
6872       afp->right_end = DialogText (r4, "1", 5, NULL);
6873       SetValue (afp->use_whole_interval, 1);
6874       Disable (afp->left_end);
6875       Disable (afp->right_end);
6876 
6877       /* apply to some sequences or all sequences */
6878       afp->all_or_some_grp = HiddenGroup (indexer_only_group, 1, 0, ChangeAllOrSome);
6879       SetObjectExtra (afp->all_or_some_grp, afp, NULL);
6880       RadioButton (afp->all_or_some_grp, "Apply to all sequences");
6881       RadioButton (afp->all_or_some_grp, "Apply to sequences in this list");
6882       afp->accession_list_txt = DialogText (afp->all_or_some_grp, "", 25, NULL);
6883       SetValue (afp->all_or_some_grp, 1);
6884       ChangeAllOrSome(afp->all_or_some_grp);
6885 
6886       /* add to features that already have same */
6887       if (type == ADD_CDS)
6888       {
6889         afp->add_to_seq_with_like_feature = CheckBox (indexer_only_group, "Also add to sequences that already have a CDS", NULL);
6890         afp->also_add_mRNA_btn = CheckBox (indexer_only_group, "Also add mRNA", NULL);
6891         SetStatus (afp->also_add_mRNA_btn, FALSE);
6892       }
6893       else if (type == ADD_RRNA)
6894       {
6895         afp->add_to_seq_with_like_feature = CheckBox (indexer_only_group, "Also add to sequences that already have an rRNA", NULL);
6896       }
6897       else if (type == ADD_IMP)
6898       {
6899         afp->add_to_seq_with_like_feature = CheckBox (indexer_only_group, "Also add to sequences that already have this feature", NULL);
6900       }
6901       SafeSetStatus (afp->add_to_seq_with_like_feature, TRUE);
6902       AlignObjects (ALIGN_CENTER, (HANDLE) r2,
6903                                    (HANDLE) afp->add_to_seq_with_like_feature,
6904                                    (HANDLE) afp->also_add_mRNA_btn,
6905                                    NULL);
6906     }
6907     else
6908     {
6909       afp->use_whole_interval = NULL;
6910       afp->all_or_some_grp = NULL;
6911       afp->accession_list_txt = NULL;
6912     }
6913 
6914     AlignObjects (ALIGN_CENTER, (HANDLE) g,
6915                                 (HANDLE) afp->strand_group,
6916                                 (HANDLE) indexer_only_group,
6917                                 NULL);
6918   }
6919   afp->feature_details_dlg = BatchApplyFeatureDetailsDialog (h, type, EnableApplyFeatureAccept, afp);
6920 
6921 
6922   afp->gbquals = NULL;
6923 
6924   c = HiddenGroup (h, 4, 0, NULL);
6925   afp->accept = DefaultButton (c, "Accept", DoTheApplyToAllProc);
6926   SetObjectExtra (afp->accept, afp, NULL);
6927   PushButton (c, "Cancel", StdCancelButtonProc);
6928   afp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
6929 
6930   if (parts_group == NULL)
6931   {
6932     AlignObjects (ALIGN_CENTER, (HANDLE) c,
6933                                 (HANDLE) afp->feature_details_dlg,
6934                                 (HANDLE) feature_details,
6935                                 NULL);
6936   }
6937   else
6938   {
6939     AlignObjects (ALIGN_CENTER, (HANDLE) parts_group,
6940                                 (HANDLE) c,
6941                                 (HANDLE) afp->feature_details_dlg,
6942                                 (HANDLE) feature_details,
6943                                 NULL);
6944   }
6945 
6946   EnableApplyFeatureAccept (afp);
6947   RealizeWindow (w);
6948   Show (w);
6949   SendMessageToDialog (afp->feature_details_dlg, VIB_MSG_ENTER);
6950   Update ();
6951 }
6952 
CommonApplyToAllProc(BaseFormPtr bfp,Int2 type)6953 extern void CommonApplyToAllProc (BaseFormPtr bfp, Int2 type)
6954 {
6955   if (bfp == NULL) return;
6956   CommonApplyToAllProcBfpInfo (bfp->input_entityID,
6957                                bfp->input_itemID,
6958                                bfp->input_itemtype, type);
6959 }
6960 
CommonApplyToAllProcMenuItem(IteM i,Int2 type)6961 static void CommonApplyToAllProcMenuItem (IteM i, Int2 type)
6962 {
6963   BaseFormPtr bfp;
6964 
6965 #ifdef WIN_MAC
6966   bfp = currentFormDataPtr;
6967 #else
6968   bfp = GetObjectExtra (i);
6969 #endif
6970   if (bfp == NULL) return;
6971 
6972   CommonApplyToAllProc (bfp, type);
6973 }
6974 
6975 
ApplyCDSBtn(ButtoN b)6976 extern void ApplyCDSBtn (ButtoN b)
6977 {
6978   BaseFormPtr bfp;
6979 
6980   bfp = (BaseFormPtr) GetObjectExtra (b);
6981   if (bfp == NULL) {
6982     return;
6983   }
6984   CommonApplyToAllProc (bfp, ADD_CDS);
6985 }
6986 
6987 
ApplyTitle(IteM i)6988 extern void ApplyTitle (IteM i)
6989 
6990 {
6991   CommonApplyToAllProcMenuItem (i, ADD_TITLE);
6992 }
6993 
ApplyCDS(IteM i)6994 extern void ApplyCDS (IteM i)
6995 
6996 {
6997   CommonApplyToAllProcMenuItem (i, ADD_CDS);
6998 }
6999 
ApplyRRNA(IteM i)7000 extern void ApplyRRNA (IteM i)
7001 
7002 {
7003   CommonApplyToAllProcMenuItem (i, ADD_RRNA);
7004 }
7005 
ApplyImpFeat(IteM i)7006 extern void ApplyImpFeat (IteM i)
7007 
7008 {
7009   CommonApplyToAllProcMenuItem (i, ADD_IMP);
7010 }
7011 
7012 #define SUBMISSION_PAGE   0
7013 #define CONTACT_PAGE      1
7014 #define AUTHOR_PAGE       2
7015 #define AFFILIATION_PAGE  3
7016 
7017 typedef struct submitform {
7018   FORM_MESSAGE_BLOCK
7019   GrouP           pages [4];
7020   Int2            currentPage;
7021   DialoG          tbs;
7022 
7023   GrouP           hup;
7024   GrouP           dateGrp;
7025 
7026   TexT            title;
7027   DialoG          reldate;
7028   TexT            firstname;
7029   TexT            middleinit;
7030   TexT            lastname;
7031   PopuP           suffix;
7032   DialoG          phonefaxemail;
7033   DialoG          authors;
7034   ButtoN          use_consortium;
7035   TexT            consortium;
7036   DialoG          affil;
7037 
7038   Boolean         visitedContact;
7039   Boolean         visitedAuthor;
7040 
7041   SeqDescrPtr     descriptors;
7042 
7043   ButtoN          nextBtn;
7044   ButtoN          prevBtn;
7045   BtnActnProc     goToNext;
7046   BtnActnProc     goToPrev;
7047 } SubmitForm, PNTR SubmitFormPtr;
7048 
AddConsortiumToAuthList(AuthListPtr alp,TexT consortium)7049 static AuthListPtr AddConsortiumToAuthList (AuthListPtr alp, TexT consortium)
7050 
7051 {
7052   AuthorPtr    ap;
7053   ValNodePtr   names;
7054   PersonIdPtr  pid;
7055 
7056   if (TextHasNoText (consortium)) return alp;
7057   if (alp == NULL) {
7058     alp = AuthListNew ();
7059     alp->choice = 1;
7060   }
7061   pid = PersonIdNew ();
7062   if (pid == NULL) return NULL;
7063   pid->choice = 5;
7064   pid->data = SaveStringFromText (consortium);
7065   ap = AuthorNew ();
7066   if (ap == NULL) return NULL;
7067   ap->name = pid;
7068   names = ValNodeAdd (&(alp->names));
7069   names->choice = 1;
7070   names->data.ptrvalue = ap;
7071   return alp;
7072 }
7073 
AuthListToConsortium(AuthListPtr alp,TexT consortium)7074 static Boolean AuthListToConsortium (AuthListPtr alp, TexT consortium)
7075 
7076 {
7077   AuthorPtr    ap;
7078   ValNodePtr   names;
7079   PersonIdPtr  pid;
7080   CharPtr      str;
7081   Boolean      rval = FALSE;
7082 
7083   if (alp == NULL || consortium == NULL) return FALSE;
7084   if (alp->choice != 1) return FALSE;
7085   for (names = alp->names; names != NULL; names = names->next) {
7086     ap = names->data.ptrvalue;
7087     if (ap == NULL) continue;
7088     pid = ap->name;
7089     if (pid == NULL || pid->choice != 5 || StringHasNoText (pid->data)) continue;
7090     str = (CharPtr) pid->data;
7091     SafeSetTitle (consortium, str);
7092     rval = TRUE;
7093   }
7094   return rval;
7095 }
7096 
SequinBlockPtrToSubmitForm(ForM f,Pointer data)7097 static void SequinBlockPtrToSubmitForm (ForM f, Pointer data)
7098 
7099 {
7100   AuthorPtr       ap;
7101   DatePtr         dp;
7102   NameStdPtr      nsp;
7103   PersonIdPtr     pid;
7104   SubmitFormPtr   sbfp;
7105   SequinBlockPtr  sbp;
7106   CharPtr         str;
7107   CharPtr         txt;
7108 
7109   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7110   sbp = (SequinBlockPtr) data;
7111   if (sbfp != NULL) {
7112     sbfp->descriptors = SeqDescrFree (sbfp->descriptors);
7113     if (sbp != NULL) {
7114       SafeSetTitle (sbfp->title, sbp->citsubtitle);
7115       PointerToDialog (sbfp->reldate, (Pointer) sbp->releasedate);
7116       ap = sbp->contactperson;
7117       if (ap != NULL) {
7118         pid = ap->name;
7119         if (pid != NULL && pid->choice == 2) {
7120           nsp = pid->data;
7121           if (nsp != NULL) {
7122             str = NameStdPtrToAuthorSpreadsheetString (nsp);
7123             if (str != NULL) {
7124               txt = ExtractTagListColumn (str, 0);
7125               SafeSetTitle (sbfp->firstname, txt);
7126               MemFree (txt);
7127               txt = ExtractTagListColumn (str, 1);
7128               SafeSetTitle (sbfp->middleinit, txt);
7129               MemFree (txt);
7130               txt = ExtractTagListColumn (str, 2);
7131               SafeSetTitle (sbfp->lastname, txt);
7132               MemFree (txt);
7133               txt = ExtractTagListColumn (str, 3);
7134               if (! StringHasNoText (txt)) {
7135                 SetEnumPopupByName (sbfp->suffix, name_suffix_alist, txt);
7136               }
7137               /*
7138               SafeSetTitle (sbfp->suffix, txt);
7139               */
7140               MemFree (txt);
7141               MemFree (str);
7142             }
7143           }
7144         }
7145         PointerToDialog (sbfp->phonefaxemail, (Pointer) ap->affil);
7146       }
7147       PointerToDialog (sbfp->authors, (Pointer) sbp->citsubauthors);
7148       if (AuthListToConsortium (sbp->citsubauthors, sbfp->consortium)) {
7149         SetStatus (sbfp->use_consortium, TRUE);
7150         Enable (sbfp->consortium);
7151       } else {
7152         SetStatus (sbfp->use_consortium, FALSE);
7153         Disable (sbfp->consortium);
7154       }
7155 
7156       PointerToDialog (sbfp->affil, (Pointer) sbp->citsubaffil);
7157       if (sbp->holduntilpublished) {
7158         SafeSetValue (sbfp->hup, 2);
7159         SafeShow (sbfp->dateGrp);
7160       } else {
7161         SafeSetValue (sbfp->hup, 1);
7162         SafeHide (sbfp->dateGrp);
7163       }
7164       sbfp->visitedAuthor = TRUE;
7165       SetValue (sbfp->tbs, 0);
7166       sbfp->descriptors = (SeqDescrPtr) AsnIoMemCopy (sbp->descriptors, (AsnReadFunc)SeqDescrAsnRead, (AsnWriteFunc) SeqDescrAsnWrite);
7167     } else {
7168       SafeSetTitle (sbfp->title, NULL);
7169       dp = DateCurr ();
7170       if (dp != NULL) {
7171         dp->data [3] = 0; /* force to end of month */
7172         dp = DateAdvance (dp, 12);
7173         /*
7174         (dp->data [1])++;
7175         if (dp->data [2] == 2 && dp->data [3] > 28) {
7176           dp->data [3] = 28;
7177         }
7178         */
7179         PointerToDialog (sbfp->reldate, (Pointer) dp);
7180       } else {
7181         PointerToDialog (sbfp->reldate, NULL);
7182       }
7183       DateFree (dp);
7184       SafeSetTitle (sbfp->firstname, "");
7185       SafeSetTitle (sbfp->middleinit, "");
7186       SafeSetTitle (sbfp->lastname, "");
7187       PointerToDialog (sbfp->phonefaxemail, NULL);
7188       PointerToDialog (sbfp->authors, NULL);
7189       SafeSetTitle (sbfp->consortium, "");
7190       PointerToDialog (sbfp->affil, NULL);
7191       SafeSetValue (sbfp->hup, 1);
7192       SafeHide (sbfp->dateGrp);
7193       SetValue (sbfp->tbs, 0);
7194     }
7195   }
7196 }
7197 
7198 
ContactNameFromSubmitForm(SubmitFormPtr sbfp)7199 static CharPtr ContactNameFromSubmitForm (SubmitFormPtr sbfp)
7200 {
7201   Char            str [128];
7202   CharPtr         txt;
7203   Uint2           suffixVal;
7204   Char            sfx [32];
7205 
7206   if (sbfp == NULL) {
7207     return NULL;
7208   }
7209 
7210   str [0] = '\0';
7211   txt = SaveStringFromText (sbfp->firstname);
7212   StringCat (str, txt);
7213   StringCat (str, "\t");
7214   MemFree (txt);
7215   txt = SaveStringFromText (sbfp->middleinit);
7216   StringCat (str, txt);
7217   StringCat (str, "\t");
7218   MemFree (txt);
7219   txt = SaveStringFromText (sbfp->lastname);
7220   StringCat (str, txt);
7221   StringCat (str, "\t");
7222   MemFree (txt);
7223   suffixVal = GetValue (sbfp->suffix);
7224   sprintf (sfx, "%d", (int) (suffixVal - 1));
7225   StringCat (str, sfx);
7226   StringCat (str, "\n");
7227   txt = StringSave (str);
7228   return txt;
7229 }
7230 
7231 
FixSubmitFormSpecialCharacters(SubmitFormPtr sbfp)7232 static void FixSubmitFormSpecialCharacters (SubmitFormPtr sbfp)
7233 {
7234   ValNodePtr list = NULL;
7235   CharPtr         citsubtitle;
7236   AffilPtr        affil;
7237   CharPtr         firstname;
7238   CharPtr         middleinit;
7239   CharPtr         lastname;
7240 
7241   if (sbfp == NULL) {
7242     return;
7243   }
7244 
7245   citsubtitle = SaveStringFromText (sbfp->title);
7246   SpecialCharFindWithContext (&citsubtitle, &list, NULL, NULL);
7247 
7248   firstname = SaveStringFromText (sbfp->firstname);
7249   middleinit = SaveStringFromText (sbfp->middleinit);
7250   lastname = SaveStringFromText (sbfp->lastname);
7251 
7252   SpecialCharFindWithContext (&firstname, &list, NULL, NULL);
7253   SpecialCharFindWithContext (&middleinit, &list, NULL, NULL);
7254   SpecialCharFindWithContext (&lastname, &list, NULL, NULL);
7255 
7256   affil = (AffilPtr) DialogToPointer (sbfp->phonefaxemail);
7257   if (affil != NULL) {
7258     SpecialCharFindWithContext (&(affil->fax), &list, NULL, NULL);
7259     SpecialCharFindWithContext (&(affil->phone), &list, NULL, NULL);
7260     SpecialCharFindWithContext (&(affil->email), &list, NULL, NULL);
7261   }
7262 
7263   if (list != NULL) {
7264     FixSpecialCharactersForStringsInList (list, "You must replace all non-ASCII characters.", TRUE);
7265     SetTitle (sbfp->title, citsubtitle);
7266     SetTitle (sbfp->firstname, firstname);
7267     SetTitle (sbfp->middleinit, middleinit);
7268     SetTitle (sbfp->lastname, lastname);
7269     PointerToDialog (sbfp->phonefaxemail, affil);
7270     FreeContextList (list);
7271   }
7272 
7273   citsubtitle = MemFree (citsubtitle);
7274   firstname = MemFree (firstname);
7275   middleinit = MemFree (middleinit);
7276   lastname = MemFree (lastname);
7277   affil = AffilFree (affil);
7278 }
7279 
7280 
SubmitFormToSequinBlockPtr(ForM f)7281 static Pointer SubmitFormToSequinBlockPtr (ForM f)
7282 
7283 {
7284   AffilPtr        affil;
7285   AuthorPtr       ap;
7286   NameStdPtr      nsp;
7287   PersonIdPtr     pid;
7288   SubmitFormPtr   sbfp;
7289   SequinBlockPtr  sbp;
7290   CharPtr         txt;
7291 
7292   sbp = NULL;
7293   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7294   if (sbfp != NULL) {
7295     FixSubmitFormSpecialCharacters(sbfp);
7296     sbp = (SequinBlockPtr) MemNew (sizeof (SequinBlock));
7297     if (sbp != NULL) {
7298       sbp->citsubtitle = SaveStringFromTextAndStripNewlines (sbfp->title);
7299       ap = AuthorNew ();
7300       if (ap != NULL) {
7301         pid = PersonIdNew ();
7302         ap->name = pid;
7303         if (pid != NULL) {
7304           pid->choice = 2;
7305           txt = ContactNameFromSubmitForm (sbfp);
7306           nsp = AuthorSpreadsheetStringToNameStdPtr (txt);
7307           MemFree (txt);
7308           pid->data = nsp;
7309           if (nsp != NULL) {
7310             if (StringHasNoText (nsp->names [0])) {
7311               ap = AuthorFree (ap);
7312             }
7313           }
7314         }
7315         affil = (AffilPtr) DialogToPointer (sbfp->phonefaxemail);
7316         if (affil != NULL) {
7317           if (affil->choice == 2) {
7318             affil->affil = MemFree (affil->affil);
7319             affil->div = MemFree (affil->div);
7320             affil->city = MemFree (affil->city);
7321             affil->sub = MemFree (affil->sub);
7322             affil->country = MemFree (affil->country);
7323             affil->street = MemFree (affil->street);
7324             affil->postal_code = MemFree (affil->postal_code);
7325             if (affil->phone == NULL && affil->fax == NULL &&
7326                 affil->email == NULL) {
7327               affil = AffilFree (affil);
7328             }
7329           } else {
7330             affil = AffilFree (affil);
7331           }
7332         }
7333         if (affil != NULL) {
7334           if (ap == NULL) {
7335             ap = AuthorNew();
7336           }
7337           ap->affil = affil;
7338         }
7339       }
7340       sbp->contactperson = ap;
7341       sbp->citsubauthors = (AuthListPtr) DialogToPointer (sbfp->authors);
7342       if (GetStatus (sbfp->use_consortium)) {
7343         sbp->citsubauthors = AddConsortiumToAuthList (sbp->citsubauthors, sbfp->consortium);
7344       }
7345       sbp->citsubaffil = (AffilPtr) DialogToPointer (sbfp->affil);
7346       if (GetValue (sbfp->hup) == 2) {
7347         sbp->holduntilpublished = TRUE;
7348         sbp->releasedate = (DatePtr) DialogToPointer (sbfp->reldate);
7349       }
7350       sbp->descriptors = (SeqDescrPtr) AsnIoMemCopy (sbfp->descriptors, (AsnReadFunc)SeqDescrAsnRead, (AsnWriteFunc) SeqDescrAsnWrite);
7351       if (sbp->contactperson == NULL &&
7352           sbp->citsubauthors == NULL &&
7353           sbp->citsubaffil == NULL &&
7354           sbp->descriptors == NULL) {
7355         sbp = SequinBlockFree (sbp);
7356       }
7357     }
7358   }
7359   return (Pointer) sbp;
7360 }
7361 
SubmitBlockPtrToSubmitForm(ForM f,Pointer data)7362 static void SubmitBlockPtrToSubmitForm (ForM f, Pointer data)
7363 
7364 {
7365   AuthorPtr       ap;
7366   AuthListPtr     authors;
7367   ContactInfoPtr  cip;
7368   CitSubPtr       csp;
7369   DatePtr         dp;
7370   NameStdPtr      nsp;
7371   PersonIdPtr     pid;
7372   SubmitFormPtr   sbfp;
7373   SubmitBlockPtr  sbp;
7374   CharPtr         str;
7375   CharPtr         txt;
7376 
7377   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7378   sbp = (SubmitBlockPtr) data;
7379   if (sbfp != NULL) {
7380     if (sbp != NULL) {
7381       PointerToDialog (sbfp->reldate, (Pointer) sbp->reldate);
7382       cip = sbp->contact;
7383       if (cip != NULL) {
7384         ap = cip->contact;
7385         if (ap != NULL) {
7386           pid = ap->name;
7387           if (pid != NULL && pid->choice == 2) {
7388             nsp = pid->data;
7389             if (nsp != NULL) {
7390               str = NameStdPtrToAuthorSpreadsheetString (nsp);
7391               if (str != NULL) {
7392                 txt = ExtractTagListColumn (str, 0);
7393                 SafeSetTitle (sbfp->firstname, txt);
7394                 MemFree (txt);
7395                 txt = ExtractTagListColumn (str, 1);
7396                 SafeSetTitle (sbfp->middleinit, txt);
7397                 MemFree (txt);
7398                 txt = ExtractTagListColumn (str, 2);
7399                 SafeSetTitle (sbfp->lastname, txt);
7400                 MemFree (txt);
7401                 txt = ExtractTagListColumn (str, 3);
7402                 if (! StringHasNoText (txt)) {
7403                   SetEnumPopupByName (sbfp->suffix, name_suffix_alist, txt);
7404                 }
7405                 /*
7406                 SafeSetTitle (sbfp->suffix, txt);
7407                 */
7408                 MemFree (txt);
7409                 MemFree (str);
7410               }
7411             }
7412           }
7413           PointerToDialog (sbfp->phonefaxemail, (Pointer) ap->affil);
7414         }
7415       }
7416       csp = sbp->cit;
7417       if (csp != NULL) {
7418         authors = csp->authors;
7419         if (authors != NULL) {
7420           PointerToDialog (sbfp->authors, (Pointer) authors);
7421           if (AuthListToConsortium (authors, sbfp->consortium)) {
7422             SetStatus (sbfp->use_consortium, TRUE);
7423             Enable (sbfp->consortium);
7424           } else {
7425             SetStatus (sbfp->use_consortium, FALSE);
7426             Disable (sbfp->consortium);
7427           }
7428           PointerToDialog (sbfp->affil, (Pointer) authors->affil);
7429         }
7430       }
7431       if (sbp->hup) {
7432         SafeSetValue (sbfp->hup, 2);
7433         SafeShow (sbfp->dateGrp);
7434       } else {
7435         SafeSetValue (sbfp->hup, 1);
7436         SafeHide (sbfp->dateGrp);
7437       }
7438       sbfp->visitedAuthor = TRUE;
7439       SetValue (sbfp->tbs, 0);
7440     } else {
7441       SafeSetTitle (sbfp->title, NULL);
7442       dp = DateCurr ();
7443       if (dp != NULL) {
7444         dp->data [3] = 0; /* force to end of month */
7445         dp = DateAdvance (dp, 12);
7446         PointerToDialog (sbfp->reldate, (Pointer) dp);
7447       } else {
7448         PointerToDialog (sbfp->reldate, NULL);
7449       }
7450       DateFree (dp);
7451       SafeSetTitle (sbfp->firstname, "");
7452       SafeSetTitle (sbfp->middleinit, "");
7453       SafeSetTitle (sbfp->lastname, "");
7454       SafeSetValue (sbfp->suffix, 0);
7455       PointerToDialog (sbfp->phonefaxemail, NULL);
7456       PointerToDialog (sbfp->authors, NULL);
7457       SafeSetTitle (sbfp->consortium, "");
7458       PointerToDialog (sbfp->affil, NULL);
7459       SafeSetValue (sbfp->hup, 1);
7460       SafeHide (sbfp->dateGrp);
7461       SetValue (sbfp->tbs, 0);
7462     }
7463   }
7464 }
7465 
TitleToSubmitBlockForm(ForM f,Pointer data)7466 static void TitleToSubmitBlockForm(ForM f, Pointer data)
7467 
7468 {
7469   CharPtr         man_title;
7470   SubmitFormPtr   sbfp;
7471 
7472   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7473   man_title = (CharPtr) data;
7474   if (sbfp != NULL)
7475   {
7476     if (man_title == NULL) {
7477       SetTitle (sbfp->title, "");
7478     } else {
7479       SetTitle (sbfp->title, man_title);
7480     }
7481   }
7482 }
7483 
7484 
DescriptorsToSubmitBlockForm(ForM f,Pointer data)7485 static void DescriptorsToSubmitBlockForm(ForM f, Pointer data)
7486 
7487 {
7488   SubmitFormPtr   sbfp;
7489   SeqDescrPtr     sdp_list;
7490 
7491   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7492   sdp_list = (SeqDescrPtr) data;
7493   if (sbfp != NULL)
7494   {
7495     sbfp->descriptors = SeqDescrFree (sbfp->descriptors);
7496     if (sdp_list != NULL)
7497     {
7498       sbfp->descriptors = AsnIoMemCopy (sdp_list, (AsnReadFunc) SeqDescrAsnRead, (AsnWriteFunc) SeqDescrAsnWrite);
7499     }
7500   }
7501 }
7502 
7503 
AddNonPunctFieldToErrList(TexT t,CharPtr name,ValNodePtr PNTR err_list)7504 static void AddNonPunctFieldToErrList (TexT t, CharPtr name, ValNodePtr PNTR err_list)
7505 {
7506   CharPtr val, cp;
7507 
7508   if (t == NULL || err_list == NULL) {
7509     return;
7510   }
7511   if (TextHasNoText (t)) {
7512     *err_list = AddStringToValNodeChain (*err_list, name, TESTRESULT_MISSING);
7513   } else {
7514     val = SaveStringFromText (t);
7515     for (cp = val; *cp != 0 && ispunct (*cp); cp++) {
7516     }
7517     if (*cp == 0) {
7518       *err_list = AddStringToValNodeChain (*err_list, name, TESTRESULT_INVALID);
7519     }
7520     val = MemFree (val);
7521   }
7522 }
7523 
7524 
AddNonPunctStringToErrList(CharPtr val,CharPtr name,ValNodePtr PNTR err_list)7525 static void AddNonPunctStringToErrList (CharPtr val, CharPtr name, ValNodePtr PNTR err_list)
7526 {
7527   CharPtr cp;
7528   Boolean any_punct = FALSE;
7529 
7530   if (err_list == NULL) {
7531     return;
7532   }
7533   if (StringHasNoText (val)) {
7534     *err_list = AddStringToValNodeChain (*err_list, name, TESTRESULT_MISSING);
7535   } else {
7536     for (cp = val; *cp != 0 && (unsigned)(*cp + 1) <= 256 && ispunct (*cp); cp++) {
7537       any_punct = TRUE;
7538     }
7539     if (*cp == 0 && any_punct) {
7540       *err_list = AddStringToValNodeChain (*err_list, name, TESTRESULT_INVALID);
7541     }
7542   }
7543 }
7544 
7545 
AddAuthListErrors(AuthListPtr auth,ValNodePtr PNTR err_list)7546 static void AddAuthListErrors (AuthListPtr auth, ValNodePtr PNTR err_list)
7547 {
7548   ValNodePtr name;
7549 	AuthorPtr  ap;
7550 	NameStdPtr  nsp;
7551 	PersonIdPtr  pid;
7552 
7553   if (auth == NULL || err_list == NULL) {
7554     return;
7555   }
7556   if (auth->choice == 1) {
7557     for (name = auth->names; name != NULL; name = name->next) {
7558 		  ap = name->data.ptrvalue;
7559 		  if (ap != NULL) {
7560 			  pid = ap->name;
7561 			  if (pid != NULL) {
7562 				  if (pid->choice == 2) {
7563 					  nsp = pid->data;
7564 					  if (nsp != NULL) {
7565               AddNonPunctStringToErrList (nsp->names [0], "author last name", err_list);
7566               AddNonPunctStringToErrList (nsp->names [1], "author first name", err_list);
7567 					  }
7568 				  }
7569 			  }
7570 		  }
7571     }
7572 	}
7573 }
7574 
7575 
TestSubmitForm(ForM f)7576 static ValNodePtr TestSubmitForm (ForM f)
7577 
7578 {
7579   AffilPtr       affil;
7580   AuthListPtr    authors;
7581   DatePtr        dp;
7582   ValNodePtr     head;
7583   SubmitFormPtr  sbfp;
7584 
7585   head = NULL;
7586 
7587   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7588   if (sbfp == NULL) {
7589     return NULL;
7590   }
7591 
7592   AddNonPunctFieldToErrList (sbfp->firstname, "first_name", &head);
7593   AddNonPunctFieldToErrList (sbfp->firstname, "last name", &head);
7594 
7595   affil = DialogToPointer (sbfp->phonefaxemail);
7596   if (affil != NULL) {
7597     if (StringHasNoText (affil->phone)) {
7598       head = AddStringToValNodeChain (head, "telephone number", TESTRESULT_WARN);
7599     }
7600     if (StringHasNoText (affil->fax)) {
7601       head = AddStringToValNodeChain (head, "fax number", TESTRESULT_WARN);
7602     }
7603     if (StringHasNoText (affil->email)) {
7604       head = AddStringToValNodeChain (head, "e-mail address", TESTRESULT_WARN);
7605     }
7606   } else {
7607     head = AddStringToValNodeChain (head, "telephone number", TESTRESULT_WARN);
7608     head = AddStringToValNodeChain (head, "fax number", TESTRESULT_WARN);
7609     head = AddStringToValNodeChain (head, "e-mail address", TESTRESULT_WARN);
7610   }
7611   affil = AffilFree (affil);
7612 
7613   if (GetValue (sbfp->hup) == 2) {
7614     dp = DialogToPointer (sbfp->reldate);
7615     if (dp == NULL) {
7616       head = AddStringToValNodeChain (head, "release date", TESTRESULT_MISSING);
7617     }
7618     dp = DateFree (dp);
7619   }
7620   if (TextHasNoText (sbfp->title)) {
7621     head = AddStringToValNodeChain (head, "manuscript title", TESTRESULT_MISSING);
7622   }
7623 
7624   ValNodeLink (&head, TestDialog (sbfp->authors));
7625   authors = DialogToPointer (sbfp->authors);
7626   if (GetStatus (sbfp->use_consortium)) {
7627     authors = AddConsortiumToAuthList (authors, sbfp->consortium);
7628   }
7629   if (authors == NULL) {
7630     head = AddStringToValNodeChain (head, "author names", TESTRESULT_MISSING);
7631   } else {
7632     AddAuthListErrors (authors, &head);
7633   }
7634   authors = AuthListFree (authors);
7635   affil = DialogToPointer (sbfp->affil);
7636   if (affil == NULL) {
7637     head = AddStringToValNodeChain (head, "affiliation", TESTRESULT_MISSING);
7638   } else {
7639     AddNonPunctStringToErrList (affil->affil, "institution", &head);
7640   }
7641   affil = AffilFree (affil);
7642 
7643   return head;
7644 }
7645 
7646 /*
7647 static Boolean ReadSubmitBlock (ForM f, CharPtr filename)
7648 
7649 {
7650   AsnIoPtr        aip;
7651   Char            path [PATH_MAX];
7652   SubmitFormPtr   sbfp;
7653   SubmitBlockPtr  sbp;
7654 
7655   path [0] = '\0';
7656   StringNCpy_0 (path, filename, sizeof (path));
7657   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7658   if (sbfp != NULL) {
7659     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
7660       aip = AsnIoOpen (path, "r");
7661       if (aip != NULL) {
7662         sbp = SubmitBlockAsnRead (aip, NULL);
7663         AsnIoClose (aip);
7664         if (sbp != NULL) {
7665           SubmitBlockPtrToSubmitForm (f, (Pointer) sbp);
7666           sbp = SubmitBlockFree (sbp);
7667           Update ();
7668           return TRUE;
7669         }
7670       }
7671     }
7672   }
7673   return FALSE;
7674 }
7675 */
7676 
7677 
ReadNextASNObject(FILE * fp,Uint2Ptr datatypeptr,Uint2Ptr entityIDptr)7678 static Pointer ReadNextASNObject (FILE *fp, Uint2Ptr datatypeptr, Uint2Ptr entityIDptr)
7679 {
7680   AsnIoPtr       aip;
7681   Pointer        dataptr = NULL;
7682   Int4           pos;
7683   ObjMgrPtr      omp;
7684   ObjMgrTypePtr  omtp = NULL;
7685   FileCache      fc;
7686   CharPtr        str, tag, pEnd;
7687   Char           line [4096];
7688 
7689   if (fp == NULL) {
7690       return NULL;
7691   }
7692 
7693   FileCacheSetup (&fc, fp);
7694 
7695   pos = FileCacheTell (&fc);
7696 
7697   str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
7698   while (str != NULL && StringHasNoText (str)) {
7699     str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
7700   }
7701 
7702   if (str == NULL) return NULL; /* already at end of file */
7703 
7704   if (StringStr (str, "::=") == NULL) return NULL;
7705 
7706   /* first skip past empty space at start of line */
7707   tag = str;
7708   while (*tag != '\0' && IS_WHITESP (*tag)) {
7709     tag++;
7710   }
7711   pEnd = tag;
7712   while (*pEnd != '\0' && !IS_WHITESP (*pEnd)) {
7713     pEnd++;
7714   }
7715   *pEnd = 0;
7716 
7717   omp = ObjMgrReadLock ();
7718   omtp = ObjMgrTypeFind (omp, 0, tag, NULL);
7719   ObjMgrUnlock ();
7720 
7721   if (omtp == NULL) {
7722       return NULL;
7723   }
7724   FileCacheFree (&fc, FALSE);
7725   fseek (fp, pos, SEEK_SET);
7726 
7727   aip = AsnIoNew (ASNIO_TEXT_IN, fp, NULL, NULL, NULL);
7728   aip->scan_for_start = TRUE;
7729   dataptr = (*(omtp->asnread)) (aip, NULL);
7730   pos = AsnIoTell (aip);
7731   AsnIoFree (aip, FALSE);
7732   fseek (fp, pos, SEEK_SET);
7733 
7734   if (dataptr == NULL) {
7735     ErrPostEx (SEV_ERROR, 0, 0, "Couldn't read type [%s]", omtp->asnname);
7736   } else {
7737     if (datatypeptr != NULL) {
7738       *datatypeptr = omtp->datatype;
7739     }
7740     if (entityIDptr != NULL) {
7741       *entityIDptr = ObjMgrRegister (omtp->datatype, dataptr);
7742     }
7743   }
7744   return dataptr;
7745 }
7746 
7747 
ReadSubmitBlock(ForM f,CharPtr filename)7748 static Boolean ReadSubmitBlock (ForM f, CharPtr filename)
7749 
7750 {
7751   Pointer         dataptr;
7752   Uint2           datatype;
7753   Uint2           entityID;
7754   SubmitFormPtr   sbfp;
7755   SubmitBlockPtr  sbp;
7756   SeqSubmitPtr    ssp;
7757   Char            path [PATH_MAX];
7758   CharPtr         man_title;
7759   CitGenPtr       cgp;
7760   FILE           * fp;
7761   PubdescPtr      pdp;
7762   ValNodePtr      sdp, vnp;
7763   Boolean         is_title_pub = FALSE;
7764   SeqDescPtr      sdp_list = NULL;
7765 
7766   path [0] = '\0';
7767   StringNCpy_0 (path, filename, sizeof (path));
7768   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7769   if (sbfp == NULL) {
7770     return FALSE;
7771   }
7772   if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
7773     fp = FileOpen(path, "r");
7774     dataptr = ReadNextASNObject (fp, &datatype, &entityID);
7775     sbp = NULL;
7776     man_title = NULL;
7777     /* clear out previous descriptors */
7778     sbfp->descriptors = SeqDescrFree (sbfp->descriptors);
7779     while (dataptr != NULL) {
7780       if (entityID > 0) {
7781         switch (datatype) {
7782           case OBJ_SUBMIT_BLOCK :
7783             if (sbp == NULL) {
7784               sbp = (SubmitBlockPtr) AsnIoMemCopy (dataptr,
7785                                                    (AsnReadFunc) SubmitBlockAsnRead,
7786                                                    (AsnWriteFunc) SubmitBlockAsnWrite);
7787             }
7788             break;
7789           case OBJ_SEQSUB :
7790             if (sbp == NULL) {
7791               ssp = (SeqSubmitPtr) dataptr;
7792               if (ssp != NULL) {
7793                 sbp = (SubmitBlockPtr) AsnIoMemCopy (ssp->sub,
7794                                                      (AsnReadFunc) SubmitBlockAsnRead,
7795                                                      (AsnWriteFunc) SubmitBlockAsnWrite);
7796               }
7797             }
7798             break;
7799           case OBJ_SEQDESC:
7800             sdp = (ValNodePtr) dataptr;
7801             is_title_pub = FALSE;
7802             if (sdp->choice == Seq_descr_pub && sdp->data.ptrvalue != NULL && man_title == NULL) {
7803               pdp = (PubdescPtr) sdp->data.ptrvalue;
7804               vnp = pdp->pub;
7805               while (vnp != NULL && vnp->choice != PUB_Gen) {
7806                 vnp = vnp->next;
7807               }
7808               if (vnp != NULL && vnp->data.ptrvalue != NULL) {
7809                 cgp = (CitGenPtr) vnp->data.ptrvalue;
7810                 if (StringICmp (cgp->cit, "unpublished") == 0
7811                     && !StringHasNoText (cgp->title)) {
7812                   man_title = StringSave (cgp->title);
7813                   is_title_pub = TRUE;
7814                 }
7815               }
7816             }
7817             if (!is_title_pub) {
7818               ValNodeLink (&sdp_list, (SeqDescPtr) AsnIoMemCopy (sdp, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite));
7819             }
7820             break;
7821           default :
7822             break;
7823         }
7824       }
7825       ObjMgrDelete (datatype, dataptr);
7826       dataptr = ReadNextASNObject (fp, &datatype, &entityID);
7827     }
7828     FileClose (fp);
7829     if (sbp != NULL || man_title != NULL || sdp_list != NULL) {
7830       if (sbp != NULL) {
7831         SubmitBlockPtrToSubmitForm (f, sbp);
7832         sbp = SubmitBlockFree (sbp);
7833       }
7834       if (man_title != NULL) {
7835         TitleToSubmitBlockForm (f, man_title);
7836         man_title = MemFree (man_title);
7837       }
7838       if (sdp_list != NULL) {
7839         DescriptorsToSubmitBlockForm (f, sdp_list);
7840         sdp_list = SeqDescrFree (sdp_list);
7841       }
7842       Update ();
7843       return TRUE;
7844     }
7845   }
7846   return FALSE;
7847 }
7848 
MakeUnpubPub(CharPtr title,AuthListPtr alp,AffilPtr affil)7849 static SeqDescrPtr MakeUnpubPub (CharPtr title, AuthListPtr alp, AffilPtr affil)
7850 
7851 {
7852   CitGenPtr    cgp;
7853   PubdescPtr   pdp;
7854   ValNodePtr   pep;
7855   SeqDescrPtr  vnp;
7856 
7857   if (StringHasNoText (title) || alp == NULL) return NULL;
7858   pdp = PubdescNew ();
7859   if (pdp == NULL) return NULL;
7860   vnp = SeqDescrNew (NULL);
7861   if (vnp == NULL) return NULL;
7862   vnp->choice = Seq_descr_pub;
7863   vnp->data.ptrvalue = (Pointer) pdp;
7864   pdp->reftype = 0;
7865   pep = ValNodeNew (NULL);
7866   pdp->pub = pep;
7867   if (pep != NULL) {
7868     cgp = CitGenNew ();
7869     if (cgp != NULL) {
7870       pep->choice = PUB_Gen;
7871       pep->data.ptrvalue = cgp;
7872       cgp->cit = StringSave ("unpublished");
7873       cgp->authors = alp;
7874       if (alp != NULL) {
7875         alp->affil = affil;
7876         if (affil != NULL) {
7877           affil->phone = MemFree (affil->phone);
7878           affil->fax = MemFree (affil->fax);
7879           affil->email = MemFree (affil->email);
7880         }
7881       }
7882       cgp->title = StringSave (title);
7883     }
7884   }
7885   return vnp;
7886 }
7887 
7888 extern SubmitBlockPtr ConvertSequinBlockToSubmitBlock (SequinBlockPtr sqp);
7889 
7890 NLM_EXTERN void AsnPrintNewLine PROTO((AsnIoPtr aip));
7891 
WriteSubmitBlock(ForM f,CharPtr filename)7892 static Boolean WriteSubmitBlock (ForM f, CharPtr filename)
7893 
7894 {
7895   AffilPtr        affil;
7896   AsnIoPtr        aip;
7897   AuthListPtr     alp;
7898   Char            path [PATH_MAX];
7899   SubmitFormPtr   sbfp;
7900   SubmitBlockPtr  sbp;
7901   SeqDescrPtr     sdp;
7902   SequinBlockPtr  sqp;
7903   CharPtr         title;
7904 #ifdef WIN_MAC
7905   FILE            *fp;
7906 #endif
7907 
7908   path [0] = '\0';
7909   StringNCpy_0 (path, filename, sizeof (path));
7910   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7911   if (sbfp != NULL) {
7912     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
7913 #ifdef WIN_MAC
7914       fp = FileOpen (path, "r");
7915       if (fp != NULL) {
7916         FileClose (fp);
7917       } else {
7918         FileCreate (path, "TEXT", "ttxt");
7919       }
7920 #endif
7921       sqp = (SequinBlockPtr) SubmitFormToSequinBlockPtr (f);
7922       if (sqp != NULL) {
7923         title = StringSaveNoNull (sqp->citsubtitle);
7924         alp = AsnIoMemCopy ((Pointer) sqp->citsubauthors,
7925                             (AsnReadFunc) AuthListAsnRead,
7926                             (AsnWriteFunc) AuthListAsnWrite);
7927         affil = AsnIoMemCopy ((Pointer) sqp->citsubaffil,
7928                               (AsnReadFunc) AffilAsnRead,
7929                               (AsnWriteFunc) AffilAsnWrite);
7930         sbp = ConvertSequinBlockToSubmitBlock (sqp);
7931         if (sbp != NULL) {
7932           aip = AsnIoOpen (path, "w");
7933           if (aip != NULL) {
7934             sbp->tool = MemFree (sbp->tool);
7935             SubmitBlockAsnWrite (sbp, aip, NULL);
7936             AsnPrintNewLine (aip);
7937             sdp = MakeUnpubPub (title, alp, affil);
7938             if (sdp != NULL) {
7939               AsnIoReset (aip);
7940               SeqDescAsnWrite (sdp, aip, NULL);
7941               AsnPrintNewLine (aip);
7942               SeqDescFree (sdp);
7943             }
7944             AsnIoClose (aip);
7945             sbp = SubmitBlockFree (sbp);
7946             return TRUE;
7947           }
7948         }
7949       }
7950     }
7951   }
7952   return FALSE;
7953 }
7954 
ReadContactPage(ForM f,CharPtr filename)7955 static Boolean ReadContactPage (ForM f, CharPtr filename)
7956 
7957 {
7958   AsnIoPtr        aip;
7959   AuthorPtr       ap;
7960   ContactInfoPtr  cip;
7961   NameStdPtr      nsp;
7962   Char            path [PATH_MAX];
7963   PersonIdPtr     pid;
7964   SubmitFormPtr   sbfp;
7965   CharPtr         str;
7966   CharPtr         txt;
7967 
7968   path [0] = '\0';
7969   StringNCpy_0 (path, filename, sizeof (path));
7970   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7971   if (sbfp != NULL) {
7972     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
7973       aip = AsnIoOpen (path, "r");
7974       if (aip != NULL) {
7975         cip = ContactInfoAsnRead (aip, NULL);
7976         AsnIoClose (aip);
7977         if (cip != NULL) {
7978           ap = cip->contact;
7979           if (ap != NULL) {
7980             pid = ap->name;
7981             if (pid != NULL && pid->choice == 2) {
7982               nsp = pid->data;
7983               if (nsp != NULL) {
7984                 str = NameStdPtrToAuthorSpreadsheetString (nsp);
7985                 if (str != NULL) {
7986                   txt = ExtractTagListColumn (str, 0);
7987                   SafeSetTitle (sbfp->firstname, txt);
7988                   MemFree (txt);
7989                   txt = ExtractTagListColumn (str, 1);
7990                   SafeSetTitle (sbfp->middleinit, txt);
7991                   MemFree (txt);
7992                   txt = ExtractTagListColumn (str, 2);
7993                   SafeSetTitle (sbfp->lastname, txt);
7994                   MemFree (txt);
7995                   txt = ExtractTagListColumn (str, 3);
7996                   if (! StringHasNoText (txt)) {
7997                     SetEnumPopupByName (sbfp->suffix, name_suffix_alist, txt);
7998                   }
7999                   MemFree (txt);
8000                   MemFree (str);
8001                 }
8002               }
8003             }
8004             PointerToDialog (sbfp->phonefaxemail, (Pointer) ap->affil);
8005           }
8006           cip = ContactInfoFree (cip);
8007           Update ();
8008           return TRUE;
8009         }
8010       }
8011     }
8012   }
8013   return FALSE;
8014 }
8015 
WriteContactPage(ForM f,CharPtr filename)8016 static Boolean WriteContactPage (ForM f, CharPtr filename)
8017 
8018 {
8019   AffilPtr        affil;
8020   AsnIoPtr        aip;
8021   AuthorPtr       ap;
8022   ContactInfoPtr  cip;
8023   NameStdPtr      nsp;
8024   Char            path [PATH_MAX];
8025   PersonIdPtr     pid;
8026   SubmitFormPtr   sbfp;
8027   Char            sfx [32];
8028   Char            str [128];
8029   Uint2           suffixVal;
8030   CharPtr         txt;
8031 #ifdef WIN_MAC
8032   FILE            *fp;
8033 #endif
8034 
8035   path [0] = '\0';
8036   StringNCpy_0 (path, filename, sizeof (path));
8037   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8038   if (sbfp != NULL) {
8039     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
8040 #ifdef WIN_MAC
8041       fp = FileOpen (path, "r");
8042       if (fp != NULL) {
8043         FileClose (fp);
8044       } else {
8045         FileCreate (path, "TEXT", "ttxt");
8046       }
8047 #endif
8048       aip = AsnIoOpen (path, "w");
8049       if (aip != NULL) {
8050         cip = ContactInfoNew ();
8051         if (cip != NULL) {
8052           ap = AuthorNew ();
8053           if (ap != NULL) {
8054             pid = PersonIdNew ();
8055             ap->name = pid;
8056             if (pid != NULL) {
8057               pid->choice = 2;
8058               str [0] = '\0';
8059               txt = SaveStringFromText (sbfp->firstname);
8060               StringCat (str, txt);
8061               StringCat (str, "\t");
8062               MemFree (txt);
8063               txt = SaveStringFromText (sbfp->middleinit);
8064               StringCat (str, txt);
8065               StringCat (str, "\t");
8066               MemFree (txt);
8067               txt = SaveStringFromText (sbfp->lastname);
8068               StringCat (str, txt);
8069               StringCat (str, "\t");
8070               MemFree (txt);
8071               suffixVal = GetValue (sbfp->suffix);
8072               sprintf (sfx, "%d", (int) (suffixVal - 1));
8073               StringCat (str, sfx);
8074               StringCat (str, "\n");
8075               txt = StringSave (str);
8076               nsp = AuthorSpreadsheetStringToNameStdPtr (txt);
8077               MemFree (txt);
8078               pid->data = nsp;
8079               if (nsp != NULL) {
8080                 if (StringHasNoText (nsp->names [0])) {
8081                   ap = AuthorFree (ap);
8082                 }
8083               }
8084             }
8085             affil = (AffilPtr) DialogToPointer (sbfp->phonefaxemail);
8086             if (affil != NULL) {
8087               if (affil->choice == 2) {
8088                 affil->affil = MemFree (affil->affil);
8089                 affil->div = MemFree (affil->div);
8090                 affil->city = MemFree (affil->city);
8091                 affil->sub = MemFree (affil->sub);
8092                 affil->country = MemFree (affil->country);
8093                 affil->street = MemFree (affil->street);
8094                 affil->postal_code = MemFree (affil->postal_code);
8095                 if (affil->phone == NULL && affil->fax == NULL &&
8096                     affil->email == NULL) {
8097                   affil = AffilFree (affil);
8098                 }
8099               } else {
8100                 affil = AffilFree (affil);
8101               }
8102             }
8103             ap->affil = affil;
8104           }
8105           cip->contact = ap;
8106           ContactInfoAsnWrite (cip, aip, NULL);
8107           AsnIoClose (aip);
8108           cip = ContactInfoFree (cip);
8109           return TRUE;
8110         }
8111       }
8112     }
8113   }
8114   return FALSE;
8115 }
8116 
ReadAuthListPage(ForM f,CharPtr filename)8117 static Boolean ReadAuthListPage (ForM f, CharPtr filename)
8118 
8119 {
8120   AsnIoPtr       aip;
8121   AuthListPtr    alp;
8122   Char           path [PATH_MAX];
8123   SubmitFormPtr  sbfp;
8124 
8125   path [0] = '\0';
8126   StringNCpy_0 (path, filename, sizeof (path));
8127   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8128   if (sbfp != NULL) {
8129     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
8130       aip = AsnIoOpen (path, "r");
8131       if (aip != NULL) {
8132         alp = AuthListAsnRead (aip, NULL);
8133         AsnIoClose (aip);
8134         if (alp != NULL) {
8135           PointerToDialog (sbfp->authors, alp);
8136           if (AuthListToConsortium (alp, sbfp->consortium)) {
8137             SetStatus (sbfp->use_consortium, TRUE);
8138             Enable (sbfp->consortium);
8139           } else {
8140             SetStatus (sbfp->use_consortium, FALSE);
8141             Disable (sbfp->consortium);
8142           }
8143           alp = AuthListFree (alp);
8144           Update ();
8145           return TRUE;
8146         }
8147       }
8148     }
8149   }
8150   return FALSE;
8151 }
8152 
WriteAuthListPage(ForM f,CharPtr filename)8153 static Boolean WriteAuthListPage (ForM f, CharPtr filename)
8154 
8155 {
8156   AsnIoPtr       aip;
8157   AuthListPtr    alp;
8158   Char           path [PATH_MAX];
8159   SubmitFormPtr  sbfp;
8160 #ifdef WIN_MAC
8161   FILE           *fp;
8162 #endif
8163 
8164   path [0] = '\0';
8165   StringNCpy_0 (path, filename, sizeof (path));
8166   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8167   if (sbfp != NULL) {
8168     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
8169 #ifdef WIN_MAC
8170       fp = FileOpen (path, "r");
8171       if (fp != NULL) {
8172         FileClose (fp);
8173       } else {
8174         FileCreate (path, "TEXT", "ttxt");
8175       }
8176 #endif
8177       aip = AsnIoOpen (path, "w");
8178       if (aip != NULL) {
8179         alp = DialogToPointer (sbfp->authors);
8180         if (GetStatus (sbfp->use_consortium)) {
8181           alp = AddConsortiumToAuthList (alp, sbfp->consortium);
8182         }
8183         AuthListAsnWrite (alp, aip, NULL);
8184         AsnIoClose (aip);
8185         alp = AuthListFree (alp);
8186         return TRUE;
8187       }
8188     }
8189   }
8190   return FALSE;
8191 }
8192 
ReadAffilPage(ForM f,CharPtr filename)8193 static Boolean ReadAffilPage (ForM f, CharPtr filename)
8194 
8195 {
8196   AffilPtr       affil;
8197   AsnIoPtr       aip;
8198   Char           path [PATH_MAX];
8199   SubmitFormPtr  sbfp;
8200 
8201   path [0] = '\0';
8202   StringNCpy_0 (path, filename, sizeof (path));
8203   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8204   if (sbfp != NULL) {
8205     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
8206       aip = AsnIoOpen (path, "r");
8207       if (aip != NULL) {
8208         affil = AffilAsnRead (aip, NULL);
8209         AsnIoClose (aip);
8210         if (affil != NULL) {
8211           affil->phone = MemFree (affil->phone);
8212           affil->fax = MemFree (affil->fax);
8213           affil->email = MemFree (affil->email);
8214           PointerToDialog (sbfp->affil, affil);
8215           affil = AffilFree (affil);
8216           Update ();
8217           return TRUE;
8218         }
8219       }
8220     }
8221   }
8222   return FALSE;
8223 }
8224 
WriteAffilPage(ForM f,CharPtr filename)8225 static Boolean WriteAffilPage (ForM f, CharPtr filename)
8226 
8227 {
8228   AffilPtr       affil;
8229   AsnIoPtr       aip;
8230   Char           path [PATH_MAX];
8231   SubmitFormPtr  sbfp;
8232 #ifdef WIN_MAC
8233   FILE           *fp;
8234 #endif
8235 
8236   path [0] = '\0';
8237   StringNCpy_0 (path, filename, sizeof (path));
8238   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8239   if (sbfp != NULL) {
8240     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
8241 #ifdef WIN_MAC
8242       fp = FileOpen (path, "r");
8243       if (fp != NULL) {
8244         FileClose (fp);
8245       } else {
8246         FileCreate (path, "TEXT", "ttxt");
8247       }
8248 #endif
8249       aip = AsnIoOpen (path, "w");
8250       if (aip != NULL) {
8251         affil = DialogToPointer (sbfp->affil);
8252         affil->phone = MemFree (affil->phone);
8253         affil->fax = MemFree (affil->fax);
8254         affil->email = MemFree (affil->email);
8255         AffilAsnWrite (affil, aip, NULL);
8256         AsnIoClose (aip);
8257         affil = AffilFree (affil);
8258         return TRUE;
8259       }
8260     }
8261   }
8262   return FALSE;
8263 }
8264 
ImportSubmitForm(ForM f,CharPtr filename)8265 static Boolean ImportSubmitForm (ForM f, CharPtr filename)
8266 
8267 {
8268   SubmitFormPtr  sbfp;
8269 
8270   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8271   if (sbfp != NULL) {
8272     switch (sbfp->currentPage) {
8273       case SUBMISSION_PAGE :
8274         return ReadSubmitBlock (f, filename);
8275       case CONTACT_PAGE :
8276         return ReadContactPage (f, filename);
8277       case AUTHOR_PAGE :
8278         return ReadAuthListPage (f, filename);
8279       case AFFILIATION_PAGE :
8280         return ReadAffilPage (f, filename);
8281       default :
8282         break;
8283     }
8284   }
8285   return FALSE;
8286 }
8287 
ExportSubmitForm(ForM f,CharPtr filename)8288 static Boolean ExportSubmitForm (ForM f, CharPtr filename)
8289 
8290 {
8291   SubmitFormPtr  sbfp;
8292 
8293   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8294   if (sbfp != NULL) {
8295     switch (sbfp->currentPage) {
8296       case SUBMISSION_PAGE :
8297         return WriteSubmitBlock (f, filename);
8298       case CONTACT_PAGE :
8299         return WriteContactPage (f, filename);
8300       case AUTHOR_PAGE :
8301         return WriteAuthListPage (f, filename);
8302       case AFFILIATION_PAGE :
8303         return WriteAffilPage (f, filename);
8304       default :
8305         break;
8306     }
8307   }
8308   return FALSE;
8309 }
8310 
CopyContactToAuthors(SubmitFormPtr sbfp)8311 static void CopyContactToAuthors (SubmitFormPtr sbfp)
8312 
8313 {
8314   AuthListPtr  alp;
8315   AuthorPtr    ap;
8316   ValNodePtr   names;
8317   NameStdPtr   nsp;
8318   PersonIdPtr  pid;
8319   CharPtr      txt;
8320 
8321   if (sbfp == NULL) return;
8322   ap = NULL;
8323   alp = AuthListNew ();
8324   if (alp != NULL) {
8325     alp->choice = 1;
8326     names = ValNodeNew (NULL);
8327     alp->choice = 1;
8328     alp->names = names;
8329     if (names != NULL) {
8330       ap = AuthorNew ();
8331       if (ap != NULL) {
8332         pid = PersonIdNew ();
8333         ap->name = pid;
8334         if (pid != NULL) {
8335           pid->choice = 2;
8336           FixSubmitFormSpecialCharacters (sbfp);
8337           txt = ContactNameFromSubmitForm (sbfp);
8338           nsp = AuthorSpreadsheetStringToNameStdPtr (txt);
8339           MemFree (txt);
8340           pid->data = nsp;
8341           if (nsp != NULL) {
8342             if (StringHasNoText (nsp->names [0])) {
8343               ap = AuthorFree (ap);
8344             }
8345           }
8346         }
8347       }
8348       names->choice = 1;
8349       names->data.ptrvalue = ap;
8350     }
8351     if (ap == NULL) {
8352       alp = AuthListFree (alp);
8353     }
8354     if (alp != NULL) {
8355       PointerToDialog (sbfp->authors, (Pointer) alp);
8356       if (AuthListToConsortium (alp, sbfp->consortium)) {
8357         SetStatus (sbfp->use_consortium, TRUE);
8358         Enable (sbfp->consortium);
8359       } else {
8360         SetStatus (sbfp->use_consortium, FALSE);
8361         Disable (sbfp->consortium);
8362       }
8363     }
8364   }
8365   alp = AuthListFree (alp);
8366 }
8367 
SetSubmitterImportExportItems(SubmitFormPtr sbfp)8368 static void SetSubmitterImportExportItems (SubmitFormPtr sbfp)
8369 
8370 {
8371   IteM  exportItm;
8372   IteM  importItm;
8373 
8374   if (sbfp != NULL) {
8375     importItm = FindFormMenuItem ((BaseFormPtr) sbfp, VIB_MSG_IMPORT);
8376     exportItm = FindFormMenuItem ((BaseFormPtr) sbfp, VIB_MSG_EXPORT);
8377     switch (sbfp->currentPage) {
8378       case SUBMISSION_PAGE :
8379         SafeSetTitle (importItm, "Import Submitter Info...");
8380         SafeSetTitle (exportItm, "Export Submitter Info...");
8381         SafeEnable (importItm);
8382         SafeEnable (exportItm);
8383         break;
8384       case CONTACT_PAGE :
8385         SafeSetTitle (importItm, "Import Contact...");
8386         SafeSetTitle (exportItm, "Export Contact...");
8387         SafeEnable (importItm);
8388         SafeEnable (exportItm);
8389         break;
8390       case AUTHOR_PAGE :
8391         SafeSetTitle (importItm, "Import Authors...");
8392         SafeSetTitle (exportItm, "Export Authors...");
8393         SafeEnable (importItm);
8394         SafeEnable (exportItm);
8395         break;
8396       case AFFILIATION_PAGE :
8397         SafeSetTitle (importItm, "Import Affiliation...");
8398         SafeSetTitle (exportItm, "Export Affiliation...");
8399         SafeEnable (importItm);
8400         SafeEnable (exportItm);
8401         break;
8402       default :
8403         break;
8404     }
8405   }
8406 }
8407 
EnterSubmitPage(SubmitFormPtr sbfp,Int2 page)8408 static void EnterSubmitPage (SubmitFormPtr sbfp, Int2 page)
8409 
8410 {
8411   AuthListPtr  alp;
8412 
8413   if (sbfp != NULL) {
8414     switch (page) {
8415       case SUBMISSION_PAGE :
8416         Select (sbfp->title);
8417         SafeSetTitle (sbfp->prevBtn, "<< Prev Form");
8418         SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8419         break;
8420       case CONTACT_PAGE :
8421         Select (sbfp->firstname);
8422         sbfp->visitedContact = TRUE;
8423         SafeSetTitle (sbfp->prevBtn, "<< Prev Page");
8424         SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8425         break;
8426       case AUTHOR_PAGE :
8427         alp = (AuthListPtr) DialogToPointer (sbfp->authors);
8428         if (GetStatus (sbfp->use_consortium)) {
8429           alp = AddConsortiumToAuthList (alp, sbfp->consortium);
8430         }
8431         if (sbfp->visitedContact && alp == NULL) {
8432           CopyContactToAuthors (sbfp);
8433         }
8434         AuthListFree (alp);
8435         /*
8436         if (sbfp->visitedContact && (! sbfp->visitedAuthor)) {
8437           CopyContactToAuthors (sbfp);
8438         }
8439         */
8440         SendMessageToDialog (sbfp->authors, VIB_MSG_ENTER);
8441         sbfp->visitedAuthor = TRUE;
8442         SafeSetTitle (sbfp->prevBtn, "<< Prev Page");
8443         SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8444         break;
8445       case AFFILIATION_PAGE :
8446         SendMessageToDialog (sbfp->affil, VIB_MSG_ENTER);
8447         SafeSetTitle (sbfp->prevBtn, "<< Prev Page");
8448         SafeSetTitle (sbfp->nextBtn, "Next Form >>");
8449         break;
8450       default :
8451         break;
8452     }
8453   }
8454 }
8455 
ChangeSubmitFormPage(VoidPtr data,Int2 newval,Int2 oldval)8456 static void ChangeSubmitFormPage (VoidPtr data, Int2 newval, Int2 oldval)
8457 
8458 {
8459   SubmitFormPtr  sbfp;
8460 
8461   sbfp = (SubmitFormPtr) data;
8462   if (sbfp != NULL) {
8463     sbfp->currentPage = newval;
8464     SafeHide (sbfp->pages [oldval]);
8465     Update ();
8466 #ifdef WIN_MAC
8467     EnterSubmitPage (sbfp, newval);
8468 #endif
8469     SetSubmitterImportExportItems (sbfp);
8470     SafeShow (sbfp->pages [newval]);
8471 #ifndef WIN_MAC
8472     EnterSubmitPage (sbfp, newval);
8473 #endif
8474     Update ();
8475     switch (newval) {
8476       case SUBMISSION_PAGE :
8477         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Submission Page");
8478         break;
8479       case CONTACT_PAGE :
8480         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Contact Page");
8481         break;
8482       case AUTHOR_PAGE :
8483         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Authors Page");
8484         break;
8485       case AFFILIATION_PAGE :
8486         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Affiliation Page");
8487         break;
8488       default :
8489         break;
8490     }
8491   }
8492 }
8493 
NextSubmitFormBtn(ButtoN b)8494 static void NextSubmitFormBtn (ButtoN b)
8495 
8496 {
8497   SubmitFormPtr  sbfp;
8498   CharPtr        txt;
8499   Boolean        ok = TRUE;
8500 
8501   sbfp = (SubmitFormPtr) GetObjectExtra (b);
8502   if (sbfp != NULL) {
8503     if (sbfp->currentPage == 0)
8504     {
8505       txt = SaveStringFromText (sbfp->title);
8506       if (StringHasNoText (txt))
8507       {
8508       	Message (MSG_ERROR, "You must supply a tentative title for your manuscript.");
8509       	MemFree (txt);
8510       	return;
8511       }
8512       MemFree (txt);
8513     }
8514     else if (sbfp->currentPage == 1)
8515     {
8516       txt = SaveStringFromText (sbfp->firstname);
8517       if (StringHasNoText (txt))
8518       {
8519       	ok = FALSE;
8520       }
8521       MemFree (txt);
8522       txt = SaveStringFromText (sbfp->lastname);
8523       if (StringHasNoText (txt))
8524       {
8525       	ok = FALSE;
8526       }
8527       MemFree (txt);
8528       if (!ok)
8529       {
8530       	Message (MSG_ERROR, "You must supply a first and last name for the contact.");
8531       	return;
8532       }
8533     }
8534     if (sbfp->currentPage < 3) {
8535       SetValue (sbfp->tbs, sbfp->currentPage + 1);
8536     } else if (sbfp->goToNext != NULL) {
8537       (sbfp->goToNext) (b);
8538     }
8539   }
8540 }
8541 
PrevSubmitFormBtn(ButtoN b)8542 static void PrevSubmitFormBtn (ButtoN b)
8543 
8544 {
8545   SubmitFormPtr  sbfp;
8546 
8547   sbfp = (SubmitFormPtr) GetObjectExtra (b);
8548   if (sbfp != NULL) {
8549     if (sbfp->currentPage > 0) {
8550       SetValue (sbfp->tbs, sbfp->currentPage - 1);
8551     } else if (sbfp->goToPrev != NULL) {
8552       (sbfp->goToPrev) (b);
8553     }
8554   }
8555 }
8556 
ChangeHup(GrouP g)8557 static void ChangeHup (GrouP g)
8558 
8559 {
8560   Boolean        hup;
8561   SubmitFormPtr  sbfp;
8562 
8563   sbfp = (SubmitFormPtr) GetObjectExtra (g);
8564   if (sbfp != NULL) {
8565     hup = (Boolean) (GetValue (sbfp->hup) == 2);
8566     if (hup) {
8567       SafeShow (sbfp->dateGrp);
8568     } else {
8569       SafeHide (sbfp->dateGrp);
8570     }
8571   }
8572 }
8573 
8574 static CharPtr  submitFormTabs [] = {
8575   "Submission", "Contact", "Authors", "Affiliation", NULL
8576 };
8577 
SubmitFormMessage(ForM f,Int2 mssg)8578 static void SubmitFormMessage (ForM f, Int2 mssg)
8579 
8580 {
8581   SubmitFormPtr  sbfp;
8582 
8583   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8584   if (sbfp != NULL) {
8585     switch (mssg) {
8586       case VIB_MSG_IMPORT :
8587         ImportSubmitForm (f, NULL);
8588         break;
8589       case VIB_MSG_EXPORT :
8590         ExportSubmitForm (f, NULL);
8591         break;
8592       case VIB_MSG_CUT :
8593         StdCutTextProc (NULL);
8594         break;
8595       case VIB_MSG_COPY :
8596         StdCopyTextProc (NULL);
8597         break;
8598       case VIB_MSG_PASTE :
8599         StdPasteTextProc (NULL);
8600         break;
8601       case VIB_MSG_DELETE :
8602         StdDeleteTextProc (NULL);
8603         break;
8604       default :
8605         if (sbfp->appmessage != NULL) {
8606           sbfp->appmessage (f, mssg);
8607         }
8608         break;
8609     }
8610   }
8611 }
8612 
InitSubmitterFormActivate(WindoW w)8613 static void InitSubmitterFormActivate (WindoW w)
8614 
8615 {
8616   SubmitFormPtr  sbfp;
8617 
8618   sbfp = (SubmitFormPtr) GetObjectExtra (w);
8619   if (sbfp != NULL) {
8620     if (sbfp->activate != NULL) {
8621       sbfp->activate (w);
8622     }
8623     SetSubmitterImportExportItems (sbfp);
8624   }
8625 }
8626 
EnableConsortium(ButtoN b)8627 static void EnableConsortium (ButtoN b)
8628 {
8629   SubmitFormPtr  sbfp;
8630 
8631   sbfp = (SubmitFormPtr) GetObjectExtra (b);
8632   if (sbfp != NULL) {
8633     if (GetStatus (sbfp->use_consortium)) {
8634       Enable (sbfp->consortium);
8635     } else {
8636       Disable (sbfp->consortium);
8637     }
8638   }
8639 }
8640 
8641 
ImportSubmissionTemplate(ButtoN b)8642 static void ImportSubmissionTemplate (ButtoN b)
8643 {
8644   SubmitFormPtr sbfp;
8645 
8646   sbfp = (SubmitFormPtr) GetObjectExtra (b);
8647   if (sbfp == NULL) {
8648     return;
8649   }
8650   ReadSubmitBlock (sbfp->form, NULL);
8651 }
8652 
8653 
ExportSubmissionTemplate(ButtoN b)8654 static void ExportSubmissionTemplate (ButtoN b)
8655 {
8656   SubmitFormPtr sbfp;
8657 
8658   sbfp = (SubmitFormPtr) GetObjectExtra (b);
8659   if (sbfp == NULL) {
8660     return;
8661   }
8662   WriteSubmitBlock (sbfp->form, NULL);
8663 }
8664 
8665 
CleanupSubmitterForm(Nlm_GraphiC g,Nlm_VoidPtr data)8666 static void CleanupSubmitterForm (Nlm_GraphiC g, Nlm_VoidPtr data)
8667 {
8668   SubmitFormPtr f;
8669 
8670   f = (SubmitFormPtr) data;
8671   if (f != NULL) {
8672     SeqDescrFree (f->descriptors);
8673   }
8674   StdCleanupFormProc (g, data);
8675 }
8676 
8677 
CreateInitSubmitterForm(Int2 left,Int2 top,CharPtr title,BtnActnProc goToNext,BtnActnProc goBack,WndActnProc activateForm)8678 extern ForM CreateInitSubmitterForm (Int2 left, Int2 top, CharPtr title,
8679                                      BtnActnProc goToNext,
8680                                      BtnActnProc goBack,
8681                                      WndActnProc activateForm)
8682 
8683 {
8684   GrouP              c;
8685   GrouP              g;
8686   GrouP              h;
8687   GrouP              j;
8688   GrouP              m;
8689   GrouP              n;
8690   GrouP              q;
8691   SubmitFormPtr      sbfp;
8692   StdEditorProcsPtr  sepp;
8693   GrouP              t;
8694   WindoW             w;
8695   GrouP              x;
8696   GrouP              z;
8697   GrouP              g1, g2;
8698   GrouP              p;
8699   DatePtr            dp;
8700   ButtoN             b;
8701 
8702   w = NULL;
8703   sbfp = MemNew (sizeof (SubmitForm));
8704   if (sbfp != NULL) {
8705     w = FixedWindow (left, top, -10, -10, title, NULL);
8706     SetObjectExtra (w, sbfp, CleanupSubmitterForm);
8707     sbfp->form = (ForM) w;
8708     sbfp->toform = SequinBlockPtrToSubmitForm;
8709     sbfp->fromform = SubmitFormToSequinBlockPtr;
8710     sbfp->testform = TestSubmitForm;
8711     sbfp->importform = ImportSubmitForm;
8712     sbfp->exportform = ExportSubmitForm;
8713     sbfp->formmessage = SubmitFormMessage;
8714 
8715 #ifndef WIN_MAC
8716     CreateSqnInitialFormMenus (w);
8717 #endif
8718 
8719     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
8720     if (sepp != NULL) {
8721       sbfp->appmessage = sepp->handleMessages;
8722     }
8723 
8724     SetGroupSpacing (w, 10, 10);
8725 
8726     j = HiddenGroup (w, -1, 0, NULL);
8727     SetGroupSpacing (j, 10, 10);
8728 
8729     sbfp->tbs = CreateFolderTabs (j, submitFormTabs, 0, 0, 0,
8730                                   SYSTEM_FOLDER_TAB,
8731                                   ChangeSubmitFormPage, (Pointer) sbfp);
8732     sbfp->currentPage = SUBMISSION_PAGE;
8733 
8734     sbfp->visitedContact = FALSE;
8735     sbfp->visitedAuthor = FALSE;
8736 
8737     h = HiddenGroup (w, 0, 0, NULL);
8738 
8739     q = HiddenGroup (h, -1, 0, NULL);
8740     SetGroupSpacing (q, 10, 20);
8741     m = HiddenGroup (q, -1, 0, NULL);
8742     g = HiddenGroup (m, 0, -4, NULL);
8743     SetGroupSpacing (g, 3, 10);
8744     StaticPrompt (g, "When may we release your sequence record?",
8745                   0, stdLineHeight, programFont, 'l');
8746     sbfp->hup = HiddenGroup (g, 0, -2, ChangeHup);
8747     SetObjectExtra (sbfp->hup, sbfp, NULL);
8748     RadioButton (sbfp->hup, "Immediately After Processing");
8749     RadioButton (sbfp->hup, "Release Date:");
8750     SetValue (sbfp->hup, 1);
8751     sbfp->dateGrp = HiddenGroup (m, -1, 0, NULL);
8752     /* StaticPrompt (sbfp->dateGrp, "Release Date: ", 0, popupMenuHeight, programFont, 'l'); */
8753 
8754     dp = DateCurr ();
8755     if (dp != NULL && dp->data[0] == 1) {
8756       sbfp->reldate = CreateDateDialogEx (sbfp->dateGrp, NULL, dp->data[1] + 1900, 10);
8757     } else {
8758       sbfp->reldate = CreateDateDialog (sbfp->dateGrp, NULL);
8759     }
8760     p = MultiLinePrompt (sbfp->dateGrp,
8761                          "NOTE: Sequences must be released when the accession number or any portion of the sequence is published.",
8762                          25 * stdCharWidth, programFont);
8763     AlignObjects (ALIGN_CENTER, (HANDLE) sbfp->reldate, (HANDLE) p, NULL);
8764     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) sbfp->dateGrp, NULL);
8765     Hide (sbfp->dateGrp);
8766     t = HiddenGroup (q, 1, 0, NULL);
8767     StaticPrompt (t, "Tentative title for manuscript (required)", 0, 0, programFont, 'c');
8768     sbfp->title = ScrollText (t, 25, 4, programFont, TRUE, NULL);
8769     b = PushButton (q, "Click here to import a template", ImportSubmissionTemplate);
8770     SetObjectExtra (b, sbfp, NULL);
8771     AlignObjects (ALIGN_CENTER, (HANDLE) sbfp->reldate,
8772                   (HANDLE) sbfp->title, (HANDLE) t, (HANDLE) b, NULL);
8773     sbfp->pages [SUBMISSION_PAGE] = q;
8774     Hide (sbfp->pages [SUBMISSION_PAGE]);
8775 
8776     q = HiddenGroup (h, -1, 0, NULL);
8777     SetGroupSpacing (q, 10, 20);
8778     n = HiddenGroup (q, 4, 0, NULL);
8779     SetGroupSpacing (n, -1, 2);
8780     StaticPrompt (n, "First Name", 0, 0, programFont, 'c');
8781     StaticPrompt (n, "M.I.", 0, 0, programFont, 'c');
8782     StaticPrompt (n, "Last Name", 0, 0, programFont, 'c');
8783     StaticPrompt (n, "Sfx", 0, 0, programFont, 'c');
8784     sbfp->firstname = DialogText (n, "", 8, NULL);
8785     sbfp->middleinit = DialogText (n, "", 4, NULL);
8786     sbfp->lastname = DialogText (n, "", 9, NULL);
8787     /*
8788     sbfp->suffix = DialogText (n, "", 3, NULL);
8789     sbfp->suffix = PopupList (n, TRUE, SuffixPopup_Callback);
8790     */
8791     sbfp->suffix = PopupList (n, TRUE, NULL);
8792     SetObjectExtra (sbfp->suffix, sbfp, NULL);
8793     InitEnumPopup (sbfp->suffix, name_suffix_alist, NULL);
8794     SetEnumPopup (sbfp->suffix, name_suffix_alist, 0);
8795 
8796     sbfp->phonefaxemail = CreateExtAffilDialog (q, NULL, NULL, &x);
8797     Show (x);
8798     Show (sbfp->phonefaxemail);
8799     AlignObjects (ALIGN_CENTER, (HANDLE) n, (HANDLE) sbfp->phonefaxemail, NULL);
8800     sbfp->pages [CONTACT_PAGE] = q;
8801     Hide (sbfp->pages [CONTACT_PAGE]);
8802 
8803     q = HiddenGroup (h, -1, 0, NULL);
8804     SetGroupSpacing (q, 10, 20);
8805     sbfp->authors = CreateAuthorDialog (q, 3, -1);
8806     z = HiddenGroup (q, 0, 2, NULL);
8807     g1 = HiddenGroup (z, 2, 0, NULL);
8808     sbfp->use_consortium = CheckBox (g1, "Consortium", EnableConsortium);
8809     SetObjectExtra (sbfp->use_consortium, sbfp, NULL);
8810     sbfp->consortium = DialogText (g1, "", 16, NULL);
8811     Disable (sbfp->consortium);
8812     g2 = HiddenGroup (z, 1, 0, NULL);
8813     MultiLinePrompt (g2, "The consortium field should be used when a "
8814                          "consortium is responsible for the sequencing or "
8815                          "publication of the data.  Individual authors may "
8816                          "be listed along with a consortium name.",
8817                           25 * stdCharWidth, programFont);
8818     AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) g2, NULL);
8819     AlignObjects (ALIGN_CENTER, (HANDLE) sbfp->authors, (HANDLE) z, NULL);
8820     sbfp->pages [AUTHOR_PAGE] = q;
8821     Hide (sbfp->pages [AUTHOR_PAGE]);
8822 
8823     q = HiddenGroup (h, -1, 0, NULL);
8824     SetGroupSpacing (q, 10, 20);
8825     sbfp->affil = CreateExtAffilDialog (q, NULL, &g, NULL);
8826     Show (g);
8827     Show (sbfp->affil);
8828     b = PushButton (q, "Click here to export a template", ExportSubmissionTemplate);
8829     SetObjectExtra (b, sbfp, NULL);
8830     AlignObjects (ALIGN_CENTER, (HANDLE) sbfp->affil, (HANDLE) b, NULL);
8831     sbfp->pages [AFFILIATION_PAGE] = q;
8832     Hide (sbfp->pages [AFFILIATION_PAGE]);
8833 
8834     c = HiddenGroup (w, 4, 0, NULL);
8835     SetGroupSpacing (c, 10, 2);
8836     sbfp->goToPrev = goBack;
8837     sbfp->prevBtn = PushButton (c, " << Prev Form ", PrevSubmitFormBtn);
8838     SetObjectExtra (sbfp->prevBtn, sbfp, NULL);
8839     sbfp->goToNext = goToNext;
8840     sbfp->nextBtn = PushButton (c, " Next Page >> ", NextSubmitFormBtn);
8841     SetObjectExtra (sbfp->nextBtn, sbfp, NULL);
8842 
8843     AlignObjects (ALIGN_CENTER,
8844                   (HANDLE) sbfp->pages [SUBMISSION_PAGE],
8845                   (HANDLE) sbfp->pages [CONTACT_PAGE],
8846                   (HANDLE) sbfp->pages [AUTHOR_PAGE],
8847                   (HANDLE) sbfp->pages [AFFILIATION_PAGE],
8848                   (HANDLE) sbfp->tbs, (HANDLE) c, NULL);
8849 
8850     RealizeWindow (w);
8851 
8852     SafeSetTitle (sbfp->prevBtn, "<< Prev Form");
8853     SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8854 
8855     sbfp->activate = activateForm;
8856     SetActivate (w, InitSubmitterFormActivate);
8857 
8858     Show (sbfp->pages [sbfp->currentPage]);
8859     EnterSubmitPage (sbfp, sbfp->currentPage);
8860   }
8861   return (ForM) w;
8862 }
8863 
AddCodonListTotRNA(tRNAPtr trna,ValNodePtr codons)8864 extern void AddCodonListTotRNA (tRNAPtr trna, ValNodePtr codons)
8865 {
8866   ValNodePtr vnp;
8867   Int2       j, k, q;
8868   Char       str [8];
8869   Char       ch;
8870   Uint1      codon [4];
8871   Uint1      code;
8872 
8873   if (trna == NULL) return;
8874 
8875   for (j = 0; j < 6; j++) {
8876     trna->codon [j] = 255;
8877   }
8878 
8879   if (codons == NULL)
8880   {
8881     return;
8882   }
8883 
8884   for (vnp = codons, j = 0; vnp != NULL && j < 6; vnp = vnp->next) {
8885     str [0] = '\0';
8886     StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
8887     if (str [0] != '\0') {
8888       k = 0;
8889       q = 0;
8890       ch = str [k];
8891       while (ch != '\0' && q < 3) {
8892         ch = TO_UPPER (ch);
8893         if (StringChr ("ACGTU", ch) != NULL) {
8894           if (ch == 'U') {
8895             ch = 'T';
8896           }
8897           codon [q] = (Uint1) ch;
8898           q++;
8899         }
8900         k++;
8901         ch = str [k];
8902       }
8903       codon [q] = 0;
8904       if (q == 3) {
8905         code = IndexForCodon (codon, Seq_code_iupacna);
8906         if (code != INVALID_RESIDUE) {
8907           trna->codon [j] = code;
8908         }
8909       }
8910       j++;
8911     }
8912   }
8913 }
8914 
8915 
ParseCodonsFromtRNACommentProc(SeqFeatPtr sfp,Pointer userdata)8916 static void ParseCodonsFromtRNACommentProc (SeqFeatPtr sfp, Pointer userdata)
8917 {
8918   RnaRefPtr rrp;
8919   tRNAPtr   trna;
8920   CharPtr   cp, sep;
8921   CharPtr   codon_name;
8922 
8923   if (sfp == NULL
8924       || sfp->comment == NULL
8925       || sfp->data.choice != SEQFEAT_RNA
8926       || (rrp = (RnaRefPtr)sfp->data.value.ptrvalue) == NULL
8927       || rrp->type != 3 || rrp->ext.choice != 2) {
8928     return;
8929   }
8930   trna = rrp->ext.value.ptrvalue;
8931   if (trna == NULL) return;
8932 
8933   cp = StringStr (sfp->comment, "recognized codon");
8934   if (cp == NULL) {
8935     cp = StringStr (sfp->comment, "codon recognized");
8936   }
8937   if (cp == NULL) return;
8938   sep = StringStr (cp, "=");
8939   if (sep == NULL) {
8940     sep = StringStr (cp, ":");
8941   }
8942   cp = sep;
8943   if (cp == NULL) {
8944     Message (MSG_ERROR, "Unable to read codon from %s", sfp->comment);
8945     return;
8946   }
8947 
8948   codon_name = cp + 1;
8949 
8950   if (!SettRNACodons_Recognized(sfp, NULL, codon_name, ExistingTextOption_append_semi)) {
8951     Message (MSG_ERROR, "Invalid codon in %s", sfp->comment);
8952   }
8953 }
8954 
ParseCodonsFromtRNAComment(IteM i)8955 extern void ParseCodonsFromtRNAComment (IteM i)
8956 {
8957   BaseFormPtr bfp;
8958   SeqEntryPtr sep;
8959 
8960 #ifdef WIN_MAC
8961   bfp = currentFormDataPtr;
8962 #else
8963   bfp = GetObjectExtra (i);
8964 #endif
8965   if (bfp == NULL) return;
8966   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8967   if (sep == NULL) return;
8968 
8969   VisitFeaturesInSep (sep, NULL, ParseCodonsFromtRNACommentProc);
8970   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8971   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8972 }
8973 
GetAntiCodonPositionFromComment(CharPtr comment,Int4Ptr start,Int4Ptr stop)8974 static Boolean GetAntiCodonPositionFromComment (CharPtr comment, Int4Ptr start, Int4Ptr stop)
8975 {
8976   CharPtr cp, cpend;
8977   Int4    val;
8978   Char    ch;
8979 
8980   if (comment == NULL || start == NULL || stop == NULL) return FALSE;
8981   cp = StringStr (comment, "anticodon");
8982   if (cp == NULL) return FALSE;
8983   cp += 8;
8984   while (*cp != 0 && !isdigit ((Int4)(*cp)))
8985   {
8986   	cp++;
8987   }
8988   if (*cp == 0)
8989   {
8990   	Message (MSG_ERROR, "Found 'anticodon' but no numbers for position in %s", comment);
8991   	return FALSE;
8992   }
8993 
8994   cpend = cp + 1;
8995   while (*cpend != 0 && isdigit ((Int4)(*cpend)))
8996   {
8997   	cpend ++;
8998   }
8999   if (*cpend == 0)
9000   {
9001   	Message (MSG_ERROR, "Found 'anticodon' but no numbers for position in %s", comment);
9002   	return FALSE;
9003   }
9004   ch = *cpend;
9005   *cpend = 0;
9006   val = atoi (cp);
9007   *cpend = ch;
9008   cp = cpend + 1;
9009 
9010   while (*cp != 0 && !isdigit ((Int4)(*cp)))
9011   {
9012   	cp++;
9013   }
9014   if (*cp == 0)
9015   {
9016   	Message (MSG_ERROR, "Found 'anticodon' but no numbers for position in %s", comment);
9017   	return FALSE;
9018   }
9019   cpend = cp + 1;
9020   while (*cpend != 0 && isdigit ((Int4)(*cpend)))
9021   {
9022   	cpend ++;
9023   }
9024   ch = *cpend;
9025   *cpend = 0;
9026   *start = val;
9027   *stop = atoi (cp);
9028   *cpend = ch;
9029   return TRUE;
9030 }
9031 
ParseAntiCodonsFromtRNACommentProc(SeqFeatPtr sfp,Pointer userdata)9032 static void ParseAntiCodonsFromtRNACommentProc (SeqFeatPtr sfp, Pointer userdata)
9033 {
9034   RnaRefPtr rrp;
9035   tRNAPtr   trna;
9036   Int4      start;
9037   Int4      stop;
9038   SeqLocPtr slp;
9039   SeqIntPtr sip;
9040 
9041   if (sfp == NULL
9042       || sfp->comment == NULL
9043       || sfp->data.choice != SEQFEAT_RNA
9044       || (rrp = (RnaRefPtr)sfp->data.value.ptrvalue) == NULL
9045       || rrp->type != 3 || rrp->ext.choice != 2) {
9046     return;
9047   }
9048   trna = rrp->ext.value.ptrvalue;
9049   if (trna == NULL) return;
9050 
9051   if (! GetAntiCodonPositionFromComment (sfp->comment, &start, &stop)) return;
9052   sip = SeqIntNew ();
9053   if (sip == NULL) return;
9054   if (start <= stop) {
9055     sip->from = start - 1;
9056     sip->to = stop - 1;
9057   } else {
9058     sip->from = stop - 1;
9059     sip->to = start - 1;
9060   }
9061   sip->strand = SeqLocStrand (sfp->location);
9062   sip->id = SeqIdDup (SeqLocId (sfp->location));
9063   slp = ValNodeNew (NULL);
9064   if (slp == NULL) return;
9065   slp->choice = 4;
9066   slp->data.ptrvalue = sip;
9067 
9068   if (trna->anticodon != NULL) {
9069     SeqLocFree (trna->anticodon);
9070   }
9071   trna->anticodon = slp;
9072 }
9073 
ParseAntiCodonsFromtRNAComment(IteM i)9074 extern void ParseAntiCodonsFromtRNAComment (IteM i)
9075 {
9076   BaseFormPtr bfp;
9077   SeqEntryPtr sep;
9078 
9079 #ifdef WIN_MAC
9080   bfp = currentFormDataPtr;
9081 #else
9082   bfp = GetObjectExtra (i);
9083 #endif
9084   if (bfp == NULL) return;
9085   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9086   if (sep == NULL) return;
9087 
9088   VisitFeaturesInSep (sep, NULL, ParseAntiCodonsFromtRNACommentProc);
9089   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
9090   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
9091 }
9092 
ExtractString(CharPtr str,Char PNTR buf,Int2 from,Int2 to)9093 static void ExtractString (
9094   CharPtr str,
9095   Char PNTR buf,
9096   Int2 from,
9097   Int2 to
9098 )
9099 
9100 {
9101   Int2    i;
9102   Int2    j;
9103   size_t  len;
9104 
9105   if (buf == NULL) return;
9106   *buf = '\0';
9107   if (str == NULL) return;
9108 
9109   if (from < 0 || to < 0) return;
9110   len = StringLen (str);
9111   if (from > len || to > len) return;
9112 
9113   j = 0;
9114   for (i = from; i < to; i++) {
9115     buf [j] = str [i];
9116     j++;
9117   }
9118   buf [j] = '\0';
9119 }
9120 
RevcompString(CharPtr str)9121 static void RevcompString (
9122   CharPtr str
9123 )
9124 
9125 {
9126   Char    ch;
9127   int     i;
9128   int     j;
9129   size_t  len;
9130 
9131   if (str == NULL) return;
9132   len = (int) StringLen (str);
9133   if (len < 1) return;
9134 
9135   for (i = 0, j = len - 1; i < j; i++, j--) {
9136     ch = str [i];
9137     str [i] = str [j];
9138     str [j] = ch;
9139   }
9140 
9141   for (i = 0; i < len; i++) {
9142     ch = str [i];
9143     if (ch == 'A') {
9144       ch = 'T';
9145     } else if (ch == 'C') {
9146       ch = 'G';
9147     } else if (ch == 'G') {
9148       ch = 'C';
9149     } else if (ch == 'T') {
9150       ch = 'A';
9151     }
9152     str [i] = ch;
9153   }
9154 }
9155 
LongestExactMatch(CharPtr str1,CharPtr str2,Int2 PNTR gcp)9156 static Int2 LongestExactMatch (
9157   CharPtr str1,
9158   CharPtr str2,
9159   Int2 PNTR gcp
9160 )
9161 
9162 {
9163   Char  ch1, ch2;
9164   Int2  gc = 0;
9165   int   i;
9166   Int2  len = 0;
9167 
9168   i = 0;
9169   ch1 = str1 [i];
9170   ch2 = str2 [i];
9171   while (ch1 != '\0' && ch2 != '\0' && ch1 == ch2) {
9172     len++;
9173     i++;
9174     if (ch1 == 'C' || ch1 == 'G') {
9175       gc++;
9176     }
9177     ch1 = str1 [i];
9178     ch2 = str2 [i];
9179   }
9180 
9181   *gcp = gc;
9182 
9183   return len;
9184 }
9185 
LongestSlidingMatch(CharPtr str1,CharPtr str2,Int2 PNTR gcp)9186 static Int2 LongestSlidingMatch (
9187   CharPtr str1,
9188   CharPtr str2,
9189   Int2 PNTR gcp
9190 )
9191 
9192 {
9193   Int2    gc;
9194   Int2    len;
9195   Int2    max = 0;
9196   size_t  remains = 0;
9197 
9198   if (StringHasNoText (str1) || StringHasNoText (str2)) return 0;
9199 
9200   remains = StringLen (str1);
9201 
9202   while (remains > 3 && *str1 != '\0') {
9203     len = LongestExactMatch (str1, str2, &gc);
9204     if (len > max) {
9205       max = len;
9206       *gcp = gc;
9207     }
9208     str1++;
9209     remains--;
9210   }
9211 
9212   return max;
9213 }
9214 
LongestMatch(CharPtr str1,CharPtr str2,Int2 PNTR gcp)9215 static Int2 LongestMatch (
9216   CharPtr str1,
9217   CharPtr str2,
9218   Int2 PNTR gcp
9219 )
9220 
9221 {
9222   Int2    gc = 0;
9223   Int2    len;
9224   Int2    max = 0;
9225   size_t  remains = 0;
9226 
9227   if (StringHasNoText (str1) || StringHasNoText (str2)) return 0;
9228 
9229   remains = StringLen (str2);
9230 
9231   while (remains > 3 && *str2 != '\0') {
9232     len = LongestSlidingMatch (str1, str2, &gc);
9233     if (len > max) {
9234       max = len;
9235       *gcp = gc;
9236     }
9237     str2++;
9238     remains--;
9239   }
9240 
9241   return max;
9242 }
9243 
9244 
9245 typedef struct orgnamechangedata {
9246   CharPtr oldname;
9247   CharPtr newname;
9248 } OrgNameChangeData, PNTR OrgNameChangePtr;
9249 
ReplaceOldOrgNameInTitle(SeqDescrPtr sdp,OrgNameChangePtr oncp)9250 static void ReplaceOldOrgNameInTitle (SeqDescrPtr sdp, OrgNameChangePtr oncp)
9251 {
9252   CharPtr oldtitle, newtitle, orgnamestart;
9253   Int4    oldorglen;
9254 
9255   if (sdp == NULL || oncp == NULL
9256     || oncp->oldname == NULL || oncp->newname == NULL)
9257   {
9258     return;
9259   }
9260 
9261   oldtitle = sdp->data.ptrvalue;
9262 
9263   if (oldtitle == NULL) return;
9264 
9265   orgnamestart = StringRChr (oldtitle, '[');
9266   if (orgnamestart == NULL) return;
9267   oldorglen = StringLen (oncp->oldname);
9268   if (StringNCmp (orgnamestart + 1, oncp->oldname, oldorglen) == 0
9269     && orgnamestart [ oldorglen + 1] == ']')
9270   {
9271     newtitle = MemNew (StringLen (oldtitle) - StringLen (oncp->oldname) + StringLen (oncp->newname) + 2);
9272     if (newtitle == NULL) return;
9273     StringNCpy (newtitle, oldtitle, orgnamestart - oldtitle + 1);
9274     StringCat (newtitle, oncp->newname);
9275     StringCat (newtitle, "]");
9276     MemFree (sdp->data.ptrvalue);
9277     sdp->data.ptrvalue = newtitle;
9278   }
9279 }
9280 
FixProteinTitleAfterOrganismNameChange(BioseqPtr bsp,Pointer userdata)9281 static void FixProteinTitleAfterOrganismNameChange (BioseqPtr bsp, Pointer userdata)
9282 {
9283   OrgNameChangePtr oncp;
9284   SeqDescrPtr sdp;
9285   BioSourcePtr biop;
9286 
9287   if (bsp == NULL
9288     || ! ISA_aa (bsp->mol)
9289     || (oncp = (OrgNameChangePtr)userdata) == NULL
9290     || oncp->oldname == NULL
9291     || oncp->newname == NULL)
9292   {
9293     return;
9294   }
9295 
9296   for (sdp = bsp->descr; sdp != NULL; sdp = sdp->next) {
9297     if (sdp->choice == Seq_descr_title)
9298     {
9299       ReplaceOldOrgNameInTitle (sdp, oncp);
9300     }
9301     else if (sdp->choice == Seq_descr_source)
9302     {
9303       biop = sdp->data.ptrvalue;
9304       if (biop != NULL && biop->org != NULL
9305         && StringCmp (biop->org->taxname, oncp->oldname) == 0)
9306       {
9307         SetTaxNameAndRemoveTaxRef (biop->org, StringSave (oncp->newname));
9308       }
9309     }
9310   }
9311 }
9312 
9313 typedef struct parseformdata {
9314   FEATURE_FORM_BLOCK
9315 
9316   TexT           atleft;
9317   TexT           atright;
9318   DialoG         orgmod;
9319   DialoG         subsource;
9320   PopuP          taxname;
9321   Boolean        parsedef;
9322   Char           path [PATH_MAX];
9323   FILE           *fp;
9324   Boolean        replaceOldAsked;
9325   Boolean        doReplaceAll;
9326   Boolean        use_semicolon;
9327   ButtoN         leaveDlgUp;
9328 } ParseFormData, PNTR ParseFormPtr;
9329 
9330 typedef struct localidfinddata {
9331   CharPtr str;
9332   Int4    str_size;
9333 } LocalIDFindData, PNTR LocalIDFindPtr;
9334 
LookForLocalID(BioseqPtr bsp,Pointer userdata)9335 static void LookForLocalID (BioseqPtr bsp, Pointer userdata)
9336 {
9337   LocalIDFindPtr lidfp;
9338   SeqIdPtr      sip;
9339 
9340   if (bsp == NULL || (lidfp = (LocalIDFindPtr) userdata) == NULL) {
9341     return;
9342   }
9343   if (lidfp->str [0] != 0) return;
9344 
9345   for (sip = bsp->id; sip != NULL; sip = sip->next) {
9346     if (sip->choice == SEQID_LOCAL) {
9347       SeqIdWrite (sip, lidfp->str, PRINTID_REPORT, lidfp->str_size);
9348       if (StringNICmp (lidfp->str, "tmpseq_", 7) == 0 ||
9349           StringNICmp (lidfp->str, "segseq_", 7) == 0 ||
9350           StringNICmp (lidfp->str, "SEG_dna", 7) == 0)
9351       {
9352         /* don't want to use this one */
9353         lidfp->str [0] = 0;
9354       } else {
9355         return;
9356       }
9357     }
9358   }
9359 }
9360 
FindLocalIDForOrganism(SeqEntryPtr sep,CharPtr str,Int4 str_size)9361 static void FindLocalIDForOrganism (
9362   SeqEntryPtr  sep,
9363   CharPtr      str,
9364   Int4         str_size
9365 )
9366 {
9367   LocalIDFindData lidfd;
9368 
9369   if (sep == NULL || sep->data.ptrvalue == NULL) return;
9370   lidfd.str = str;
9371   lidfd.str_size = str_size;
9372   VisitBioseqsInSep (sep, (Pointer) &lidfd, LookForLocalID);
9373 }
9374 
GetDataForOrganism(SeqEntryPtr sep,CharPtr str,Int4 str_size,CharPtr useme,ParseFormPtr pfp)9375 static void GetDataForOrganism (
9376   SeqEntryPtr  sep,
9377   CharPtr      str,
9378   Int4         str_size,
9379   CharPtr      useme,
9380   ParseFormPtr pfp
9381 )
9382 {
9383   SeqEntryPtr nsep;
9384   ValNodePtr    ttl;
9385   Char          txt [128];
9386   CharPtr       ptr;
9387 
9388   str [0] = 0;
9389   if (sep == NULL || pfp == NULL) return;
9390   nsep = FindNucSeqEntry (sep);
9391   if (nsep == NULL || nsep->data.ptrvalue == NULL) return;
9392 
9393   if (useme != NULL) {
9394     StringNCpy_0 (str, useme, str_size);
9395   } else if (pfp->parsedef) {
9396     ttl = SeqEntryGetSeqDescr (nsep, Seq_descr_title, NULL);
9397     if (ttl == NULL && sep != nsep) {
9398       ttl = SeqEntryGetSeqDescr (sep, Seq_descr_title, NULL);
9399     }
9400     if (ttl == NULL || ttl->data.ptrvalue == NULL) return;
9401     StringNCpy_0 (str, (CharPtr) ttl->data.ptrvalue, str_size);
9402     GetTitle (pfp->atleft, txt, sizeof (txt));
9403     if (! StringHasNoText (txt)) {
9404       ptr = StringISearch (str, txt);
9405       if (ptr != NULL) {
9406         StringNCpy_0 (str, ptr + StringLen (txt), str_size);
9407       }
9408     }
9409     GetTitle (pfp->atright, txt, sizeof (txt));
9410     if (txt [0] != '\0' /* ! StringHasNoText (txt) */) {
9411       ptr = StringISearch (str, txt);
9412       if (ptr != NULL) {
9413         *ptr = '\0';
9414       }
9415     }
9416   } else {
9417     FindLocalIDForOrganism (nsep, str, str_size);
9418     if (str [0] == 0) {
9419       FindLocalIDForOrganism (sep, str, str_size);
9420     }
9421   }
9422   return;
9423 }
9424 
ApplyDataToBioSourcePtr(ParseFormPtr pfp,BioSourcePtr biop,BioSourcePtr topbiop,SeqEntryPtr sep,CharPtr data)9425 static void ApplyDataToBioSourcePtr (
9426   ParseFormPtr pfp,
9427   BioSourcePtr biop,
9428   BioSourcePtr topbiop,
9429   SeqEntryPtr  sep,
9430   CharPtr      data
9431 )
9432 {
9433   Int2          taxnameval;
9434   ValNodePtr    vnp;
9435   OrgRefPtr     orp;
9436   OrgModPtr     mod;
9437   Uint1         orgmodtype;
9438   Uint1         subsourcetype;
9439   Uint1         subtype;
9440   OrgNamePtr    onp;
9441   OrgModPtr     tmpmod;
9442   SubSourcePtr  ssp;
9443   SubSourcePtr  tmpssp;
9444 
9445   taxnameval = GetValue (pfp->taxname);
9446   if (taxnameval == 2) {
9447     if (biop == NULL) {
9448       biop = BioSourceNew ();
9449       if (biop != NULL) {
9450         orp = OrgRefNew ();
9451         biop->org = orp;
9452         vnp = CreateNewDescriptor (sep, Seq_descr_source);
9453         if (vnp != NULL) {
9454           vnp->data.ptrvalue = (Pointer) biop;
9455         }
9456       }
9457     }
9458     if (biop == NULL) return;
9459     orp = biop->org;
9460     if (orp == NULL) return;
9461     SetTaxNameAndRemoveTaxRef (orp, StringSave (data));
9462   }
9463   if (biop == NULL && topbiop != NULL) {
9464     biop = (BioSourcePtr) AsnIoMemCopy ((Pointer) topbiop,
9465                                         (AsnReadFunc) BioSourceAsnRead,
9466                                         (AsnWriteFunc) BioSourceAsnWrite);
9467     if (biop != NULL) {
9468       vnp = CreateNewDescriptor (sep, Seq_descr_source);
9469       if (vnp != NULL) {
9470         vnp->data.ptrvalue = (Pointer) biop;
9471       }
9472     }
9473   }
9474   if (biop == NULL) return;
9475   orgmodtype = 0;
9476   subsourcetype = 0;
9477   if (taxnameval == 3) {
9478     orgmodtype = 255;
9479   } else if (taxnameval == 4) {
9480     subsourcetype = 255;
9481   } else {
9482     vnp = DialogToPointer (pfp->orgmod);
9483     if (vnp != NULL) {
9484       orgmodtype = vnp->choice;
9485       vnp = ValNodeFreeData (vnp);
9486     }
9487     if (orgmodtype == 0) {
9488       vnp = DialogToPointer (pfp->subsource);
9489       if (vnp != NULL) {
9490         subsourcetype = vnp->choice;
9491         vnp = ValNodeFreeData (vnp);
9492       }
9493     }
9494   }
9495   if (! StringHasNoText (data)) {
9496     if (orgmodtype > 0) {
9497       subtype = orgmodtype;
9498       orp = biop->org;
9499       if (orp == NULL) {
9500         orp = OrgRefNew ();
9501         biop->org = orp;
9502       }
9503       if (orp != NULL) {
9504         onp = orp->orgname;
9505         if (onp == NULL) {
9506           onp = OrgNameNew ();
9507           orp->orgname = onp;
9508         }
9509         if (onp != NULL) {
9510           mod = onp->mod;
9511           while (mod != NULL && mod->subtype != subtype) {
9512             mod = mod->next;
9513           }
9514           if (mod == NULL) {
9515             mod = OrgModNew ();
9516             if (onp->mod == NULL) {
9517               onp->mod = mod;
9518             } else {
9519               tmpmod = onp->mod;
9520               while (tmpmod->next != NULL) {
9521                 tmpmod = tmpmod->next;
9522               }
9523               tmpmod->next = mod;
9524             }
9525           }
9526           if (mod != NULL) {
9527             mod->subtype = subtype;
9528             AppendOrReplaceString (&(mod->subname), data,
9529                                    &(pfp->replaceOldAsked),
9530                                    &(pfp->doReplaceAll),
9531                                    &(pfp->use_semicolon));
9532           }
9533         }
9534       }
9535     } else if (subsourcetype > 0) {
9536       subtype = subsourcetype;
9537       ssp = biop->subtype;
9538       while (ssp != NULL && ssp->subtype != subtype) {
9539         ssp = ssp->next;
9540       }
9541       if (ssp == NULL) {
9542         ssp = SubSourceNew ();
9543         if (biop->subtype == NULL) {
9544           biop->subtype = ssp;
9545         } else {
9546           tmpssp = biop->subtype;
9547           while (tmpssp->next != NULL) {
9548             tmpssp = tmpssp->next;
9549           }
9550           tmpssp->next = ssp;
9551         }
9552       }
9553       if (ssp != NULL) {
9554         ssp->subtype = subtype;
9555         AppendOrReplaceString (&(ssp->name), data,
9556                                &(pfp->replaceOldAsked),
9557                                &(pfp->doReplaceAll),
9558                                &(pfp->use_semicolon));
9559       }
9560     }
9561   }
9562 }
9563 
DoOneParseItem(Uint2 entityID,SeqEntryPtr sep,ParseFormPtr pfp,BioSourcePtr topbiop,CharPtr useme,SeqEntryPtr nps)9564 static void DoOneParseItem (Uint2 entityID, SeqEntryPtr sep, ParseFormPtr pfp, BioSourcePtr topbiop, CharPtr useme, SeqEntryPtr nps)
9565 
9566 {
9567   BioSourcePtr  biop;
9568   BioseqSetPtr  bssp;
9569   Char          str [256];
9570   SeqEntryPtr   tmp;
9571   OrgNameChangeData oncd;
9572 
9573   if (sep == NULL || pfp == NULL) return;
9574   if (IS_Bioseq_set (sep)) {
9575     bssp = (BioseqSetPtr) sep->data.ptrvalue;
9576     if (bssp != NULL) {
9577       /* if nucprot set, look for biosource here */
9578       biop = NULL;
9579       SeqEntryToBioSource (sep, NULL, NULL, 0, &biop);
9580       if (biop != NULL && topbiop != NULL) {
9581         topbiop = biop;
9582         if (bssp->_class == BioseqseqSet_class_nuc_prot)
9583         {
9584           GetDataForOrganism ( sep, str, sizeof (str), useme, pfp);
9585           if (topbiop->org != NULL && topbiop->org->taxname != NULL)
9586           {
9587             oncd.oldname = topbiop->org->taxname;
9588             oncd.newname = str;
9589             VisitBioseqsInSep (sep, &oncd, FixProteinTitleAfterOrganismNameChange);
9590           }
9591           ApplyDataToBioSourcePtr (pfp, topbiop, NULL, sep, str);
9592           return;
9593         }
9594       }
9595       for (tmp = bssp->seq_set; tmp != NULL; tmp = tmp->next) {
9596         DoOneParseItem (entityID, tmp, pfp, topbiop, useme, sep);
9597       }
9598       return;
9599     }
9600   }
9601   GetDataForOrganism ( sep, str, sizeof (str), useme, pfp);
9602   if (StringHasNoText (str)) return;
9603   biop = NULL;
9604   SeqEntryToBioSource (sep, NULL, NULL, 0, &biop);
9605   ApplyDataToBioSourcePtr (pfp, biop, topbiop, sep, str);
9606 }
9607 
DoOneParse(Uint2 entityID,SeqEntryPtr sep,ParseFormPtr pfp,BioSourcePtr topbiop)9608 static void DoOneParse (Uint2 entityID, SeqEntryPtr sep, ParseFormPtr pfp, BioSourcePtr topbiop)
9609 
9610 {
9611   BioseqPtr     bsp;
9612   BioseqSetPtr  bssp;
9613   Char          gb [256];
9614   CharPtr       ptr;
9615   SeqIdPtr      sip;
9616   Char          str [250];
9617   SeqEntryPtr   tmp;
9618 
9619   if (sep == NULL || pfp == NULL) return;
9620   if (pfp->fp != NULL) {
9621     ReadLine (pfp->fp, str, sizeof (str)); /* FileGets on Mac sometimes sees '\r' instead of '\n' */
9622     while (Nlm_fileDone || str [0] != 0) {
9623       if (! StringHasNoText (str)) {
9624         ptr = StringChr (str, '\t');
9625         if (ptr != NULL) {
9626           *ptr = '\0';
9627           ptr++;
9628           TrimSpacesAroundString (str);
9629           TrimSpacesAroundString (ptr);
9630           sip = MakeSeqID (str);
9631           bsp = BioseqFind (sip);
9632           SeqIdFree (sip);
9633           if (bsp == NULL) {
9634             sprintf (gb, "gb|%s|", str);
9635             sip = MakeSeqID (gb);
9636             bsp = BioseqFind (sip);
9637             SeqIdFree (sip);
9638           }
9639           if (bsp != NULL) {
9640             tmp = GetBestTopParentForData (entityID, bsp);
9641              DoOneParseItem (entityID, tmp, pfp, topbiop, ptr, NULL);
9642           }
9643         }
9644       }
9645       str [0] = 0;
9646       ReadLine (pfp->fp, str, sizeof (str));
9647     }
9648     return;
9649   }
9650   if (IS_Bioseq_set (sep)) {
9651     bssp = (BioseqSetPtr) sep->data.ptrvalue;
9652     if (bssp != NULL && (bssp->_class == 7 ||
9653                          (IsPopPhyEtcSet (bssp->_class)))) {
9654       for (tmp = bssp->seq_set; tmp != NULL; tmp = tmp->next) {
9655         DoOneParse (entityID, tmp, pfp, topbiop);
9656       }
9657       return;
9658     }
9659   }
9660   DoOneParseItem (entityID, sep, pfp, topbiop, NULL, NULL);
9661 }
9662 
DoParseDeflineProc(ButtoN b)9663 static void DoParseDeflineProc (ButtoN b)
9664 
9665 {
9666   BioSourcePtr  topbiop;
9667   ParseFormPtr  pfp;
9668   SeqEntryPtr   sep;
9669 
9670   pfp = (ParseFormPtr) GetObjectExtra (b);
9671   if (pfp == NULL || pfp->input_entityID == 0) return;
9672   sep = GetTopSeqEntryForEntityID (pfp->input_entityID);
9673   if (sep == NULL) return;
9674   Hide (pfp->form);
9675   WatchCursor ();
9676   Update ();
9677   /* if popset, look for top biosource */
9678   SeqEntryToBioSource (sep, NULL, NULL, 0, &topbiop);
9679   if (! StringHasNoText (pfp->path)) {
9680     pfp->fp = FileOpen (pfp->path, "r");
9681   }
9682   DoOneParse (pfp->input_entityID, sep, pfp, topbiop);
9683   FileClose (pfp->fp);
9684   ArrowCursor ();
9685   Update ();
9686   ObjMgrSetDirtyFlag (pfp->input_entityID, TRUE);
9687   ObjMgrSendMsg (OM_MSG_UPDATE, pfp->input_entityID, 0, 0);
9688   if (GetStatus (pfp->leaveDlgUp)) {
9689     Show (pfp->form);
9690   } else {
9691     Remove (pfp->form);
9692   }
9693 }
9694 
ParseDeflineMessageProc(ForM f,Int2 mssg)9695 static void ParseDeflineMessageProc (ForM f, Int2 mssg)
9696 
9697 {
9698   StdEditorProcsPtr  sepp;
9699 
9700   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
9701   if (sepp != NULL) {
9702     if (sepp->handleMessages != NULL) {
9703       sepp->handleMessages (f, mssg);
9704     }
9705   }
9706 }
9707 
ParseDefOrLocalIDToSource(BaseFormPtr bfp,Boolean parsedef,CharPtr path)9708 static void ParseDefOrLocalIDToSource (BaseFormPtr bfp, Boolean parsedef, CharPtr path)
9709 
9710 {
9711   ButtoN             b;
9712   GrouP              c;
9713   GrouP              g;
9714   GrouP              h;
9715   GrouP              p;
9716   ParseFormPtr       pfp;
9717   SeqEntryPtr        sep;
9718   StdEditorProcsPtr  sepp;
9719   WindoW             w;
9720 
9721   if (bfp == NULL) return;
9722   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9723   if (sep == NULL) return;
9724   pfp = (ParseFormPtr) MemNew (sizeof (ParseFormData));
9725   if (pfp == NULL) return;
9726   w = FixedWindow (-50, -33, -10, -10, "Parse file to source", StdCloseWindowProc);
9727   SetObjectExtra (w, pfp, StdCleanupFormProc);
9728   pfp->form = (ForM) w;
9729   pfp->formmessage = ParseDeflineMessageProc;
9730 
9731   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
9732   if (sepp != NULL) {
9733     SetActivate (w, sepp->activateForm);
9734     pfp->appmessage = sepp->handleMessages;
9735   }
9736 
9737   pfp->input_entityID = bfp->input_entityID;
9738   pfp->input_itemID = bfp->input_itemID;
9739   pfp->input_itemtype = bfp->input_itemtype;
9740 
9741   pfp->parsedef = parsedef;
9742   StringNCpy_0 (pfp->path, path, sizeof (pfp->path));
9743   pfp->fp = NULL;
9744 
9745   h = HiddenGroup (w, -1, 0, NULL);
9746   SetGroupSpacing (h, 10, 10);
9747 
9748   g = NULL;
9749   if (parsedef) {
9750     g = HiddenGroup (h, 4, 0, NULL);
9751     StaticPrompt (g, "Get text between", 0, dialogTextHeight, programFont, 'l');
9752     pfp->atleft = DialogText (g, "", 10, NULL);
9753     StaticPrompt (g, "and", 0, dialogTextHeight, programFont, 'l');
9754     pfp->atright = DialogText (g, "", 10, NULL);
9755   }
9756 
9757   p = HiddenGroup (h, 6, 0, NULL);
9758   if (parsedef || path != NULL) {
9759     StaticPrompt (p, "Place in", 0, popupMenuHeight, programFont, 'l');
9760   } else {
9761     StaticPrompt (p, "Place localID in", 0, popupMenuHeight, programFont, 'l');
9762   }
9763   pfp->taxname = PopupList (p, TRUE, NULL);
9764   SetObjectExtra (pfp->taxname, pfp, NULL);
9765   PopupItem (pfp->taxname, " ");
9766   PopupItem (pfp->taxname, "Taxname");
9767   PopupItem (pfp->taxname, "OrgMod Note");
9768   PopupItem (pfp->taxname, "SubSource Note");
9769   SetValue (pfp->taxname, 1);
9770   StaticPrompt (p, "or", 0, popupMenuHeight, programFont, 'l');
9771   pfp->orgmod = OrgModTypeDialog (p, SHORT_SELECTION_LIST, NULL, NULL, FALSE, FALSE, TRUE);
9772   StaticPrompt (p, "or", 0, popupMenuHeight, programFont, 'l');
9773   pfp->subsource = SubSourceTypeDialog (p, SHORT_SELECTION_LIST, NULL, NULL, FALSE, FALSE, TRUE);
9774 
9775   c = HiddenGroup (h, 4, 0, NULL);
9776   b = DefaultButton (c, "Accept", DoParseDeflineProc);
9777   SetObjectExtra (b, pfp, NULL);
9778   PushButton (c, "Cancel", StdCancelButtonProc);
9779   pfp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
9780 
9781   AlignObjects (ALIGN_CENTER, (HANDLE) p, (HANDLE) c, (HANDLE) g, NULL);
9782   RealizeWindow (w);
9783   Show (w);
9784   Select (w);
9785   Select (pfp->atleft);
9786   Update ();
9787 }
9788 
ParseDefOrLocalIDToSourceMenuItem(IteM i,Boolean parsedef,CharPtr path)9789 static void ParseDefOrLocalIDToSourceMenuItem (IteM i, Boolean parsedef, CharPtr path)
9790 {
9791   BaseFormPtr bfp;
9792 
9793 #ifdef WIN_MAC
9794   bfp = currentFormDataPtr;
9795 #else
9796   bfp = GetObjectExtra (i);
9797 #endif
9798 
9799   if (bfp == NULL) return;
9800 
9801   ParseDefOrLocalIDToSource (bfp, parsedef, path);
9802 }
9803 
ParseFileToSource(IteM i)9804 extern void ParseFileToSource (IteM i)
9805 
9806 {
9807   Char  path [PATH_MAX];
9808 
9809   if (GetInputFileName (path, sizeof (path), "", "TEXT")) {
9810     ParseDefOrLocalIDToSourceMenuItem (i, FALSE, path);
9811   }
9812 }
9813 
TrimOrgNameCallback(BioSourcePtr biop,Pointer userdata)9814 static void TrimOrgNameCallback (BioSourcePtr biop, Pointer userdata)
9815 {
9816   OrgRefPtr     orp;
9817   CharPtr       tmp, cp;
9818   CharPtr       word_break;
9819   Int4          space_len;
9820 
9821   if (biop == NULL) return;
9822 
9823   orp = biop->org;
9824   if (orp == NULL || StringHasNoText (orp->taxname)) return;
9825 
9826   tmp = StringSave (orp->taxname);
9827   cp = tmp;
9828   if (StringNICmp (tmp, "uncultured ", 11) == 0) {
9829     cp = tmp + 11;
9830   }
9831 
9832   word_break = StringStr (cp, " ");
9833   if (word_break == NULL) return;
9834 
9835   space_len = StringSpn (word_break, " ");
9836 
9837   if (StringNCmp (word_break + space_len, "sp.", 3) == 0
9838       || StringNCmp (word_break + space_len, "cf.", 3) == 0
9839       || StringNCmp (word_break + space_len, "aff.", 4) == 0)
9840   {
9841     word_break = StringStr (word_break + space_len, " ");
9842     if (word_break == NULL) return;
9843   }
9844 
9845   word_break = StringStr (word_break + space_len, " ");
9846   if (word_break == NULL) return;
9847   *word_break = 0;
9848 
9849   SetTaxNameAndRemoveTaxRef (orp, tmp);
9850 }
9851 
TrimOrganismName(IteM i)9852 extern void TrimOrganismName (IteM i)
9853 {
9854   BaseFormPtr bfp;
9855   SeqEntryPtr sep;
9856 
9857 #ifdef WIN_MAC
9858   bfp = currentFormDataPtr;
9859 #else
9860   bfp = GetObjectExtra (i);
9861 #endif
9862   if (bfp == NULL) return;
9863   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9864   if (sep == NULL) return;
9865 
9866   VisitBioSourcesInSep (sep, NULL, TrimOrgNameCallback);
9867   Update ();
9868   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
9869   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
9870 }
9871 
9872 typedef struct addmodinfo {
9873   Boolean isOrgMod;
9874   Uint1 subtype;
9875   Boolean only_sp;
9876   Boolean only_cf;
9877   Boolean only_aff;
9878   Boolean only_nr;
9879   Boolean no_taxid;
9880   CharPtr abbreviation;
9881   Boolean use_abbreviation;
9882 } AddModInfo, PNTR AddModInfoPtr;
9883 
9884 typedef struct addmodlistitem {
9885   Boolean isOrgMod;
9886   Uint1 subtype;
9887   CharPtr name;
9888   CharPtr abbreviation;
9889 } AddModListItem, PNTR AddModListItemPtr;
9890 
9891 static AddModListItem mods_list[] = {
9892 { TRUE, ORGMOD_strain, "Strain", NULL },
9893 { TRUE, ORGMOD_isolate, "Isolate", NULL },
9894 { TRUE, ORGMOD_authority, "Authority", NULL },
9895 { TRUE, ORGMOD_bio_material, "Bio-material", NULL },
9896 { TRUE, ORGMOD_biovar, "Biovar", "bv." },
9897 { FALSE, SUBSRC_clone, "Clone", NULL },
9898 { FALSE, SUBSRC_collection_date, "Collection-date", NULL },
9899 { FALSE, SUBSRC_country, "Country", NULL },
9900 { TRUE, ORGMOD_culture_collection, "Culture-collection", NULL },
9901 { TRUE, ORGMOD_forma, "Forma", "f." },
9902 { TRUE, ORGMOD_forma_specialis, "Forma-specialis", "f. sp." },
9903 { FALSE, SUBSRC_genotype, "Genotype", "genotype" },
9904 { FALSE, SUBSRC_haplotype, "Haplotype", NULL },
9905 { TRUE, ORGMOD_nat_host, "Host", NULL },
9906 { TRUE, ORGMOD_isolate, "Isolate", NULL },
9907 { TRUE, ORGMOD_pathovar, "Pathovar", "pv."},
9908 { TRUE, ORGMOD_serotype, "Serotype", NULL },
9909 { TRUE, ORGMOD_serovar, "Serovar", "serovar" },
9910 { TRUE, ORGMOD_specimen_voucher, "Specimen voucher", NULL },
9911 { TRUE, ORGMOD_strain, "Strain", NULL },
9912 { TRUE, ORGMOD_sub_species, "Sub-species", "subsp." },
9913 { TRUE, ORGMOD_subtype, "Subtype", "subtype" },
9914 { TRUE, ORGMOD_type, "Type", "type" },
9915 { TRUE, ORGMOD_variety, "Variety", "var." }
9916 };
9917 
9918 
AddModToOrgProc(BioSourcePtr biop,Pointer userdata)9919 static void AddModToOrgProc (BioSourcePtr biop, Pointer userdata)
9920 {
9921   OrgRefPtr     orp;
9922   OrgModPtr     mod;
9923   OrgNamePtr    onp;
9924   Boolean       influenza;
9925   CharPtr	str_to_add;
9926   size_t        len;
9927   CharPtr	str, tmp_name;
9928   AddModInfoPtr	ami;
9929   SubSourcePtr  ssp;
9930   Boolean       ok_to_add = FALSE;
9931 
9932   if (biop == NULL) return;
9933 
9934   ami = (AddModInfoPtr) userdata;
9935 
9936   orp = biop->org;
9937   if (orp == NULL) return;
9938 
9939   if (! ami->only_sp && ! ami->only_cf && ! ami->only_aff && ! ami->only_nr)
9940   {
9941     ok_to_add = TRUE;
9942   }
9943   if (ami->only_sp && StringStr (orp->taxname, " sp.") != NULL)
9944   {
9945     ok_to_add = TRUE;
9946   }
9947   if (ami->only_cf && StringStr (orp->taxname, " cf.") != NULL)
9948   {
9949     ok_to_add = TRUE;
9950   }
9951   if (ami->only_aff && StringStr (orp->taxname, " aff.") != NULL)
9952   {
9953     ok_to_add = TRUE;
9954   }
9955   if (ami->only_nr && StringStr (orp->taxname, " nr.") != NULL)
9956   {
9957     ok_to_add = TRUE;
9958   }
9959 
9960   if (ami->no_taxid && HasTaxonomyID (biop)) {
9961     ok_to_add = FALSE;
9962   }
9963 
9964   if (!ok_to_add)
9965   {
9966     return;
9967   }
9968 
9969   onp = orp->orgname;
9970   if (onp == NULL && ami->isOrgMod)
9971   {
9972     return;
9973   }
9974 
9975   str_to_add = NULL;
9976 
9977   if (ami->isOrgMod)
9978   {
9979     mod = onp->mod;
9980     str_to_add = NULL;
9981     while (mod != NULL) {
9982       if (mod->subtype == ami->subtype) {
9983         str_to_add = StringSave (mod->subname);
9984       }
9985       mod = mod->next;
9986     }
9987   } else {
9988     if (biop->subtype != NULL) {
9989       ssp = biop->subtype;
9990       while (ssp != NULL) {
9991         if (ssp->subtype == ami->subtype) {
9992           str_to_add = StringSave (ssp->name);
9993         }
9994         ssp = ssp->next;
9995       }
9996     }
9997   }
9998   if (str_to_add != NULL) {
9999 
10000     /* strip colons for structured modifiers */
10001     if (ami->isOrgMod
10002         && (ami->subtype == ORGMOD_bio_material
10003             || ami->subtype == ORGMOD_culture_collection
10004             || ami->subtype == ORGMOD_specimen_voucher)) {
10005       FindReplaceString (&str_to_add, ":", " ", FALSE, FALSE);
10006     }
10007 
10008     influenza = FALSE;
10009     if (StringICmp (orp->taxname, "Influenza A virus") == 0 ||
10010         StringICmp (orp->taxname, "Influenza B virus") == 0) {
10011       influenza = TRUE;
10012     }
10013     len = StringLen (orp->taxname) + StringLen (str_to_add) + 6;
10014     if (influenza) {
10015       len += 2;
10016     }
10017     if (ami->abbreviation != NULL && ami->use_abbreviation)
10018     {
10019       len += StringLen (ami->abbreviation) + 1;
10020     }
10021     str = MemNew (len);
10022     if (str != NULL) {
10023       StringCpy (str, orp->taxname);
10024       StringCat (str, " ");
10025       if (ami->abbreviation != NULL && ami->use_abbreviation)
10026       {
10027         StringCat (str, ami->abbreviation);
10028         StringCat (str, " ");
10029       }
10030       if (influenza) {
10031         StringCat (str, "(");
10032       }
10033       StringCat (str, str_to_add);
10034       if (influenza) {
10035         StringCat (str, ")");
10036       }
10037 
10038       if (influenza)
10039       {
10040         tmp_name = FixInfluenzaVirusName (str);
10041         if (tmp_name != NULL)
10042         {
10043           str = MemFree (str);
10044           str = tmp_name;
10045           tmp_name = NULL;
10046         }
10047       }
10048 
10049       SetTaxNameAndRemoveTaxRef (biop->org, str);
10050       RemoveOldName (biop->org);
10051     }
10052     str_to_add = MemFree (str_to_add);
10053   }
10054 }
10055 
AddModToOrgFeat(SeqFeatPtr sfp,Pointer userdata,FilterSetPtr fsp)10056 static void AddModToOrgFeat (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr fsp)
10057 {
10058   if (sfp == NULL || sfp->data.choice != SEQFEAT_ORG
10059       || sfp->data.value.ptrvalue == NULL || userdata == NULL)
10060   {
10061     return;
10062   }
10063   else
10064   {
10065     AddModToOrgProc (sfp->data.value.ptrvalue, userdata);
10066   }
10067 }
10068 
AddModToOrgDesc(SeqDescrPtr sdp,Pointer userdata,FilterSetPtr fsp)10069 static void AddModToOrgDesc (SeqDescrPtr sdp, Pointer userdata, FilterSetPtr fsp)
10070 {
10071   if (sdp == NULL || sdp->choice != Seq_descr_source
10072       || sdp->data.ptrvalue == NULL || userdata == NULL)
10073   {
10074     return;
10075   }
10076   else
10077   {
10078     AddModToOrgProc (sdp->data.ptrvalue, userdata);
10079   }
10080 }
10081 
10082 
10083 typedef struct addmodformptr {
10084   FEATURE_FORM_BLOCK
10085 
10086   PopuP  modifier_to_add;
10087   ButtoN only_sp;
10088   ButtoN only_cf;
10089   ButtoN only_aff;
10090   ButtoN only_nr;
10091   ButtoN no_taxid;
10092   ButtoN use_abbreviation;
10093   DialoG constraint;
10094 
10095 } AddModFormData, PNTR AddModFormPtr;
10096 
DoAddModToOrg(ButtoN b)10097 static void DoAddModToOrg (ButtoN b)
10098 {
10099   AddModFormPtr	amfp;
10100   AddModInfoPtr ami;
10101   SeqEntryPtr   sep;
10102   Int4		      mod_index;
10103   FilterSetPtr  fsp;
10104 
10105   amfp = GetObjectExtra (b);
10106   if (amfp == NULL) return;
10107   Hide (amfp->form);
10108 
10109   sep = GetTopSeqEntryForEntityID (amfp->input_entityID);
10110   if (sep == NULL) return;
10111   ami = (AddModInfoPtr) MemNew (sizeof (AddModInfo));
10112   mod_index = GetValue (amfp->modifier_to_add);
10113   if (mod_index < 1
10114     || mod_index > sizeof (mods_list) / sizeof (AddModListItem))
10115     return;
10116   mod_index = mod_index - 1;
10117 
10118   ami->isOrgMod = mods_list[mod_index].isOrgMod;
10119   ami->subtype = mods_list[mod_index].subtype;
10120   ami->abbreviation = mods_list[mod_index].abbreviation;
10121   ami->only_sp = GetStatus (amfp->only_sp);
10122   ami->only_cf = GetStatus (amfp->only_cf);
10123   ami->only_aff = GetStatus (amfp->only_aff);
10124   ami->only_nr = GetStatus (amfp->only_nr);
10125   ami->no_taxid = GetStatus (amfp->no_taxid);
10126   ami->use_abbreviation = GetStatus (amfp->use_abbreviation);
10127   /* always use abbreviation for serovar */
10128   if (ami->isOrgMod && ami->subtype == ORGMOD_serovar)
10129   {
10130   	ami->use_abbreviation = TRUE;
10131   }
10132   fsp = (FilterSetPtr) DialogToPointer (amfp->constraint);
10133   OperateOnSeqEntryConstrainedObjects (sep, fsp,
10134                                        AddModToOrgFeat,
10135                                        AddModToOrgDesc,
10136                                        SEQFEAT_ORG,
10137                                        FEATDEF_ORG,
10138                                        Seq_descr_source,
10139                                        ami);
10140   fsp = FilterSetFree (fsp);
10141 
10142   Update ();
10143   ObjMgrSetDirtyFlag (amfp->input_entityID, TRUE);
10144   ObjMgrSendMsg (OM_MSG_UPDATE, amfp->input_entityID, 0, 0);
10145 
10146   if (GetStatus (amfp->leave_dlg_up))
10147   {
10148     Show (amfp->form);
10149   }
10150   else
10151   {
10152     Remove (amfp->form);
10153   }
10154 }
10155 
ChangeModPopup(PopuP p)10156 static void ChangeModPopup (PopuP p)
10157 {
10158   AddModFormPtr amfp;
10159   Int4          mod_index;
10160 
10161   amfp = (AddModFormPtr) GetObjectExtra (p);
10162   if (amfp == NULL) return;
10163 
10164   mod_index = GetValue (amfp->modifier_to_add);
10165   if (mod_index < 1
10166     || mod_index > sizeof (mods_list) / sizeof (AddModListItem))
10167     return;
10168   mod_index = mod_index - 1;
10169   if ( mods_list [mod_index].abbreviation != NULL)
10170   {
10171     Enable (amfp->use_abbreviation);
10172     if ( !mods_list[mod_index].isOrgMod && mods_list [mod_index].subtype == SUBSRC_genotype) {
10173       SetStatus (amfp->use_abbreviation, FALSE);
10174     } else {
10175       SetStatus (amfp->use_abbreviation, TRUE);
10176     }
10177   }
10178   else
10179   {
10180     Disable (amfp->use_abbreviation);
10181   }
10182 }
10183 
10184 
AddModToOrgBaseForm(BaseFormPtr bfp)10185 extern void AddModToOrgBaseForm (BaseFormPtr bfp)
10186 {
10187   AddModFormPtr amfp;
10188   WindoW w;
10189   GrouP	g;
10190   GrouP	h;
10191   GrouP c;
10192   Int2 index;
10193   ButtoN b;
10194 
10195   if (bfp == NULL) return;
10196 
10197   amfp = (AddModFormPtr) MemNew (sizeof (AddModFormData));
10198   if (amfp == NULL) return;
10199   w = FixedWindow (-50, -33, -20, -10, "Append to Organism Name",
10200 	StdCloseWindowProc);
10201   SetObjectExtra (w, amfp, StdCleanupFormProc);
10202   amfp->form = (ForM) w;
10203 
10204   amfp->input_entityID = bfp->input_entityID;
10205   amfp->input_itemID = bfp->input_itemID;
10206 
10207   g = HiddenGroup (w, -1, 0, NULL);
10208   SetGroupSpacing (g, 10, 10);
10209 
10210   amfp->modifier_to_add = PopupList (g, TRUE, ChangeModPopup);
10211   for (index=0; index< sizeof (mods_list) / sizeof (AddModListItem); index++)
10212   {
10213     PopupItem (amfp->modifier_to_add, mods_list[index].name);
10214   }
10215   SetObjectExtra (amfp->modifier_to_add, amfp, NULL);
10216   SetValue (amfp->modifier_to_add, 1);
10217 
10218   h = HiddenGroup (g, 1, 0, NULL);
10219   amfp->only_sp = CheckBox (h, "Only append to sp. organisms", NULL);
10220   amfp->only_cf = CheckBox (h, "Only append to cf. organisms", NULL);
10221   amfp->only_aff = CheckBox (h, "Only append to aff. organisms", NULL);
10222   amfp->only_nr = CheckBox (h, "Only append to nr. organisms", NULL);
10223   amfp->no_taxid = CheckBox (h, "Only to organisms with no taxonomy ID", NULL);
10224   amfp->use_abbreviation = CheckBox (h, "Use abbreviation (for example, pv., subsp., etc.)", NULL);
10225   SetStatus (amfp->use_abbreviation, TRUE);
10226   Disable (amfp->use_abbreviation);
10227 
10228   amfp->constraint = FilterGroup (g, FALSE, TRUE, FALSE, FALSE, FALSE, NULL);
10229 
10230   c = HiddenGroup (g, 3, 0, NULL);
10231   b = DefaultButton(c, "Accept", DoAddModToOrg);
10232   SetObjectExtra(b, amfp, NULL);
10233   PushButton (c, "Cancel", StdCancelButtonProc);
10234   amfp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
10235 
10236   AlignObjects (ALIGN_CENTER, (HANDLE) amfp->modifier_to_add,
10237                               (HANDLE) h,
10238                               (HANDLE) amfp->constraint,
10239                               (HANDLE) c, NULL);
10240   RealizeWindow(w);
10241   Show(w);
10242   Update();
10243 }
10244 
10245 
AddModToOrg(IteM i)10246 extern void AddModToOrg (IteM i)
10247 {
10248   BaseFormPtr  bfp;
10249 
10250 #ifdef WIN_MAC
10251   bfp = currentFormDataPtr;
10252 #else
10253   bfp = GetObjectExtra (i);
10254 #endif
10255 
10256   AddModToOrgBaseForm (bfp);
10257 }
10258 
10259 typedef struct descformdata {
10260   FEATURE_FORM_BLOCK
10261 
10262   Uint2          oldEntityID;
10263   Uint4          oldItemID;
10264   Uint2          oldItemtype;
10265   Uint2          lookfor;
10266   Boolean        found;
10267   ObjMgrProcPtr  ompp;
10268   BioseqPtr      bsp;
10269   BioseqSetPtr   bssp;
10270   SeqEntryPtr    sep;
10271   Handle         target;
10272   Boolean        usePopupForTarget;
10273   Boolean        hasMutPopPhySet;
10274   Int2           targetScratchSpace;
10275   Int2           nucProtCount;
10276   Int2           segSetCount;
10277   Uint2          descsubtype;
10278   ButtoN         createNewBtn;
10279   CharPtr        user_object_tag;
10280 } DescFormData, PNTR DescFormPtr;
10281 
10282 
IsUserObjectCorrectTag(UserObjectPtr uop,CharPtr user_object_tag)10283 static Boolean IsUserObjectCorrectTag (UserObjectPtr uop, CharPtr user_object_tag)
10284 {
10285   if (uop == NULL) {
10286     return FALSE;
10287   } else if (user_object_tag == NULL) {
10288     return TRUE;
10289   } else if (StringCmp (uop->type->str, user_object_tag) == 0) {
10290     return TRUE;
10291   } else {
10292     return FALSE;
10293   }
10294 }
10295 
10296 
FindDescrFunc(GatherContextPtr gcp)10297 static Boolean FindDescrFunc (GatherContextPtr gcp)
10298 
10299 {
10300   DescFormPtr  dfp;
10301   ValNodePtr   vnp;
10302 
10303   if (gcp == NULL) return TRUE;
10304   dfp = (DescFormPtr) gcp->userdata;
10305   if (dfp == NULL) return TRUE;
10306   if (gcp->thistype == OBJ_SEQDESC) {
10307     vnp = (ValNodePtr) gcp->thisitem;
10308     if (vnp != NULL && vnp->choice == dfp->lookfor
10309         && (vnp->choice != Seq_descr_user || IsUserObjectCorrectTag(vnp->data.ptrvalue, dfp->user_object_tag))) {
10310       dfp->oldEntityID = gcp->entityID;
10311       dfp->oldItemID = gcp->itemID;
10312       dfp->oldItemtype = gcp->thistype;
10313       dfp->found = TRUE;
10314       return FALSE;
10315     }
10316   }
10317   return TRUE;
10318 }
10319 
10320 static CharPtr segClassList [] = {
10321   " ", "Nucleotide-Protein Set", "Segmented Nucleotide Set",
10322   "conset", "parts", "gibb", "gi", "genbank", "pir", "pub-set",
10323   "equiv", "swissprot", "pdb-entry", "MUTATION SET",
10324   "POPULATION SET", "PHYLOGENETIC SET", "ENVIRONMENTAL SAMPLES",
10325   "genomic product set", "other", NULL
10326 };
10327 
AllButPartsList(SeqEntryPtr sep,Pointer mydata,SeqEntryFunc mycallback,Int4 index,Int2 indent)10328 static Int4 AllButPartsList (SeqEntryPtr sep, Pointer mydata,
10329                              SeqEntryFunc mycallback,
10330                              Int4 index, Int2 indent)
10331 
10332 {
10333   BioseqSetPtr  bssp;
10334 
10335   if (sep == NULL) return index;
10336   if (IS_Bioseq (sep)) {
10337     if (mycallback != NULL)
10338       (*mycallback) (sep, mydata, index, indent);
10339     return index + 1;
10340   }
10341   if (Bioseq_set_class (sep) != 4) {
10342     if (mycallback != NULL)
10343       (*mycallback) (sep, mydata, index, indent);
10344     index++;
10345   }
10346   bssp = (BioseqSetPtr) sep->data.ptrvalue;
10347   sep = bssp->seq_set;
10348   indent++;
10349   while (sep != NULL) {
10350     index = AllButPartsList (sep, mydata, mycallback, index, indent);
10351     sep = sep->next;
10352   }
10353   return index;
10354 }
10355 
10356 #define AllButPartsCount( a )  AllButPartsList( a ,NULL,NULL,0,0);
10357 #define AllButPartsExplore(a,b,c) AllButPartsList(a, b, c, 0L, 0);
10358 
PopTargetProc(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)10359 static void PopTargetProc (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
10360 
10361 {
10362   DescFormPtr   dfp;
10363   BioseqPtr     bsp;
10364   BioseqSetPtr  bssp;
10365   Uint1         _class;
10366   CharPtr       ptr;
10367   SeqIdPtr      sip;
10368   Char          str [128];
10369 
10370   dfp = (DescFormPtr) mydata;
10371   if (sep != NULL && sep->data.ptrvalue != NULL) {
10372     if (sep->choice == 1) {
10373       bsp = (BioseqPtr) sep->data.ptrvalue;
10374       sip = SeqIdFindWorst (bsp->id);
10375       SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str));
10376       ptr = StringChr (str, '|');
10377       if (ptr == NULL) {
10378         ptr = str;
10379       } else {
10380         ptr++;
10381       }
10382       if (dfp->usePopupForTarget) {
10383         PopupItem (dfp->target, ptr);
10384       } else {
10385         ListItem (dfp->target, ptr);
10386       }
10387       if (bsp == dfp->bsp) {
10388         dfp->targetScratchSpace = index + 1;
10389       }
10390     } else if (sep->choice == 2) {
10391       bssp = (BioseqSetPtr) sep->data.ptrvalue;
10392       _class = bssp->_class;
10393       if (_class > 17) {
10394         _class = 18;
10395       }
10396       if (_class == 7 || (IsPopPhyEtcSet (bssp->_class))) {
10397         dfp->hasMutPopPhySet = TRUE;
10398       }
10399       if (! dfp->hasMutPopPhySet) {
10400         sprintf (str, "[%s]", segClassList [_class]);
10401       } else if (_class == 1) {
10402         (dfp->nucProtCount)++;
10403         sprintf (str, "[%s %d]", segClassList [_class], (int) dfp->nucProtCount);
10404         (dfp->segSetCount)++;
10405       } else if (_class == 2) {
10406         sprintf (str, "[%s %d]", segClassList [_class], (int) dfp->segSetCount);
10407       } else {
10408         sprintf (str, "[%s]", segClassList [_class]);
10409       }
10410       if (dfp->usePopupForTarget) {
10411         PopupItem (dfp->target, str);
10412       } else {
10413         ListItem (dfp->target, str);
10414       }
10415     }
10416   }
10417 }
10418 
PopulateTarget(DescFormPtr dfp,BioseqPtr bsp,Uint2 entityID)10419 static Int2 PopulateTarget (DescFormPtr dfp, BioseqPtr bsp, Uint2 entityID)
10420 
10421 {
10422   SeqEntryPtr  sep;
10423   Int2         val;
10424 
10425   val = 0;
10426   if (dfp != NULL) {
10427     if (bsp != NULL) {
10428       sep = SeqMgrGetSeqEntryForData (bsp);
10429       entityID = ObjMgrGetEntityIDForPointer (sep);
10430     }
10431     sep = GetTopSeqEntryForEntityID (entityID);
10432     dfp->sep = sep;
10433     if (sep != NULL) {
10434       dfp->hasMutPopPhySet = FALSE;
10435       dfp->targetScratchSpace = 1;
10436       dfp->nucProtCount = 0;
10437       dfp->segSetCount = 0;
10438       AllButPartsExplore (sep, (Pointer) dfp, PopTargetProc);
10439       val = dfp->targetScratchSpace;
10440     }
10441   }
10442   return val;
10443 }
10444 
FindNewTargetProc(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)10445 static void FindNewTargetProc (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
10446 
10447 {
10448   DescFormPtr   dfp;
10449 
10450   dfp = (DescFormPtr) mydata;
10451   if (sep != NULL && sep->data.ptrvalue != NULL) {
10452     if (index + 1 == dfp->targetScratchSpace) {
10453       if (sep->choice == 1) {
10454         dfp->bsp = (BioseqPtr) sep->data.ptrvalue;
10455       } else if (sep->choice == 2) {
10456         dfp->bssp = (BioseqSetPtr) sep->data.ptrvalue;
10457       }
10458     }
10459   }
10460 }
10461 
ChangeTargetItemID(GatherContextPtr gcp)10462 static Boolean ChangeTargetItemID (GatherContextPtr gcp)
10463 
10464 {
10465   DescFormPtr  dfp;
10466 
10467   if (gcp == NULL) return TRUE;
10468   dfp = (DescFormPtr) gcp->userdata;
10469   if (dfp == NULL) return TRUE;
10470   if (gcp->thistype == OBJ_BIOSEQ) {
10471     if (dfp->bsp == (BioseqPtr) gcp->thisitem) {
10472       dfp->input_entityID = gcp->entityID;
10473       dfp->input_itemID = gcp->itemID;
10474       dfp->input_itemtype = gcp->thistype;
10475       return FALSE;
10476     }
10477   } else if (gcp->thistype == OBJ_BIOSEQSET) {
10478     if (dfp->bssp == (BioseqSetPtr) gcp->thisitem) {
10479       dfp->input_entityID = gcp->entityID;
10480       dfp->input_itemID = gcp->itemID;
10481       dfp->input_itemtype = gcp->thistype;
10482       return FALSE;
10483     }
10484   }
10485   return TRUE;
10486 }
10487 
PreventDupTitleCreation(DescFormPtr dfp)10488 static void PreventDupTitleCreation (DescFormPtr dfp)
10489 
10490 {
10491   ValNodePtr  sdp;
10492 
10493   if (dfp == NULL) return;
10494   if (dfp->bsp != NULL) {
10495     sdp = dfp->bsp->descr;
10496   } else if (dfp->bssp != NULL) {
10497     sdp = dfp->bssp->descr;
10498   } else return;
10499   if (dfp->descsubtype != Seq_descr_title) return;
10500   while (sdp != NULL) {
10501     if (sdp->choice == Seq_descr_title) {
10502       SafeDisable (dfp->createNewBtn);
10503       return;
10504     }
10505     sdp = sdp->next;
10506   }
10507   SafeEnable (dfp->createNewBtn);
10508 }
10509 
ChangeNewDescTarget(Handle obj)10510 static void ChangeNewDescTarget (Handle obj)
10511 
10512 {
10513   DescFormPtr  dfp;
10514   GatherScope  gs;
10515 
10516   dfp = (DescFormPtr) GetObjectExtra (obj);
10517   if (dfp != NULL) {
10518     dfp->bsp = NULL;
10519     dfp->bssp = NULL;
10520     dfp->targetScratchSpace = GetValue (dfp->target);
10521     AllButPartsExplore (dfp->sep, (Pointer) dfp, FindNewTargetProc);
10522     MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
10523     gs.seglevels = 0;
10524     MemSet((Pointer) (gs.ignore), (int) (TRUE), (size_t) (OBJ_MAX * sizeof (Boolean)));
10525     gs.ignore[OBJ_BIOSEQ] = FALSE;
10526     gs.ignore[OBJ_BIOSEQSET] = FALSE;
10527     gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
10528     GatherEntity (dfp->input_entityID, (Pointer) dfp, ChangeTargetItemID, &gs);
10529     PreventDupTitleCreation (dfp);
10530   }
10531 }
10532 
10533 
10534 
CreateNewDescProc(ButtoN b)10535 static void CreateNewDescProc (ButtoN b)
10536 
10537 {
10538   DescFormPtr    dfp;
10539   OMProcControl  ompc;
10540   ObjMgrProcPtr  ompp;
10541   Int2           retval;
10542 
10543   dfp = (DescFormPtr) GetObjectExtra (b);
10544   if (dfp != NULL) {
10545     Hide (dfp->form);
10546     ompp = dfp->ompp;
10547     MemSet ((Pointer) (&ompc), 0, sizeof (OMProcControl));
10548     ompc.input_entityID = dfp->input_entityID;
10549     ompc.input_itemID = dfp->input_itemID;
10550     ompc.input_itemtype = dfp->input_itemtype;
10551     GatherDataForProc (&ompc, FALSE);
10552     ompc.proc = ompp;
10553 
10554     retval = (*(ompp->func)) (&ompc);
10555     if (retval == OM_MSG_RET_ERROR) {
10556       ErrShow ();
10557     }
10558     Update ();
10559     Remove (dfp->form);
10560   }
10561 }
10562 
EditOldDescProc(ButtoN b)10563 static void EditOldDescProc (ButtoN b)
10564 
10565 {
10566   DescFormPtr  dfp;
10567   Int2         handled;
10568 
10569   dfp = (DescFormPtr) GetObjectExtra (b);
10570   if (dfp != NULL) {
10571     Hide (dfp->form);
10572     if (dfp->oldEntityID > 0 && dfp->oldItemID > 0 && dfp->oldItemtype > 0) {
10573       WatchCursor ();
10574       handled = GatherProcLaunch (OMPROC_EDIT, FALSE, dfp->oldEntityID,
10575                                   dfp->oldItemID, dfp->oldItemtype,
10576                                   0, 0, dfp->oldItemtype, 0);
10577       ArrowCursor ();
10578       if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
10579         Message (MSG_ERROR, "Unable to edit existing descriptor.");
10580       }
10581     }
10582     Update ();
10583     Remove (dfp->form);
10584   }
10585 }
10586 
10587 static CharPtr  newDescMsg = "\
10588 Descriptors may apply to a single sequence or to a set of \
10589 sequences.  Please set the target control to the desired \
10590 set or sequence.";
10591 
10592 static CharPtr  editOldMsg = "\
10593 A descriptor of this type already exists at or above the \
10594 displayed target.  You may want to edit it instead of \
10595 creating a new descriptor.";
10596 
NewDescriptorMessageProc(ForM f,Int2 mssg)10597 static void NewDescriptorMessageProc (ForM f, Int2 mssg)
10598 
10599 {
10600   DescFormPtr  dfp;
10601 
10602   dfp = (DescFormPtr) GetObjectExtra (f);
10603   if (dfp != NULL) {
10604     if (dfp->appmessage != NULL) {
10605       dfp->appmessage (f, mssg);
10606     }
10607   }
10608 }
10609 
NewDescriptorMenuFuncEx(ObjMgrProcPtr ompp,BaseFormPtr bfp,Uint2 descsubtype,CharPtr user_object_tag)10610 extern void NewDescriptorMenuFuncEx (ObjMgrProcPtr ompp, BaseFormPtr bfp, Uint2 descsubtype, CharPtr user_object_tag)
10611 
10612 {
10613   ButtoN             b;
10614   BioseqPtr          bsp;
10615   GrouP              c;
10616   Int4               count;
10617   DescFormPtr        dfp;
10618   Uint2              entityID;
10619   GrouP              g;
10620   GatherScope        gs;
10621   GrouP              h;
10622   GrouP              p1, p2;
10623   SeqEntryPtr        sep;
10624   StdEditorProcsPtr  sepp;
10625   SeqIdPtr           sip;
10626   SeqLocPtr          slp;
10627   Int2               val;
10628   WindoW             w;
10629   GrouP              target_grp;
10630 
10631 #ifdef WIN_MAC
10632   bfp = (BaseFormPtr) currentFormDataPtr;
10633 #endif
10634   if (bfp == NULL) return;
10635   if (ompp == NULL || ompp->func == NULL) return;
10636   if (ompp->inputtype != OBJ_SEQDESC) return;
10637   dfp = (DescFormPtr) MemNew (sizeof (DescFormData));
10638   if (dfp == NULL) return;
10639   dfp->ompp = ompp;
10640   dfp->lookfor = ompp->subinputtype;
10641   if (dfp->lookfor == Seq_descr_user) {
10642     dfp->user_object_tag = user_object_tag;
10643   }
10644   dfp->found = FALSE;
10645   dfp->descsubtype = descsubtype;
10646   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
10647   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
10648   gs.seglevels = 0;
10649   gs.get_feats_location = TRUE;
10650   MemSet((Pointer) (gs.ignore), (int) (TRUE), (size_t) (OBJ_MAX * sizeof (Boolean)));
10651   gs.ignore[OBJ_BIOSEQ] = FALSE;
10652   gs.ignore[OBJ_BIOSEQSET] = FALSE;
10653   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
10654   gs.ignore[OBJ_SEQDESC] = FALSE;
10655   if (bsp != NULL) {
10656     slp = ValNodeNew (NULL);
10657     slp->choice = SEQLOC_WHOLE;
10658     sip = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
10659     slp->data.ptrvalue = sip;
10660     gs.target = slp;
10661   }
10662   dfp->bsp = bsp;
10663   GatherEntity (bfp->input_entityID, (Pointer) dfp, FindDescrFunc, &gs);
10664   SeqLocFree (gs.target);
10665   w = FixedWindow (-50, -33, -10, -10, "Descriptor Target Control", StdCloseWindowProc);
10666   SetObjectExtra (w, dfp, StdCleanupFormProc);
10667   dfp->form = (ForM) w;
10668   dfp->formmessage = NewDescriptorMessageProc;
10669 
10670   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
10671   if (sepp != NULL) {
10672     SetActivate (w, sepp->activateForm);
10673     dfp->appmessage = sepp->handleMessages;
10674   }
10675 
10676   dfp->input_entityID = bfp->input_entityID;
10677   dfp->input_itemID = bfp->input_itemID;
10678   dfp->input_itemtype = bfp->input_itemtype;
10679 
10680   h = HiddenGroup (w, -1, 0, NULL);
10681   SetGroupSpacing (h, 10, 10);
10682 
10683   target_grp = HiddenGroup (h, -1, 0, NULL);
10684 
10685   p1 = MultiLinePrompt (target_grp, newDescMsg, 25 * stdCharWidth, programFont);
10686 
10687   entityID = bfp->input_entityID;
10688   if (bsp != NULL) {
10689     sep = SeqMgrGetSeqEntryForData (bsp);
10690     entityID = ObjMgrGetEntityIDForChoice (sep);
10691   }
10692   sep = GetTopSeqEntryForEntityID (entityID);
10693   count = AllButPartsCount (sep);
10694   if (count < 32) {
10695     g = HiddenGroup (target_grp, 2, 0, NULL);
10696     StaticPrompt (g, "Target", 0, popupMenuHeight, programFont, 'l');
10697     dfp->usePopupForTarget = TRUE;
10698     dfp->target = PopupList (g, TRUE, (PupActnProc) ChangeNewDescTarget);
10699   } else {
10700     g = HiddenGroup (target_grp, 0, 2, NULL);
10701     StaticPrompt (g, "Target", 0, 0, programFont, 'c');
10702     dfp->usePopupForTarget = FALSE;
10703     dfp->target = SingleList (g, 14, 3, (LstActnProc) ChangeNewDescTarget);
10704   }
10705   SetObjectExtra (dfp->target, dfp, NULL);
10706   val = PopulateTarget (dfp, bsp, bfp->input_entityID);
10707   SetValue (dfp->target, val);
10708   ChangeNewDescTarget ((Handle) dfp->target);
10709 
10710   AlignObjects (ALIGN_CENTER, (HANDLE) p1, (HANDLE) g, NULL);
10711 
10712   p2 = NULL;
10713   if (dfp->found) {
10714     p2 = MultiLinePrompt (h, editOldMsg, 25 * stdCharWidth, programFont);
10715   }
10716 
10717   c = HiddenGroup (h, 4, 0, NULL);
10718   SetGroupSpacing (c, 10, 2);
10719   dfp->createNewBtn = PushButton (c, "Create New", CreateNewDescProc);
10720   SetObjectExtra (dfp->createNewBtn, dfp, NULL);
10721   if (dfp->found) {
10722     b = DefaultButton (c, "Edit Old", EditOldDescProc);
10723     SetObjectExtra (b, dfp, NULL);
10724   }
10725   PushButton (c, "Cancel", StdCancelButtonProc);
10726 
10727   AlignObjects (ALIGN_CENTER, (HANDLE) target_grp, (HANDLE) c, (HANDLE) p2, NULL);
10728   RealizeWindow (w);
10729   PreventDupTitleCreation (dfp);
10730   Show (w);
10731   Update ();
10732 }
10733 
NewDescriptorMenuFunc(ObjMgrProcPtr ompp,BaseFormPtr bfp,Uint2 descsubtype)10734 extern void NewDescriptorMenuFunc (ObjMgrProcPtr ompp, BaseFormPtr bfp, Uint2 descsubtype)
10735 {
10736   NewDescriptorMenuFuncEx (ompp, bfp, descsubtype, NULL);
10737 }
10738 
10739 
NewDescriptorMenuProc(IteM i)10740 static void NewDescriptorMenuProc (IteM i)
10741 
10742 {
10743   NewObjectPtr  nop;
10744 
10745   nop = (NewObjectPtr) GetObjectExtra (i);
10746   if (nop == NULL) return;
10747   NewDescriptorMenuFunc (nop->ompp, nop->bfp, nop->descsubtype);
10748 }
10749 
10750 
NewDescriptorMenuProcExtra(IteM i)10751 static void NewDescriptorMenuProcExtra (IteM i)
10752 
10753 {
10754   NewObjectPtr  nop;
10755 
10756   nop = (NewObjectPtr) GetObjectExtra (i);
10757   if (nop == NULL) return;
10758   if (nop->blurb == NULL) {
10759     NewDescriptorMenuFunc (nop->ompp, nop->bfp, nop->descsubtype);
10760   } else {
10761     NewDescriptorMenuFuncEx (nop->ompp, nop->bfp, nop->descsubtype, nop->blurb);
10762   }
10763 }
10764 
10765 
SetupNewDescriptorsMenu(MenU m,BaseFormPtr bfp)10766 extern void SetupNewDescriptorsMenu (MenU m, BaseFormPtr bfp)
10767 
10768 {
10769   Boolean        allowgenbank, allow_structured_comment = FALSE;
10770   IteM           i;
10771   NewObjectPtr   nop;
10772   ObjMgrPtr      omp;
10773   ObjMgrProcPtr  ompp;
10774   ObjMgrTypePtr  omtp;
10775 
10776   if (m == NULL) return;
10777   omp = ObjMgrGet ();
10778   if (omp == NULL) return;
10779   ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, 0, 0, NULL);
10780   if (ompp == NULL) return;
10781   omtp = NULL;
10782   allowgenbank = FALSE;
10783 /*#ifdef EXTRA_SERVICES*/
10784   if (extraServices) {
10785     allowgenbank = TRUE;
10786   }
10787 /*#endif*/
10788   if (indexerVersion) {
10789     allow_structured_comment = TRUE;
10790   }
10791 
10792   while ((omtp = ObjMgrTypeFindNext (omp, omtp)) != NULL) {
10793     ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, omtp->datatype, 0, NULL);
10794     if (ompp != NULL) {
10795       switch (omtp->datatype) {
10796         case OBJ_SEQDESC :
10797           ompp = NULL;
10798           while ((ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT,
10799 				  omtp->datatype, 0, ompp)) != NULL) {
10800             if (ompp->subinputtype != Seq_descr_pub) {
10801               if (!allowgenbank && ompp->subinputtype == Seq_descr_genbank) {
10802                 /* skip */
10803               } else if (!allow_structured_comment && ompp->subinputtype == Seq_descr_user && StringCmp (ompp->proclabel, "Structured Comment") == 0) {
10804                 /* skip */
10805               } else if (ompp->subinputtype == Seq_descr_name) {
10806                 /* skip */
10807               } else if (ompp->subinputtype == Seq_descr_region) {
10808                 /* skip */
10809               } else if (ompp->subinputtype == Seq_descr_create_date) {
10810                 /* skip */
10811               } else if (ompp->subinputtype == Seq_descr_update_date) {
10812                 /* skip */
10813               } else if (ompp->subinputtype == Seq_descr_user) {
10814                 if (StringCmp (ompp->proclabel, "GenomeProjectsDB") == 0) {
10815                   /* skip */
10816                 } else {
10817                   i = CommandItem (m, ompp->proclabel, NewDescriptorMenuProcExtra);
10818                   nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
10819                   if (nop != NULL) {
10820                     nop->ompp = ompp;
10821                     nop->bfp = bfp;
10822                     nop->descsubtype = ompp->subinputtype;
10823                     if (StringCmp (ompp->proclabel, "DBLink") == 0) {
10824                       nop->blurb = "DBLink";
10825                     /*
10826                     } else if (StringCmp (ompp->proclabel, "GenomeProjectsDB") == 0) {
10827                       nop->blurb = "GenomeProjectsDB";
10828                     */
10829                     } else if (StringCmp (ompp->proclabel, "Structured Comment") == 0) {
10830                       nop->blurb = "StructuredComment";
10831                     } else if (StringCmp (ompp->proclabel, "TPA Assembly") == 0) {
10832                       nop->blurb = "TpaAssembly";
10833                     } else if (StringCmp (ompp->proclabel, "RefGene Tracking") == 0) {
10834                       nop->blurb = "RefGeneTracking";
10835                     }
10836                   }
10837                   SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);
10838                 }
10839               } else {
10840                 i = CommandItem (m, ompp->proclabel, NewDescriptorMenuProc);
10841                 nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
10842                 if (nop != NULL) {
10843                   nop->ompp = ompp;
10844                   nop->bfp = bfp;
10845                   nop->descsubtype = ompp->subinputtype;
10846                 }
10847                 SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);
10848               }
10849             }
10850           }
10851           break;
10852         default :
10853           break;
10854       }
10855     }
10856   }
10857 }
10858 
10859 static CharPtr  editOldDescMsg = "\
10860 You may really want to edit an existing BioSource descriptor instead.\n\
10861 Proceed anyway?";
10862 
NewFeatureMenuProc(IteM i)10863 static void NewFeatureMenuProc (IteM i)
10864 
10865 {
10866   MsgAnswer      ans;
10867   BaseFormPtr    bfp;
10868   NewObjectPtr   nop;
10869   OMProcControl  ompc;
10870   ObjMgrProcPtr  ompp;
10871   Int2           retval;
10872 
10873   nop = (NewObjectPtr) GetObjectExtra (i);
10874   if (nop == NULL) return;
10875 #ifdef WIN_MAC
10876   bfp = (BaseFormPtr) currentFormDataPtr;
10877 #else
10878   bfp = nop->bfp;
10879 #endif
10880   if (bfp == NULL) return;
10881   ompp = nop->ompp;
10882   if (ompp == NULL || ompp->func == NULL) return;
10883   if (ompp->subinputtype == FEATDEF_BIOSRC) {
10884     ans = Message (MSG_YN, editOldDescMsg);
10885     if (ans == ANS_NO) return;
10886   }
10887   MemSet ((Pointer) (&ompc), 0, sizeof (OMProcControl));
10888   ompc.input_entityID = bfp->input_entityID;
10889   ompc.input_itemID = bfp->input_itemID;
10890   ompc.input_itemtype = bfp->input_itemtype;
10891   GatherDataForProc (&ompc, FALSE);
10892   ompc.proc = ompp;
10893   retval = (*(ompp->func)) (&ompc);
10894   if (retval == OM_MSG_RET_ERROR) {
10895     ErrShow ();
10896   }
10897 }
10898 
10899 #ifdef WIN_MAC
10900 VoidPtr macUserDataPtr = NULL;
10901 #endif
10902 
EnableFeaturesPerTarget(BaseFormPtr bfp)10903 extern void EnableFeaturesPerTarget (BaseFormPtr bfp)
10904 
10905 {
10906   BioseqPtr     bsp;
10907   Uint1         mol;
10908   NewObjectPtr  nop;
10909 
10910   if (bfp == NULL) return;
10911 #ifdef WIN_MAC
10912   nop = (NewObjectPtr) macUserDataPtr;
10913 #else
10914   nop = (NewObjectPtr) bfp->userDataPtr;
10915 #endif
10916   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
10917   mol = 0;
10918   if (bsp != NULL) {
10919     mol = bsp->mol;
10920   }
10921   while (nop != NULL) {
10922     if (nop->kind == 2) {
10923       /* analysis menu item, ignore it */
10924     } else if (mol == 0) {
10925       SafeDisable (nop->item);
10926     } else if (ISA_na (mol) && (nop->molgroup == 2 || nop->molgroup == 3)) {
10927       SafeEnable (nop->item);
10928     } else if (ISA_aa (mol) && (nop->molgroup == 1 || nop->molgroup == 3)) {
10929       SafeEnable (nop->item);
10930     } else {
10931       SafeDisable (nop->item);
10932     }
10933     nop = nop->next;
10934   }
10935 }
10936 
LinkNewObjectLists(NewObjectPtr list1,NewObjectPtr list2)10937 static VoidPtr LinkNewObjectLists (NewObjectPtr list1, NewObjectPtr list2)
10938 
10939 {
10940   NewObjectPtr  nop;
10941 
10942   if (list1 == NULL) return list2;
10943   nop = list1;
10944   while (nop->next != NULL) {
10945     nop = nop->next;
10946   }
10947   nop->next = list2;
10948   return list1;
10949 }
10950 
10951 
IsUnwantedFeatureType(Uint1 key)10952 extern Boolean IsUnwantedFeatureType (Uint1 key)
10953 {
10954 #if 1
10955   return FALSE;
10956 #else
10957   if (key == FEATDEF_satellite || key == FEATDEF_repeat_unit) {
10958     return TRUE;
10959   } else {
10960     return FALSE;
10961   }
10962 #endif
10963 }
10964 
10965 
SetupNewFeaturesMenu(MenU m,BaseFormPtr bfp)10966 extern void SetupNewFeaturesMenu (MenU m, BaseFormPtr bfp)
10967 
10968 {
10969   FeatDispGroupPtr  fdgp;
10970   FeatDefPtr        fdp;
10971   NewObjectPtr      first;
10972   IteM              i;
10973   Uint1             key;
10974   CharPtr           label;
10975   NewObjectPtr      last;
10976   NewObjectPtr      nop;
10977   ObjMgrPtr         omp;
10978   ObjMgrProcPtr     ompp;
10979   ObjMgrTypePtr     omtp;
10980   MenU              sub;
10981   Uint2             subtype;
10982 
10983   if (m == NULL) return;
10984   omp = ObjMgrGet ();
10985   if (omp == NULL) return;
10986   ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, 0, 0, NULL);
10987   if (ompp == NULL) return;
10988   omtp = NULL;
10989   first = NULL;
10990   last = NULL;
10991   while ((omtp = ObjMgrTypeFindNext (omp, omtp)) != NULL) {
10992     ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, omtp->datatype, 0, NULL);
10993     if (ompp != NULL) {
10994       switch (omtp->datatype) {
10995         case OBJ_SEQFEAT :
10996           fdgp = NULL;
10997           while ((fdgp = DispGroupFindNext (fdgp, &key, &label)) != NULL) {
10998             if (fdgp->groupkey != 0) {
10999               sub = SubMenu (m, fdgp->groupname);
11000               fdp = NULL;
11001               label = NULL;
11002               while ((fdp = FeatDefFindNext (fdp, &key, &label,
11003                      fdgp->groupkey, FALSE)) != NULL) {
11004                 if (key != FEATDEF_BAD && key != FEATDEF_repeat_unit && key != FEATDEF_LTR) {
11005                   ompp = NULL;
11006                   while ((ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT,
11007 				          omtp->datatype, 0, ompp)) != NULL) {
11008                     if (ompp->subinputtype == fdp->featdef_key &&
11009                         ompp->subinputtype != FEATDEF_PUB &&
11010                         !IsRegulatorySubtype(ompp->subinputtype)) {
11011                       i = CommandItem (sub, ompp->proclabel, NewFeatureMenuProc);
11012                       nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
11013                       if (nop != NULL) {
11014                         nop->kind = 1; /* feature creation item */
11015                         nop->ompp = ompp;
11016                         nop->bfp = bfp;
11017                         nop->item = i;
11018                         nop->molgroup = fdp->molgroup;
11019                       }
11020                       if (first == NULL) {
11021                         first = nop;
11022                       }
11023                       if (last != NULL) {
11024                         last->next = nop;
11025                       }
11026                       last = nop;
11027                       SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);
11028                     }
11029                   }
11030                 }
11031               }
11032             }
11033           }
11034           /* if (indexerVersion) { */
11035             sub = SubMenu (m, "Remaining Features");
11036             fdp = NULL;
11037             label = NULL;
11038             while ((fdp = FeatDefFindNext (fdp, &key, &label, 0, FALSE)) != NULL) {
11039               if (key != FEATDEF_BAD && !IsUnwantedFeatureType(key)) {
11040                 ompp = NULL;
11041                 while ((ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT,
11042 				                                           omtp->datatype, 0, ompp)) != NULL) {
11043 				          subtype = ompp->subinputtype;
11044                   if (subtype == fdp->featdef_key && OkToListFeatDefInRemainingFeatures (subtype)) {
11045                     i = CommandItem (sub, ompp->proclabel, NewFeatureMenuProc);
11046                     nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
11047                     if (nop != NULL) {
11048                       nop->kind = 1; /* feature creation item */
11049                       nop->ompp = ompp;
11050                       nop->bfp = bfp;
11051                       nop->item = i;
11052                       nop->molgroup = fdp->molgroup;
11053                     }
11054                     if (first == NULL) {
11055                       first = nop;
11056                     }
11057                     if (last != NULL) {
11058                       last->next = nop;
11059                     }
11060                     last = nop;
11061                     SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);
11062                   }
11063                 }
11064               }
11065             }
11066           /* } */
11067           break;
11068         default :
11069           break;
11070       }
11071     }
11072   }
11073 #ifdef WIN_MAC
11074   macUserDataPtr = LinkNewObjectLists (macUserDataPtr, first);
11075 #else
11076   bfp->userDataPtr = LinkNewObjectLists (bfp->userDataPtr, first);
11077 #endif
11078 }
11079 
SetupNewPublicationsMenu(MenU m,BaseFormPtr bfp)11080 extern void SetupNewPublicationsMenu (MenU m, BaseFormPtr bfp)
11081 
11082 {
11083   NewObjectPtr   first;
11084   IteM           i;
11085   NewObjectPtr   nop;
11086   ObjMgrPtr      omp;
11087   ObjMgrProcPtr  ompp;
11088   ObjMgrTypePtr  omtp;
11089 
11090   if (m == NULL) return;
11091   omp = ObjMgrGet ();
11092   if (omp == NULL) return;
11093   ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, 0, 0, NULL);
11094   if (ompp == NULL) return;
11095   omtp = NULL;
11096   while ((omtp = ObjMgrTypeFindNext (omp, omtp)) != NULL) {
11097     ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, omtp->datatype, 0, NULL);
11098     if (ompp != NULL) {
11099       switch (omtp->datatype) {
11100         case OBJ_SEQFEAT :
11101             ompp = NULL;
11102             while ((ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT,
11103 				    omtp->datatype, 0, ompp)) != NULL) {
11104               if (ompp->subinputtype == FEATDEF_PUB) {
11105                 i = CommandItem (m, "Publication Feature", NewFeatureMenuProc);
11106                 nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
11107                 if (nop != NULL) {
11108                   nop->kind = 1; /* feature creation item */
11109                   nop->ompp = ompp;
11110                   nop->bfp = bfp;
11111                   nop->item = i;
11112                   nop->molgroup = 3;
11113 #ifdef WIN_MAC
11114                   first = (NewObjectPtr) macUserDataPtr;
11115 #else
11116                   first = (NewObjectPtr) bfp->userDataPtr;
11117 #endif
11118                   if (first != NULL) {
11119                     while (first->next != NULL) {
11120                       first = first->next;
11121                     }
11122                     first->next = nop;
11123                   }
11124                 }
11125                 SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);
11126               }
11127             }
11128           break;
11129         case OBJ_SEQDESC :
11130           ompp = NULL;
11131           while ((ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT,
11132 				  omtp->datatype, 0, ompp)) != NULL) {
11133             if (ompp->subinputtype == Seq_descr_pub) {
11134               i = CommandItem (m, "Publication Descriptor", NewDescriptorMenuProc);
11135               nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
11136               if (nop != NULL) {
11137                 nop->ompp = ompp;
11138                 nop->bfp = bfp;
11139               }
11140               SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);
11141             }
11142           }
11143           break;
11144         default :
11145           break;
11146       }
11147     }
11148   }
11149 }
11150 
11151 #ifdef WIN_MAC
11152 extern IteM  addSecondaryItem;
11153 #endif
11154 
SetupEditSecondary(MenU m,BaseFormPtr bfp)11155 extern void SetupEditSecondary (MenU m, BaseFormPtr bfp)
11156 
11157 {
11158   IteM           i;
11159   NewObjectPtr   nop;
11160   ObjMgrPtr      omp;
11161   ObjMgrProcPtr  ompp;
11162   ObjMgrTypePtr  omtp;
11163 
11164   if (m == NULL) return;
11165   omp = ObjMgrGet ();
11166   if (omp == NULL) return;
11167   ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, 0, 0, NULL);
11168   if (ompp == NULL) return;
11169   omtp = NULL;
11170   while ((omtp = ObjMgrTypeFindNext (omp, omtp)) != NULL) {
11171     ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, omtp->datatype, 0, NULL);
11172     if (ompp != NULL) {
11173       switch (omtp->datatype) {
11174         case OBJ_SEQDESC :
11175           ompp = NULL;
11176           while ((ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT,
11177 				  omtp->datatype, 0, ompp)) != NULL) {
11178             if (ompp->subinputtype != Seq_descr_pub) {
11179               if (ompp->subinputtype == Seq_descr_genbank) {
11180                 i = CommandItem (m, "Add Secondary", NewDescriptorMenuProc);
11181                 nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
11182                 if (nop != NULL) {
11183                   nop->ompp = ompp;
11184                   nop->bfp = bfp;
11185                 }
11186                 SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);
11187 #ifdef WIN_MAC
11188                 if (addSecondaryItem == NULL) {
11189                   addSecondaryItem = i;
11190                 }
11191 #endif
11192                 return;
11193               }
11194             }
11195           }
11196           break;
11197         default :
11198           break;
11199       }
11200     }
11201   }
11202 }
11203 
11204 typedef struct gbformdata {
11205   FEATURE_FORM_BLOCK
11206 
11207   ButtoN         clearExtraAccns;
11208   ButtoN         clearSource;
11209   ButtoN         clearKeywords;
11210   ButtoN         clearOrigin;
11211   ButtoN         clearOldDate;
11212   ButtoN         clearEntryDate;
11213   ButtoN         clearDivision;
11214   ButtoN         clearTaxonomy;
11215 } GbeditFormData, PNTR GbeditFormPtr;
11216 
EditGenbankCallback(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)11217 static void EditGenbankCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
11218 
11219 {
11220   BioseqPtr      bsp;
11221   BioseqSetPtr   bssp;
11222   Boolean        empty;
11223   GBBlockPtr     gbp;
11224   GbeditFormPtr  gfp;
11225   ValNodePtr     nextsdp;
11226   Pointer PNTR   prevsdp;
11227   ValNodePtr     sdp;
11228 
11229   if (mydata == NULL) return;
11230   if (sep == NULL || sep->data.ptrvalue == NULL) return;
11231   gfp = (GbeditFormPtr) mydata;
11232   if (gfp == NULL) return;
11233   if (IS_Bioseq (sep)) {
11234     bsp = (BioseqPtr) sep->data.ptrvalue;
11235     sdp = bsp->descr;
11236     prevsdp = (Pointer PNTR) &(bsp->descr);
11237   } else if (IS_Bioseq_set (sep)) {
11238     bssp = (BioseqSetPtr) sep->data.ptrvalue;
11239     sdp = bssp->descr;
11240     prevsdp = (Pointer PNTR) &(bssp->descr);
11241   } else return;
11242   while (sdp != NULL) {
11243     nextsdp = sdp->next;
11244     empty = FALSE;
11245     if (sdp->choice == Seq_descr_genbank && sdp->data.ptrvalue != NULL) {
11246       gbp = (GBBlockPtr) sdp->data.ptrvalue;
11247       if (GetStatus (gfp->clearExtraAccns)) {
11248         gbp->extra_accessions = ValNodeFreeData (gbp->extra_accessions);
11249       }
11250       if (GetStatus (gfp->clearSource)) {
11251         gbp->source = MemFree (gbp->source);
11252       }
11253       if (GetStatus (gfp->clearKeywords)) {
11254         gbp->keywords = ValNodeFreeData (gbp->keywords);
11255       }
11256       if (GetStatus (gfp->clearOrigin)) {
11257         gbp->origin = MemFree (gbp->origin);
11258       }
11259       if (GetStatus (gfp->clearOldDate)) {
11260         gbp->date = MemFree (gbp->date);
11261       }
11262       if (GetStatus (gfp->clearEntryDate)) {
11263         gbp->entry_date = DateFree (gbp->entry_date);
11264       }
11265       if (GetStatus (gfp->clearDivision)) {
11266         gbp->div = MemFree (gbp->div);
11267       }
11268       if (GetStatus (gfp->clearTaxonomy)) {
11269         gbp->taxonomy = MemFree (gbp->taxonomy);
11270       }
11271       if (gbp->extra_accessions == NULL && gbp->source == NULL &&
11272           gbp->keywords == NULL && gbp->origin == NULL &&
11273           gbp->date == NULL && gbp->entry_date == NULL &&
11274           gbp->div == NULL && gbp->taxonomy == NULL) {
11275         empty = TRUE;
11276         ObjMgrDeSelect (0, 0, 0, 0, NULL);
11277       }
11278     }
11279     if (empty) {
11280       *(prevsdp) = sdp->next;
11281       sdp->next = NULL;
11282       SeqDescFree (sdp);
11283     } else {
11284       prevsdp = (Pointer PNTR) &(sdp->next);
11285     }
11286     sdp = nextsdp;
11287   }
11288 }
11289 
DoEditGenbank(ButtoN b)11290 static void DoEditGenbank (ButtoN b)
11291 
11292 {
11293   GbeditFormPtr  gfp;
11294   SeqEntryPtr    sep;
11295 
11296   gfp = GetObjectExtra (b);
11297   if (gfp == NULL) return;
11298   sep = GetTopSeqEntryForEntityID (gfp->input_entityID);
11299   if (sep == NULL) return;
11300   Hide (gfp->form);
11301   WatchCursor ();
11302   Update ();
11303   SeqEntryExplore (sep, (Pointer) gfp, EditGenbankCallback);
11304   ArrowCursor ();
11305   Update ();
11306   ObjMgrSetDirtyFlag (gfp->input_entityID, TRUE);
11307   ObjMgrSendMsg (OM_MSG_UPDATE, gfp->input_entityID, 0, 0);
11308   Remove (gfp->form);
11309 }
11310 
EditGenbankMessageProc(ForM f,Int2 mssg)11311 static void EditGenbankMessageProc (ForM f, Int2 mssg)
11312 
11313 {
11314   GbeditFormPtr  gfp;
11315 
11316   gfp = (GbeditFormPtr) GetObjectExtra (f);
11317   if (gfp != NULL) {
11318     if (gfp->appmessage != NULL) {
11319       gfp->appmessage (f, mssg);
11320     }
11321   }
11322 }
11323 
EditGenbankElements(Handle i)11324 extern void EditGenbankElements (Handle i)
11325 
11326 {
11327   BaseFormPtr        bfp;
11328   ButtoN             b;
11329   GrouP              c;
11330   GrouP              g;
11331   GbeditFormPtr      gfp;
11332   GrouP              h;
11333   SeqEntryPtr        sep;
11334   StdEditorProcsPtr  sepp;
11335   WindoW             w;
11336 
11337 #ifdef WIN_MAC
11338   bfp = currentFormDataPtr;
11339 #else
11340   bfp = GetObjectExtra (i);
11341 #endif
11342   if (bfp == NULL) return;
11343   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
11344   if (sep == NULL) return;
11345   gfp = (GbeditFormPtr) MemNew (sizeof (GbeditFormData));
11346   if (gfp == NULL) return;
11347   w = FixedWindow (-50, -33, -10, -10, "GenBank Block Removal", StdCloseWindowProc);
11348   SetObjectExtra (w, gfp, StdCleanupFormProc);
11349   gfp->form = (ForM) w;
11350   gfp->formmessage = EditGenbankMessageProc;
11351 
11352   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
11353   if (sepp != NULL) {
11354     SetActivate (w, sepp->activateForm);
11355     gfp->appmessage = sepp->handleMessages;
11356   }
11357 
11358   gfp->input_entityID = bfp->input_entityID;
11359   gfp->input_itemID = bfp->input_itemID;
11360   gfp->input_itemtype = bfp->input_itemtype;
11361 
11362   h = HiddenGroup (w, -1, 0, NULL);
11363   SetGroupSpacing (h, 10, 10);
11364 
11365   g = HiddenGroup (h, -1, 0, NULL);
11366 
11367   gfp->clearExtraAccns = CheckBox (g, "Clear Secondary Accessions", NULL);
11368   gfp->clearSource = CheckBox (g, "Clear Source Line", NULL);
11369   gfp->clearKeywords = CheckBox (g, "Clear Keywords", NULL);
11370   gfp->clearOrigin = CheckBox (g, "Clear Origin", NULL);
11371   gfp->clearOldDate = CheckBox (g, "Clear Old Date", NULL);
11372   gfp->clearEntryDate = CheckBox (g, "Clear Entry Date", NULL);
11373   gfp->clearDivision = CheckBox (g, "Clear Division", NULL);
11374   gfp->clearTaxonomy = CheckBox (g, "Clear Lineage", NULL);
11375 
11376   c = HiddenGroup (h, 4, 0, NULL);
11377   b = DefaultButton (c, "Accept", DoEditGenbank);
11378   SetObjectExtra (b, gfp, NULL);
11379   PushButton (c, "Cancel", StdCancelButtonProc);
11380 
11381   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
11382   RealizeWindow (w);
11383   Show (w);
11384   Update ();
11385 }
11386 
11387 typedef struct helpindex {
11388   Int2           item;
11389   CharPtr        heading;
11390   CharPtr        section;
11391   CharPtr        combined;
11392 } HelpIndex, PNTR HelpIndexPtr;
11393 
11394 typedef struct helpform {
11395   FORM_MESSAGE_BLOCK
11396   DoC            doc;
11397   DoC            list;
11398   TexT           findTxt;
11399   ButtoN         findBtn;
11400   GrouP          dismissGrp;
11401   ValNodePtr     mainStrings;
11402   ValNodePtr     indexStrings;
11403   ValNodePtr     index;
11404   Char           file [PATH_MAX];
11405 } HelpForm, PNTR HelpFormPtr;
11406 
11407 #define TBL_FMT 1
11408 #define TXT_FMT 2
11409 #define HDG_FMT 3
11410 #define SUB_FMT 4  /* and beyond, encoding indent */
11411 
11412 static ParData lstParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
11413 static ColData lstColFmt = {0, 0, 80, 0, NULL, 'l', FALSE, FALSE, FALSE, FALSE, TRUE};
11414 
11415 static ParData hdgParFmt = {TRUE, FALSE, FALSE, FALSE, FALSE, 0, 0};
11416 static ColData hdgColFmt = {0, 0, 80, 0, NULL, 'c', TRUE, FALSE, FALSE, FALSE, TRUE};
11417 
11418 static ParData subParFmt = {TRUE, FALSE, FALSE, FALSE, FALSE, 0, 0};
11419 static ColData subColFmt = {0, 0, 80, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE};
11420 
11421 static ParData tblParFmt = {TRUE, FALSE, FALSE, FALSE, TRUE, 0, 0};
11422 static ColData tblColFmt = {0, 0, 80, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE};
11423 
11424 static ParData txtParFmt = {TRUE, FALSE, FALSE, FALSE, FALSE, 0, 0};
11425 static ColData txtColFmt = {0, 0, 80, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE};
11426 
ResetHelpLists(HelpFormPtr hfp)11427 static void ResetHelpLists (HelpFormPtr hfp)
11428 
11429 {
11430   HelpIndexPtr  hip;
11431   ValNodePtr    vnp;
11432 
11433   if (hfp != NULL) {
11434     hfp->mainStrings = ValNodeFreeData (hfp->mainStrings);
11435     hfp->indexStrings = ValNodeFreeData (hfp->indexStrings);
11436     vnp = hfp->index;
11437     while (vnp != NULL) {
11438       hip = (HelpIndexPtr) vnp->data.ptrvalue;
11439       if (hip != NULL) {
11440         hip->heading = MemFree (hip->heading);
11441         hip->section = MemFree (hip->section);
11442         hip->combined = MemFree (hip->combined);
11443       }
11444       vnp = vnp->next;
11445     }
11446     hfp->index = ValNodeFreeData (hfp->index);
11447   }
11448 }
11449 
TrimTrailingSpaces(CharPtr str)11450 static void TrimTrailingSpaces (CharPtr str)
11451 
11452 {
11453   size_t  len;
11454 
11455   if (str != NULL && str [0] != '\0') {
11456     len = StringLen (str);
11457     while (len > 0 && str [len - 1] == ' ') {
11458       len--;
11459     }
11460     str [len] = '\0';
11461   }
11462 }
11463 
ParseHelpFile(HelpFormPtr hfp,Boolean printPath)11464 static Boolean ParseHelpFile (HelpFormPtr hfp, Boolean printPath)
11465 
11466 {
11467   Char          ch;
11468   Uint1         choice;
11469   FileCache     fc;
11470   FILE          *fp;
11471   Boolean       goOn;
11472   Char          heading [512];
11473   HelpIndexPtr  hip;
11474   Boolean       inTable;
11475   Int2          level;
11476   ValNodePtr    list;
11477   Int2          numItems;
11478   Char          path [PATH_MAX];
11479   CharPtr       ptr;
11480   Char          section [512];
11481   Char          str [512];
11482   ValNodePtr    vnp;
11483 
11484   if (hfp == NULL || hfp->doc == NULL) return FALSE;
11485   Hide (hfp->list);
11486   Hide (hfp->doc);
11487   Update ();
11488   Reset (hfp->list);
11489   Reset (hfp->doc);
11490   ResetHelpLists (hfp);
11491   if (hfp->file == NULL || hfp->file [0] == '\0') return FALSE;
11492   numItems = 0;
11493   ProgramPath (path, sizeof (path));
11494   ptr = StringRChr (path, DIRDELIMCHR);
11495   if (ptr != NULL) {
11496     *ptr = '\0';
11497   }
11498   FileBuildPath (path, NULL, hfp->file);
11499   fp = FileOpen (path, "r");
11500   if (fp == NULL) {
11501     if (GetAppParam ("NCBI", "ErrorProcessing", "MsgPath", NULL, path, sizeof (path))) {
11502       FileBuildPath (path, NULL, hfp->file);
11503       fp = FileOpen (path, "r");
11504     }
11505   }
11506   if (fp == NULL) {
11507     if (GetAppParam ("NCBI", "NCBI", "DATA", NULL, path, sizeof (path))) {
11508       FileBuildPath (path, NULL, hfp->file);
11509       fp = FileOpen (path, "r");
11510     }
11511   }
11512   if (fp != NULL) {
11513     if (printPath) {
11514       SetTitle (hfp->form, path);
11515     }
11516     list = NULL;
11517     heading [0] = '\0';
11518     section [0] = '\0';
11519     inTable = FALSE;
11520     if (! FileCacheSetup (&fc, fp)) return FALSE;
11521     goOn = (FileCacheGetString (&fc, str, sizeof (str)) != NULL);
11522     while (goOn) {
11523       ptr = str;
11524       ch = *ptr;
11525       while (ch != '\n' && ch != '\r' && ch != '\0') {
11526         ptr++;
11527         ch = *ptr;
11528       }
11529       *ptr = '\0';
11530       if (inTable) {
11531         TrimTrailingSpaces (str);
11532       } else {
11533         TrimSpacesAroundString (str);
11534       }
11535       ch = str [0];
11536       if (ch == '>' || ch == '*' || ch == '#' || ch == '!') {
11537         if (list != NULL) {
11538           ptr = MergeValNodeStrings (list, inTable);
11539           if (inTable) {
11540             choice = TBL_FMT;
11541           } else {
11542             choice = TXT_FMT;
11543           }
11544           numItems++;
11545           vnp = ValNodeAdd (&(hfp->mainStrings));
11546           if (vnp != NULL) {
11547             vnp->choice = choice;
11548             vnp->data.ptrvalue = ptr;
11549           }
11550           /* ptr = MemFree (ptr); */
11551           list = ValNodeFreeData (list);
11552         }
11553         ch = str [0];
11554         if (ch == '>') {
11555           StringNCpy_0 (heading, str + 1, sizeof (heading));
11556           numItems++;
11557           vnp = ValNodeAdd (&(hfp->mainStrings));
11558           if (vnp != NULL) {
11559             vnp->choice = HDG_FMT;
11560             vnp->data.ptrvalue = StringSave (heading);
11561           }
11562           vnp = ValNodeAdd (&(hfp->indexStrings));
11563           if (vnp != NULL) {
11564             vnp->choice = 0;
11565             vnp->data.ptrvalue = StringSave (heading);
11566           }
11567           vnp = ValNodeAdd (&(hfp->index));
11568           if (vnp != NULL) {
11569             hip = (HelpIndexPtr) MemNew (sizeof (HelpIndex));
11570             vnp->data.ptrvalue = (Pointer) hip;
11571             if (hip != NULL) {
11572               hip->item = numItems;
11573               hip->heading = StringSave (heading);
11574             }
11575           }
11576         } else if (ch == '*') {
11577           level = 1;
11578           ch = str [level];
11579           while (ch == '*') {
11580             level++;
11581             ch = str [level];
11582           }
11583           StringNCpy_0 (section, str + level, sizeof (section));
11584           numItems++;
11585           vnp = ValNodeAdd (&(hfp->mainStrings));
11586           if (vnp != NULL) {
11587             if (level < 2) {
11588               vnp->choice = SUB_FMT;
11589             } else {
11590               vnp->choice = 5 * (level - 1);
11591             }
11592             vnp->data.ptrvalue = StringSave (section);
11593           }
11594           vnp = ValNodeAdd (&(hfp->indexStrings));
11595           if (vnp != NULL) {
11596             vnp->choice = 5 * level;
11597             vnp->data.ptrvalue = StringSave (section);
11598           }
11599           vnp = ValNodeAdd (&(hfp->index));
11600           if (vnp != NULL) {
11601             hip = (HelpIndexPtr) MemNew (sizeof (HelpIndex));
11602             vnp->data.ptrvalue = (Pointer) hip;
11603             if (hip != NULL) {
11604               hip->item = numItems;
11605               hip->heading = StringSave (heading);
11606               hip->section = StringSave (section);
11607               sprintf (str, "%s|%s", heading, section);
11608               hip->combined = StringSave (str);
11609             }
11610           }
11611         } else if (ch == '#' || ch == '!') {
11612           inTable = (Boolean) (ch == '!');
11613           vnp = ValNodeAdd (&list);
11614           if (vnp != NULL) {
11615             if (! StringHasNoText (str + 1)) {
11616               vnp->data.ptrvalue = StringSave (str + 1);
11617             }
11618           }
11619         }
11620       } else if (ch == '<') {
11621       } else if (ch != '\0') {
11622         vnp = ValNodeAdd (&list);
11623         if (vnp != NULL) {
11624           if (! StringHasNoText (str)) {
11625             vnp->data.ptrvalue = StringSave (str);
11626           }
11627         }
11628       }
11629       goOn = (Boolean) (goOn && (FileCacheGetString (&fc, str, sizeof (str)) != NULL));
11630     }
11631     if (list != NULL) {
11632       ptr = MergeValNodeStrings (list, inTable);
11633       if (inTable) {
11634         choice = TBL_FMT;
11635       } else {
11636         choice = TXT_FMT;
11637       }
11638       numItems++;
11639       vnp = ValNodeAdd (&(hfp->mainStrings));
11640       if (vnp != NULL) {
11641         vnp->choice = choice;
11642         vnp->data.ptrvalue = ptr;
11643       }
11644       /* ptr = MemFree (ptr); */
11645       list = ValNodeFreeData (list);
11646     }
11647     FileClose (fp);
11648     return TRUE;
11649   } else {
11650     return FALSE;
11651   }
11652 }
11653 
GetHelpFontFromConfig(CharPtr param,FonT dfault)11654 static FonT GetHelpFontFromConfig (CharPtr param, FonT dfault)
11655 
11656 {
11657   FonT  f;
11658   Char  str [128];
11659 
11660   f = dfault;
11661   if (GetSequinAppParam ("SCREEN", param, NULL, str, sizeof (str))) {
11662     f = Nlm_ParseFontEx (str, NULL);
11663   }
11664   if (f == NULL) {
11665     f = dfault;
11666   }
11667   return f;
11668 }
11669 
SetupHelpFonts(void)11670 static void SetupHelpFonts (void)
11671 
11672 {
11673   if (IsJapanese()) {
11674 #ifdef WIN_MAC
11675     /* Osaka is common font for Japanese on Macintosh. */
11676     hdgColFmt.font = Nlm_ParseFontEx ("Osaka,14,b", NULL);
11677     subColFmt.font = Nlm_ParseFontEx ("Osaka,10,b", NULL);
11678     txtColFmt.font = Nlm_ParseFontEx ("Osaka,10", NULL);
11679     lstColFmt.font = Nlm_ParseFontEx ("Osaka\x81\x7c\x93\x99\x95\x9d,12", NULL);
11680     tblColFmt.font = Nlm_ParseFontEx ("Osaka\x81\x7c\x93\x99\x95\x9d,12", NULL);
11681 /*    hdgColFmt.font = GetResidentFont (Nlm_Minchou(14, STYLE_BOLD));	*/
11682 /*    subColFmt.font = GetResidentFont (Nlm_Minchou(10, STYLE_BOLD));	*/
11683 /*    txtColFmt.font = GetResidentFont (Nlm_Gothic(10, STYLE_REGULAR));	*/
11684 /*    lstColFmt.font = GetResidentFont (Nlm_MinchouFixed(12, STYLE_REGULAR));	*/
11685 /*    tblColFmt.font = GetResidentFont (Nlm_MinchouFixed(12, STYLE_REGULAR));	*/
11686 #endif
11687 #ifdef WIN_MSWIN
11688     hdgColFmt.font = Nlm_ParseFontEx ("\x82\x6c\x82\x72\x20\x82\x6f\x96\xbe\x92\xa9,14,b,Kanji", NULL);
11689     subColFmt.font = Nlm_ParseFontEx ("\x82\x6c\x82\x72\x20\x82\x6f\x96\xbe\x92\xa9,11,b,Kanji", NULL);
11690     txtColFmt.font = Nlm_ParseFontEx ("\x82\x6c\x82\x72\x20\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e,11,,Kanji", NULL);
11691     lstColFmt.font = Nlm_ParseFontEx ("\x82\x6c\x82\x72\x20\x96\xbe\x92\xa9,12,f,Kanji", NULL);
11692     tblColFmt.font = Nlm_ParseFontEx ("\x82\x6c\x82\x72\x20\x96\xbe\x92\xa9,12,f,Kanji", NULL);
11693 /*    hdgColFmt.font = GetResidentFont (Nlm_Minchou(14, STYLE_BOLD));	*/
11694 /*    subColFmt.font = GetResidentFont (Nlm_Minchou(11, STYLE_BOLD));	*/
11695 /*    txtColFmt.font = GetResidentFont (Nlm_Gothic(11, STYLE_REGULAR));	*/
11696 /*    lstColFmt.font = GetResidentFont (Nlm_MinchouFixed(12, STYLE_REGULAR));	*/
11697 /*    tblColFmt.font = GetResidentFont (Nlm_MinchouFixed(12, STYLE_REGULAR));	*/
11698 #endif
11699 #ifdef WIN_MOTIF
11700     hdgColFmt.font = ParseFont ("Times,18,b");
11701     subColFmt.font = ParseFont ("Helvetica,12,b");
11702     txtColFmt.font = ParseFont ("fixed,13");
11703     lstColFmt.font = programFont;
11704     tblColFmt.font = programFont;
11705 #endif
11706   } else if (IsEnglish() || IsFrench() || IsGerman() || IsItalian() || IsSystemLang()) {
11707 #ifdef WIN_MAC
11708     hdgColFmt.font = ParseFont ("Times,14,b");
11709     subColFmt.font = ParseFont ("Geneva,10,b");
11710     txtColFmt.font = ParseFont ("Geneva,10");
11711 #endif /*WIN_MAC*/
11712 #ifdef WIN_MSWIN
11713     hdgColFmt.font = ParseFont ("Times New Roman,14,b");
11714     subColFmt.font = ParseFont ("Arial,11,b");
11715     txtColFmt.font = ParseFont ("Times New Roman,11");
11716 #endif /*WIN_MSWIN*/
11717 #ifdef WIN_MOTIF
11718     hdgColFmt.font = ParseFont ("Times,18,b");
11719     subColFmt.font = ParseFont ("Helvetica,12,b");
11720     txtColFmt.font = ParseFont ("Times,14");
11721 #endif /*WIN_MOTIF*/
11722     lstColFmt.font = programFont;
11723     tblColFmt.font = programFont;
11724   } else {
11725   /* above call to IsSystemLang should override this section */
11726     /* default system font is often native character set */
11727     /* because native character sets have a set of ascii letters,
11728        english help file can also be drawn as well as native letters. */
11729     hdgColFmt.font = systemFont;
11730     subColFmt.font = systemFont;
11731     txtColFmt.font = systemFont;
11732     lstColFmt.font = systemFont;
11733     tblColFmt.font = systemFont;
11734   }
11735 
11736   /* now allow override by sequin config file */
11737   hdgColFmt.font = GetHelpFontFromConfig ("HEADING", hdgColFmt.font);
11738   subColFmt.font = GetHelpFontFromConfig ("SUBHEAD", subColFmt.font);
11739   txtColFmt.font = GetHelpFontFromConfig ("TEXT", txtColFmt.font);
11740   lstColFmt.font = GetHelpFontFromConfig ("LIST", lstColFmt.font);
11741   tblColFmt.font = GetHelpFontFromConfig ("TABLE", tblColFmt.font);
11742 }
11743 
PopulateHelpForm(HelpFormPtr hfp)11744 static Boolean PopulateHelpForm (HelpFormPtr hfp)
11745 
11746 {
11747   Int2        firstLine;
11748   Int2        firstShown;
11749   RecT        r;
11750   BaR         sb;
11751   Int4        startsAt;
11752   CharPtr     text;
11753   ValNodePtr  vnp;
11754 
11755   if (hfp == NULL || hfp->doc == NULL) return FALSE;
11756   Hide (hfp->list);
11757   Hide (hfp->doc);
11758   Update ();
11759   if (! GetScrlParams4 (hfp->doc, NULL, &firstShown, &firstLine)) {
11760     firstShown = 0;
11761     firstLine = 0;
11762   }
11763   sb = GetSlateVScrollBar ((SlatE) hfp->doc);
11764   Reset (hfp->list);
11765   Reset (hfp->doc);
11766   if (hfp->file == NULL || hfp->file [0] == '\0') return FALSE;
11767   if (hfp->mainStrings == NULL || hfp->indexStrings == NULL) return FALSE;
11768   ObjectRect (hfp->doc, &r);
11769   InsetRect (&r, 4, 4);
11770   lstColFmt.pixWidth = r.right - r.left;
11771   hdgColFmt.pixWidth = r.right - r.left;
11772   subColFmt.pixWidth = r.right - r.left;
11773   /*
11774   tblColFmt.pixWidth = screenRect.right - screenRect.left;
11775   */
11776   tblColFmt.pixWidth = r.right - r.left;
11777   tblColFmt.pixInset = 10;
11778   txtColFmt.pixWidth = r.right - r.left;
11779   txtColFmt.pixInset = 10;
11780 
11781   for (vnp = hfp->indexStrings; vnp != NULL; vnp = vnp->next) {
11782     lstColFmt.pixInset = vnp->choice;
11783     AppendText (hfp->list, vnp->data.ptrvalue, &lstParFmt, &lstColFmt, programFont);
11784   }
11785 
11786   for (vnp = hfp->mainStrings; vnp != NULL; vnp = vnp->next) {
11787     switch (vnp->choice) {
11788       case TBL_FMT :
11789         AppendText (hfp->doc, vnp->data.ptrvalue, &tblParFmt, &tblColFmt, programFont);
11790         break;
11791       case TXT_FMT :
11792         AppendText (hfp->doc, vnp->data.ptrvalue, &txtParFmt, &txtColFmt, programFont);
11793         break;
11794       case HDG_FMT :
11795         AppendText (hfp->doc, vnp->data.ptrvalue, &hdgParFmt, &hdgColFmt, systemFont);
11796         break;
11797       case SUB_FMT :
11798         subColFmt.pixInset = 0;
11799         AppendText (hfp->doc, vnp->data.ptrvalue, &subParFmt, &subColFmt, programFont);
11800         break;
11801       default :
11802         subColFmt.pixInset = vnp->choice;
11803         AppendText (hfp->doc, vnp->data.ptrvalue, &subParFmt, &subColFmt, programFont);
11804         break;
11805     }
11806   }
11807 
11808   UpdateDocument (hfp->list, 0, 0);
11809   /*
11810   UpdateDocument (hfp->doc, 0, 0);
11811   */
11812   text = GetDocText (hfp->doc, firstShown, 0, 0);
11813   MemFree (text);
11814   AdjustDocScroll (hfp->doc);
11815   GetItemParams4 (hfp->doc, firstShown, &startsAt, NULL, NULL, NULL, NULL);
11816   CorrectBarValue (sb, startsAt + firstLine);
11817   Show (hfp->list);
11818   Show (hfp->doc);
11819   Update ();
11820   return TRUE;
11821 }
11822 
RefreshHelpForm(ButtoN b)11823 static void RefreshHelpForm (ButtoN b)
11824 
11825 {
11826   HelpFormPtr  hfp;
11827 
11828   hfp = (HelpFormPtr) GetObjectExtra (b);
11829   if (hfp == NULL) return;
11830   ParseHelpFile (hfp, TRUE);
11831   PopulateHelpForm (hfp);
11832   Update ();
11833 }
11834 
CleanupHelpForm(GraphiC g,VoidPtr data)11835 static void CleanupHelpForm (GraphiC g, VoidPtr data)
11836 
11837 {
11838   ResetHelpLists ((HelpFormPtr) data);
11839   StdCleanupFormProc (g, data);
11840 }
11841 
HelpListNotify(DoC d,Int2 item,Int2 row,Int2 col,Boolean dblclick)11842 static void HelpListNotify (DoC d, Int2 item, Int2 row, Int2 col, Boolean dblclick)
11843 
11844 {
11845   HelpFormPtr   hfp;
11846   HelpIndexPtr  hip;
11847   BaR           sb;
11848   Int2          startsAt;
11849   ValNodePtr    vnp;
11850 
11851   hfp = (HelpFormPtr) GetObjectExtra (d);
11852   if (hfp == NULL || hfp->doc == NULL) return;
11853   if (item == 0 || row == 0 || col == 0) return;
11854   vnp = hfp->index;
11855   while (vnp != NULL && item > 1) {
11856     item--;
11857     vnp = vnp->next;
11858   }
11859   if (vnp != NULL) {
11860     hip = (HelpIndexPtr) vnp->data.ptrvalue;
11861     if (hip != NULL) {
11862       GetItemParams (hfp->doc, hip->item, &startsAt, NULL, NULL, NULL, NULL);
11863       ResetClip ();
11864       sb = GetSlateVScrollBar ((SlatE) hfp->doc);
11865       SetValue (sb, startsAt);
11866       Update ();
11867     }
11868   }
11869 }
11870 
ResizeHelpForm(WindoW w)11871 static void ResizeHelpForm (WindoW w)
11872 
11873 {
11874   Int2         delta;
11875   Int2         diff;
11876   Int2         gap;
11877   Int2         height;
11878   HelpFormPtr  hfp;
11879   RecT         r;
11880   RecT         s;
11881   RecT         t;
11882   Int2         width;
11883 
11884   hfp = (HelpFormPtr) GetObjectExtra (w);
11885   if (hfp != NULL) {
11886     ObjectRect (w, &r);
11887     width = r.right - r.left;
11888     height = r.bottom - r.top;
11889     GetPosition (hfp->doc, &s);
11890     GetPosition (hfp->dismissGrp, &t);
11891     diff = t.bottom - t.top;
11892     gap = t.top - s.bottom;
11893     t.bottom = height - s.left;
11894     t.top = t.bottom - diff;
11895     delta = (width - t.right - t.left) / 2;
11896     t.left += delta;
11897     t.right += delta;
11898     s.right = width - s.left;
11899     /*
11900     s.bottom = height - s.left;
11901     */
11902     s.bottom = t.top - gap;
11903     SetPosition (hfp->dismissGrp, &t);
11904     SetPosition (hfp->doc, &s);
11905     AdjustPrnt (hfp->doc, &s, FALSE);
11906     PopulateHelpForm (hfp);
11907     Update ();
11908   }
11909 }
11910 
ScrollToTextInDoc(DoC d,Int2 item,CharPtr text)11911 static Boolean ScrollToTextInDoc (DoC d, Int2 item, CharPtr text)
11912 
11913 {
11914   Pointer  data;
11915   Boolean  found;
11916   RecT     rct;
11917   BaR      sb;
11918   Int4     startsAt;
11919   CharPtr  str;
11920   WindoW   tempPort;
11921 
11922   found = FALSE;
11923   GetItemParams4 (d, item, &startsAt, NULL, NULL, NULL, &data);
11924   str = (CharPtr) data;
11925   if (StringISearch (str, text) != NULL) {
11926     found = TRUE;
11927   }
11928   if (found) {
11929     tempPort = SavePort (d);
11930     Select (d);
11931     sb = GetSlateVScrollBar ((SlatE) d);
11932     CorrectBarValue (sb, startsAt);
11933     ObjectRect (d, &rct);
11934     InsetRect (&rct, 4, 4);
11935     InsetRect (&rct, -1, -1);
11936     InvalRect (&rct);
11937     RestorePort (tempPort);
11938     Update ();
11939   }
11940   return found;
11941 }
11942 
FindHelpBtnProc(ButtoN b)11943 static void FindHelpBtnProc (ButtoN b)
11944 
11945 {
11946   Int2         firstShown;
11947   HelpFormPtr  hfp;
11948   Int2         i;
11949   Int2         numItems;
11950   Char         str [256];
11951 
11952   hfp = (HelpFormPtr) GetObjectExtra (b);
11953   if (hfp == NULL) return;
11954   GetTitle (hfp->findTxt, str, sizeof (str) - 1);
11955   GetDocParams (hfp->doc, &numItems, NULL);
11956   if (GetScrlParams (hfp->doc, NULL, &firstShown, NULL)) {
11957     for (i = firstShown + 1; i <= numItems; i++) {
11958       if (ScrollToTextInDoc (hfp->doc, i, str)) {
11959         return;
11960       }
11961     }
11962     for (i = 1; i < firstShown; i++) {
11963       if (ScrollToTextInDoc (hfp->doc, i, str)) {
11964         return;
11965       }
11966     }
11967   }
11968 }
11969 
FindHelpTextProc(TexT t)11970 static void FindHelpTextProc (TexT t)
11971 
11972 {
11973   HelpFormPtr  hfp;
11974 
11975   hfp = (HelpFormPtr) GetObjectExtra (t);
11976   if (hfp == NULL) return;
11977   if (TextLength (t) > 0) {
11978     SafeEnable (hfp->findBtn);
11979   } else {
11980     SafeDisable (hfp->findBtn);
11981   }
11982 }
11983 
HelpFormMessage(ForM f,Int2 mssg)11984 static void HelpFormMessage (ForM f, Int2 mssg)
11985 
11986 {
11987   FILE         *fp;
11988   HelpFormPtr  hfp;
11989   Char         path [PATH_MAX];
11990 
11991   hfp = (HelpFormPtr) GetObjectExtra (f);
11992   if (hfp != NULL) {
11993     switch (mssg) {
11994       case VIB_MSG_CLOSE :
11995         Hide (f);
11996         break;
11997       case VIB_MSG_PRINT :
11998         PrintDocument (hfp->doc);
11999         break;
12000       case VIB_MSG_EXPORT :
12001         if (GetOutputFileName (path, sizeof (path), "help.txt")) {
12002           WatchCursor ();
12003 #ifdef WIN_MAC
12004           fp = FileOpen (path, "r");
12005           if (fp != NULL) {
12006             FileClose (fp);
12007           } else {
12008             FileCreate (path, "TEXT", "ttxt");
12009           }
12010 #endif
12011           fp = FileOpen (path, "w");
12012           if (fp != NULL) {
12013             SaveDocument (hfp->doc, fp);
12014             FileClose (fp);
12015           }
12016           ArrowCursor ();
12017         }
12018         break;
12019       default :
12020         if (hfp->appmessage != NULL) {
12021           hfp->appmessage (f, mssg);
12022         }
12023         break;
12024     }
12025   }
12026 }
12027 
HelpFormActivate(WindoW w)12028 static void HelpFormActivate (WindoW w)
12029 
12030 {
12031   IteM         exportItm;
12032   HelpFormPtr  hfp;
12033 
12034   hfp = (HelpFormPtr) GetObjectExtra (w);
12035   if (hfp != NULL) {
12036     if (hfp->activate != NULL) {
12037       hfp->activate (w);
12038     }
12039     exportItm = FindFormMenuItem ((BaseFormPtr) hfp, VIB_MSG_EXPORT);
12040     SafeSetTitle (exportItm, "Export Help...");
12041   }
12042 }
12043 
CreateHelpForm(Int2 left,Int2 top,CharPtr title,CharPtr file,BtnActnProc closeForm,WndActnProc activateForm)12044 extern ForM CreateHelpForm (Int2 left, Int2 top, CharPtr title,
12045                             CharPtr file, BtnActnProc closeForm,
12046                             WndActnProc activateForm)
12047 
12048 {
12049   ButtoN             b;
12050   GrouP              c;
12051   GrouP              h;
12052   Int2               height;
12053   HelpFormPtr        hfp;
12054   StdEditorProcsPtr  sepp;
12055   WindoW             w;
12056 #ifndef WIN_MAC
12057   MenU               m;
12058 #endif
12059 
12060   w = NULL;
12061   hfp = MemNew (sizeof (HelpForm));
12062   if (hfp != NULL) {
12063     w = DocumentWindow (left, top, -10, -10, title,
12064                         StdSendCloseWindowMessageProc, ResizeHelpForm);
12065     SetObjectExtra (w, hfp, CleanupHelpForm);
12066     hfp->form = (ForM) w;
12067     hfp->formmessage = HelpFormMessage;
12068 
12069     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
12070     if (sepp != NULL) {
12071       hfp->appmessage = sepp->handleMessages;
12072     }
12073 
12074     StringNCpy_0 (hfp->file, file, sizeof (hfp->file));
12075 
12076 #ifndef WIN_MAC
12077     m = PulldownMenu (w, "File");
12078     FormCommandItem (m, "Export", (BaseFormPtr) hfp, VIB_MSG_EXPORT);
12079     SeparatorItem (m);
12080 #ifdef WIN_MSWIN
12081     FormCommandItem (m, "Print", (BaseFormPtr) hfp, VIB_MSG_PRINT);
12082     SeparatorItem (m);
12083 #endif
12084     FormCommandItem (m, "Close", (BaseFormPtr) hfp, VIB_MSG_CLOSE);
12085 #endif
12086 
12087     c = HiddenGroup (w, 4, 0, NULL);
12088     StaticPrompt (c, "Find", 0, dialogTextHeight, programFont, 'l');
12089     hfp->findTxt = DialogText (c, "", 20, FindHelpTextProc);
12090     SetObjectExtra (hfp->findTxt, hfp, NULL);
12091     hfp->findBtn = PushButton (c, "Find", FindHelpBtnProc);
12092     SetObjectExtra (hfp->findBtn, hfp, NULL);
12093     Disable (hfp->findBtn);
12094 
12095     h = HiddenGroup (w, -1, 0, NULL);
12096     SelectFont (programFont);
12097     height = LineHeight ();
12098     SelectFont (systemFont);
12099     hfp->list = DocumentPanel (h, stdCharWidth * 28, height * 5);
12100     SetDocAutoAdjust (hfp->list, FALSE);
12101     SetObjectExtra (hfp->list, hfp, NULL);
12102     SetDocNotify (hfp->list, HelpListNotify);
12103 
12104     hfp->doc = DocumentPanel (h, stdCharWidth * 33, stdLineHeight * 20);
12105     SetDocAutoAdjust (hfp->doc, FALSE);
12106     SetObjectExtra (hfp->doc, hfp, NULL);
12107 
12108     hfp->dismissGrp = HiddenGroup (w, 2, 0, NULL);
12109     PushButton (hfp->dismissGrp, "Dismiss", closeForm);
12110     if (indexerVersion) {
12111       b = PushButton (hfp->dismissGrp, "Refresh", RefreshHelpForm);
12112       SetObjectExtra (b, hfp, NULL);
12113     }
12114 
12115     AlignObjects (ALIGN_CENTER, (HANDLE) hfp->doc, (HANDLE) hfp->dismissGrp, NULL);
12116 
12117     RealizeWindow (w);
12118 
12119     SetupHelpFonts ();
12120 
12121     if (activateForm != NULL) {
12122       hfp->activate = activateForm;
12123     } else {
12124       if (sepp != NULL) {
12125         hfp->activate = sepp->activateForm;
12126       }
12127     }
12128     SetActivate (w, HelpFormActivate);
12129     HelpFormActivate ((WindoW) hfp->form);
12130 
12131     if (ParseHelpFile (hfp, FALSE)) {
12132       if (! PopulateHelpForm (hfp)) {
12133         w = Remove (w);
12134       }
12135     } else {
12136       w = Remove (w);
12137     }
12138   }
12139   return (ForM) w;
12140 }
12141 
SendHelpScrollMessage(ForM f,CharPtr heading,CharPtr section)12142 extern void SendHelpScrollMessage (ForM f, CharPtr heading, CharPtr section)
12143 
12144 {
12145   HelpFormPtr   hfp;
12146   HelpIndexPtr  hip;
12147   BaR           sb;
12148   Int2          startsAt;
12149   CharPtr       str;
12150   Char          txt [256];
12151   Boolean       useBoth;
12152   Boolean       useHeading;
12153   Boolean       useSection;
12154   ValNodePtr    vnp;
12155 
12156   hfp = (HelpFormPtr) GetObjectExtra (f);
12157   if (hfp != NULL) {
12158     vnp = hfp->index;
12159     txt [0] = '\0';
12160     useBoth = FALSE;
12161     useHeading = FALSE;
12162     useSection = FALSE;
12163     if (heading != NULL && *heading != '\0' && section != NULL && *section != '\0') {
12164       useBoth = TRUE;
12165       if (StringLen (heading) + StringLen (section) < sizeof (txt) - 2) {
12166         StringCpy (txt, heading);
12167         StringCat (txt, "|");
12168         StringCat (txt, section);
12169       }
12170     } else if (heading != NULL && *heading != '\0') {
12171       useHeading = TRUE;
12172       StringNCpy_0 (txt, heading, sizeof (txt));
12173     } else if (section != NULL && *section != '\0') {
12174       useSection = TRUE;
12175       StringNCpy_0 (txt, section, sizeof (txt));
12176     }
12177     while (vnp != NULL) {
12178       hip = (HelpIndexPtr) vnp->data.ptrvalue;
12179       if (hip != NULL) {
12180         if (useBoth) {
12181           str = hip->combined;
12182         } else if (useHeading) {
12183           str = hip->heading;
12184         } else if (useSection) {
12185           str = hip->section;
12186         } else {
12187           str = NULL;
12188         }
12189         if (str != NULL && StringICmp (txt, str) == 0) {
12190           GetItemParams (hfp->doc, hip->item, &startsAt, NULL, NULL, NULL, NULL);
12191           sb = GetSlateVScrollBar ((SlatE) hfp->doc);
12192           ResetClip ();
12193           SetValue (sb, startsAt);
12194           Update ();
12195           return;
12196         }
12197       }
12198       vnp = vnp->next;
12199     }
12200   }
12201 }
12202 
12203 typedef struct applycdsframe
12204 {
12205   FEATURE_FORM_BLOCK
12206   DialoG constraint_dlg;
12207   PopuP  current_frame_popup;
12208   PopuP  new_frame_popup;
12209   ButtoN retranslate_btn;
12210 
12211   Int4 current_frame_flag;
12212   Int4 new_frame;
12213   Boolean retranslate_flag;
12214   ConstraintChoiceSetPtr constraint;
12215   LogInfoPtr lip;
12216 } ApplyCDSFrameData, PNTR ApplyCDSFramePtr;
12217 
ApplyCDSFrameCallback(SeqFeatPtr sfp,Pointer userdata)12218 static void ApplyCDSFrameCallback (SeqFeatPtr sfp, Pointer userdata)
12219 {
12220   CdRegionPtr       crp;
12221   ApplyCDSFramePtr acfp;
12222 
12223   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION
12224       || (acfp = (ApplyCDSFramePtr) userdata) == NULL
12225       || !DoesObjectMatchConstraintChoiceSet (OBJ_SEQFEAT, sfp, acfp->constraint))
12226   {
12227     return;
12228   }
12229 
12230   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
12231   if (crp == NULL)
12232   {
12233     crp = CdRegionNew ();
12234     sfp->data.value.ptrvalue = crp;
12235   }
12236 
12237   if (acfp->current_frame_flag == 4 || crp->frame == acfp->current_frame_flag)
12238   {
12239     if (acfp->new_frame == 4) {
12240       if (!SetBestFrameByLocation (sfp)) {
12241         LogCDSAmbiguousFrame (acfp->lip, sfp);
12242       }
12243     } else {
12244       crp->frame = acfp->new_frame;
12245     }
12246     if (acfp->retranslate_flag)
12247     {
12248       RetranslateOneCDS (sfp, acfp->input_entityID, TRUE, FALSE);
12249     }
12250   }
12251 }
12252 
DoApplyCDSFrame(ButtoN b)12253 static void DoApplyCDSFrame (ButtoN b)
12254 {
12255   ApplyCDSFramePtr acfp;
12256   SeqEntryPtr      sep;
12257 
12258   acfp = (ApplyCDSFramePtr) GetObjectExtra (b);
12259   if (acfp == NULL)
12260   {
12261     return;
12262   }
12263 
12264   sep = GetTopSeqEntryForEntityID (acfp->input_entityID);
12265   if (sep == NULL)
12266   {
12267     return;
12268   }
12269 
12270   WatchCursor ();
12271   Update ();
12272 
12273   acfp->lip = OpenLog ("Ambiguous frames");
12274   acfp->constraint = DialogToPointer (acfp->constraint_dlg);
12275 
12276   acfp->current_frame_flag = GetValue (acfp->current_frame_popup);
12277   acfp->new_frame = GetValue (acfp->new_frame_popup);
12278   acfp->retranslate_flag = GetStatus (acfp->retranslate_btn);
12279 
12280   VisitFeaturesInSep (sep, acfp, ApplyCDSFrameCallback);
12281 
12282   acfp->constraint = ConstraintChoiceSetFree (acfp->constraint);
12283 
12284   ArrowCursor ();
12285   Update ();
12286   ObjMgrSetDirtyFlag (acfp->input_entityID, TRUE);
12287   ObjMgrSendMsg (OM_MSG_UPDATE, acfp->input_entityID, 0, 0);
12288   Remove (acfp->form);
12289   CloseLog (acfp->lip);
12290   acfp->lip = FreeLog (acfp->lip);
12291 
12292 }
12293 
ApplyCDSFrame(IteM i)12294 extern void ApplyCDSFrame (IteM i)
12295 {
12296   BaseFormPtr        bfp;
12297   GrouP              g, h, c;
12298   ApplyCDSFramePtr   acfp;
12299   WindoW             w;
12300   ButtoN             b;
12301 
12302   /* Get current sequence */
12303 
12304 #ifdef WIN_MAC
12305   bfp = currentFormDataPtr;
12306 #else
12307   bfp = GetObjectExtra (i);
12308 #endif
12309   if (bfp == NULL)
12310     return;
12311 
12312   acfp = (ApplyCDSFramePtr) MemNew (sizeof (ApplyCDSFrameData));
12313   if (acfp == NULL)
12314   {
12315     return;
12316   }
12317   acfp->lip = NULL;
12318 
12319   w = FixedWindow (-50, -33, -20, -10, "Apply CDS Frame",	StdCloseWindowProc);
12320   SetObjectExtra (w, acfp, StdCleanupFormProc);
12321   acfp->form = (ForM) w;
12322 
12323   acfp->input_entityID = bfp->input_entityID;
12324   acfp->input_itemID = bfp->input_itemID;
12325 
12326   g = HiddenGroup (w, -1, 0, NULL);
12327   SetGroupSpacing (g, 10, 10);
12328 
12329   h = HiddenGroup (g, 2, 0, NULL);
12330   SetGroupSpacing (h, 10, 10);
12331   StaticPrompt (h, "Set Coding Region frame to:", 0, dialogTextHeight,
12332                 programFont, 'l');
12333   acfp->new_frame_popup = PopupList (h, TRUE, NULL);
12334   PopupItem (acfp->new_frame_popup, "1");
12335   PopupItem (acfp->new_frame_popup, "2");
12336   PopupItem (acfp->new_frame_popup, "3");
12337   PopupItem (acfp->new_frame_popup, "Best");
12338   SetValue (acfp->new_frame_popup, 1);
12339 
12340   StaticPrompt (h, "Where Coding Region frame is:", 0, dialogTextHeight,
12341                 programFont, 'l');
12342   acfp->current_frame_popup = PopupList (h, TRUE, NULL);
12343   PopupItem (acfp->current_frame_popup, "1");
12344   PopupItem (acfp->current_frame_popup, "2");
12345   PopupItem (acfp->current_frame_popup, "3");
12346   PopupItem (acfp->current_frame_popup, "Any frame");
12347 
12348   SetValue (acfp->current_frame_popup, 4);
12349 
12350   acfp->constraint_dlg = ComplexConstraintDialog (g, NULL, NULL);
12351   ChangeComplexConstraintFieldType (acfp->constraint_dlg, FieldType_cds_gene_prot, NULL, Macro_feature_type_cds);
12352 
12353   acfp->retranslate_btn = CheckBox (g, "Retranslate adjusted coding regions", NULL);
12354   SetStatus (acfp->retranslate_btn, TRUE);
12355 
12356   c = HiddenGroup (g, 2, 0, NULL);
12357   b = DefaultButton(c, "Accept", DoApplyCDSFrame);
12358   SetObjectExtra(b, acfp, NULL);
12359   PushButton (c, "Cancel", StdCancelButtonProc);
12360 
12361   AlignObjects (ALIGN_CENTER, (HANDLE) h,
12362                               (HANDLE) acfp->constraint,
12363                               (HANDLE) acfp->retranslate_btn,
12364                               (HANDLE) c, NULL);
12365   RealizeWindow(w);
12366   Show(w);
12367   Update();
12368 
12369 }
12370 
FreeSeqIdList(ValNodePtr id_list)12371 extern ValNodePtr FreeSeqIdList (ValNodePtr id_list)
12372 {
12373   SeqIdPtr sip;
12374   ValNodePtr vnp;
12375 
12376   for (vnp = id_list; vnp != NULL; vnp = vnp->next) {
12377        sip = vnp->data.ptrvalue;
12378        sip = SeqIdFree (sip);
12379      vnp->data.ptrvalue = NULL;
12380   }
12381   id_list = ValNodeFree (id_list);
12382   return NULL;
12383 }
12384 
12385 
SplitByCommasAndSpaces(CharPtr list)12386 static ValNodePtr SplitByCommasAndSpaces (CharPtr list)
12387 {
12388   CharPtr cp;
12389   Char    ch;
12390   ValNodePtr str_list = NULL;
12391   Int4       len;
12392 
12393   if (StringHasNoText (list)) {
12394     return NULL;
12395   }
12396 
12397   /* skip any leading blanks */
12398   list += StringSpn (list, " ,\t");
12399   len = StringCSpn (list, " ,\t");
12400   while (len != 0) {
12401     cp = list + len;
12402     ch = *cp;
12403     *cp = 0;
12404     ValNodeAddPointer (&str_list, 0, StringSave (list));
12405     *cp = ch;
12406     list = cp + StringSpn (cp, " ,\t");
12407     len = StringCSpn (list, " ,\t");
12408   }
12409   return str_list;
12410 }
12411 
12412 
ParseIDStr(CharPtr id_str,CharPtr PNTR prefix,Int4Ptr num,Int4Ptr num_len)12413 static Boolean ParseIDStr (CharPtr id_str, CharPtr PNTR prefix, Int4Ptr num, Int4Ptr num_len)
12414 {
12415   CharPtr start_number;
12416   Char    ch;
12417 
12418   if (StringHasNoText (id_str) || prefix == NULL || num == NULL || num_len == NULL) {
12419     return FALSE;
12420   }
12421 
12422   start_number = id_str + StringLen (id_str);
12423   while (start_number > id_str && isdigit (*(start_number - 1))) {
12424     start_number--;
12425   }
12426   *num_len = StringLen (start_number);
12427   if (num_len == 0) {
12428     return FALSE;
12429   }
12430   *num = atoi (start_number);
12431   if (start_number == id_str) {
12432     *prefix = NULL;
12433   } else {
12434     ch = *start_number;
12435     *start_number = 0;
12436     *prefix = StringSave (id_str);
12437     *start_number = ch;
12438   }
12439   return TRUE;
12440 }
12441 
ExpandAccessionRanges(CharPtr list_str,SeqEntryPtr sep)12442 static ValNodePtr ExpandAccessionRanges (CharPtr list_str, SeqEntryPtr sep)
12443 {
12444   ValNodePtr id_list = NULL;
12445   CharPtr    cp;
12446   Char       ch;
12447   SeqIdPtr   sip;
12448   CharPtr    last_prefix = NULL, this_prefix = NULL, tmpstr;
12449   Int4       num_len = 0, num_len2;
12450   Int4       range_start, range_end, sw;
12451 
12452   if (StringHasNoText (list_str)) {
12453     return NULL;
12454   } else if ((cp = StringChr (list_str, '-')) == NULL) {
12455     sip = CreateSeqIdFromText(list_str, sep);
12456     if (sip == NULL) {/* Bad SeqId string */
12457       Message (MSG_ERROR, "Unable to parse %s as ID\n", list_str);
12458       return NULL;
12459     } else {
12460       ValNodeAddPointer (&id_list, 0, sip);
12461       return id_list;
12462     }
12463   } else {
12464     ch = *cp;
12465     *cp = 0;
12466     if (!ParseIDStr (list_str, &this_prefix, &range_start, &num_len)) {
12467       *cp = ch;
12468       Message (MSG_ERROR, "Unable to parse %s", list_str);
12469       return NULL;
12470     }
12471     *cp = ch;
12472     if (!ParseIDStr (cp + 1, &last_prefix, &range_end, &num_len2)) {
12473       Message (MSG_ERROR, "Unable to parse %s", list_str);
12474       this_prefix = MemFree (this_prefix);
12475       return NULL;
12476     }
12477     if (last_prefix != NULL && StringCmp (this_prefix, last_prefix) != 0) {
12478       Message (MSG_ERROR, "Unable to parse range for %s", list_str);
12479       this_prefix = MemFree (this_prefix);
12480       last_prefix = MemFree (last_prefix);
12481       return NULL;
12482     }
12483 
12484     if (range_start > range_end) {
12485       sw = range_start;
12486       range_start = range_end;
12487       range_end = sw;
12488     }
12489     tmpstr = (CharPtr) MemNew (sizeof (Char) * StringLen (this_prefix) + 15);
12490     for (sw = range_start; sw <= range_end; sw++) {
12491       sprintf (tmpstr, "%s%0*d", this_prefix == NULL ? "" : this_prefix, num_len, sw);
12492       sip = CreateSeqIdFromText(tmpstr, sep);
12493       if (sip == NULL) {
12494         if (sw == range_start || sw == range_end) {
12495           Message (MSG_ERROR, "Unable to parse range for %s", list_str);
12496           id_list = FreeSeqIdList (id_list);
12497           break;
12498         }
12499       } else {
12500         ValNodeAddPointer (&id_list, 0, sip);
12501       }
12502     }
12503     tmpstr = MemFree (tmpstr);
12504   }
12505 
12506   this_prefix = MemFree (this_prefix);
12507   last_prefix = MemFree (last_prefix);
12508 
12509   return id_list;
12510 }
12511 
12512 
ParseAccessionNumberListFromString(CharPtr list_str,SeqEntryPtr sep)12513 extern ValNodePtr ParseAccessionNumberListFromString (CharPtr list_str, SeqEntryPtr sep)
12514 {
12515   ValNodePtr token_list, vnp, id_list = NULL, tmp;
12516 
12517   if (StringHasNoText (list_str)) {
12518       Message (MSG_ERROR, "No accession numbers listed!");
12519       return NULL;
12520   }
12521 
12522   token_list = SplitByCommasAndSpaces (list_str);
12523   for (vnp = token_list; vnp != NULL; vnp = vnp->next) {
12524     tmp = ExpandAccessionRanges (vnp->data.ptrvalue, sep);
12525     if (tmp == NULL) {
12526       id_list = FreeSeqIdList (id_list);
12527       break;
12528     } else {
12529       ValNodeLink (&id_list, tmp);
12530     }
12531   }
12532   token_list = ValNodeFreeData (token_list);
12533   return id_list;
12534 }
12535 
12536 
12537 typedef struct resolvefeatureoverlaps {
12538   Uint1 trim_type;
12539   ValNodePtr trim_constraint;
12540   Uint1 intersect_type;
12541   ValNodePtr intersect_constraint;
12542   LogInfoPtr lip;
12543 } ResolveFeatureOverlapsData, PNTR ResolveFeatureOverlapsPtr;
12544 
TrimLocationForIntersectingFeatures(SeqLocPtr PNTR p_slp,ValNodePtr feat_list)12545 static Boolean TrimLocationForIntersectingFeatures (SeqLocPtr PNTR p_slp, ValNodePtr feat_list)
12546 {
12547   SeqLocPtr  slp;
12548   SeqFeatPtr sfp;
12549   ValNodePtr vnp;
12550   Int4       orig_left, new_left, feat_left;
12551   Int4       orig_right, new_right, feat_right;
12552   Int4       tmp;
12553   SeqIdPtr   sip;
12554   Boolean    changed = FALSE, end_changed;
12555 
12556   if (p_slp == NULL || *p_slp == NULL || feat_list == NULL) return FALSE;
12557 
12558   slp = *p_slp;
12559   orig_left = SeqLocStart (slp);
12560   orig_right = SeqLocStop (slp);
12561   if (orig_left > orig_right)
12562   {
12563     tmp = orig_left;
12564     orig_left = orig_right;
12565     orig_right = tmp;
12566   }
12567 
12568   new_left = orig_left;
12569   new_right = orig_right;
12570 
12571   for (vnp = feat_list; vnp != NULL; vnp = vnp->next)
12572   {
12573     sfp = (SeqFeatPtr) vnp->data.ptrvalue;
12574     feat_left = SeqLocStart (sfp->location);
12575     feat_right = SeqLocStop (sfp->location);
12576     if (feat_left > feat_right)
12577     {
12578       tmp = feat_left;
12579       feat_left = feat_right;
12580       feat_right = tmp;
12581     }
12582     if (feat_left <= orig_left && feat_right >= orig_left && feat_right <= orig_right)
12583     {
12584       /* trim on left */
12585       if (new_left < feat_right + 1)
12586       {
12587         new_left = feat_right + 1;
12588       }
12589     }
12590     else if (feat_left <= orig_right && feat_right >= orig_right && feat_left >= orig_left)
12591     {
12592       /* trim on right */
12593       if (new_right > feat_left - 1)
12594       {
12595         new_right = feat_left - 1;
12596       }
12597     }
12598   }
12599 
12600   if (new_left >= new_right)
12601   {
12602     *p_slp = SeqLocFree (*p_slp);
12603   }
12604   else
12605   {
12606     if (new_left > orig_left)
12607     {
12608       sip = SeqLocId (slp);
12609       end_changed = FALSE;
12610       *p_slp = SeqLocDelete (*p_slp, sip, orig_left, new_left - 1, FALSE, &end_changed);
12611       changed |= end_changed;
12612     }
12613     if (new_right < orig_right)
12614     {
12615       sip = SeqLocId (slp);
12616       end_changed = FALSE;
12617       *p_slp = SeqLocDelete (*p_slp, sip, new_right + 1, orig_right, FALSE, &end_changed);
12618       changed |= end_changed;
12619     }
12620   }
12621   return changed;
12622 }
12623 
12624 
ResolveFeatureOverlapsBioseqCallback(BioseqPtr bsp,Pointer data)12625 static void ResolveFeatureOverlapsBioseqCallback (BioseqPtr bsp, Pointer data)
12626 {
12627   ResolveFeatureOverlapsPtr r;
12628   SeqFeatPtr sfp;
12629   SeqMgrFeatContext fcontext;
12630   ValNodePtr        overlap_list;
12631   CharPtr           feat_desc;
12632   ValNode           vn;
12633 
12634   r = (ResolveFeatureOverlapsPtr) data;
12635   if (bsp == NULL || r == NULL) return;
12636 
12637   MemSet (&vn, 0, sizeof (ValNode));
12638   vn.next = NULL;
12639   vn.choice = OBJ_SEQFEAT;
12640 
12641   for (sfp = SeqMgrGetNextFeature (bsp, NULL, 0, r->trim_type, &fcontext);
12642        sfp != NULL;
12643        sfp = SeqMgrGetNextFeature (bsp, sfp, 0, r->trim_type, &fcontext))
12644   {
12645     vn.data.ptrvalue = sfp;
12646     if (!DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, r->trim_constraint)) {
12647       continue;
12648     }
12649     feat_desc = GetDiscrepancyItemText (&vn);
12650     overlap_list = ListFeaturesOverlappingLocationEx (bsp, sfp->location, 0, r->intersect_type, r->intersect_constraint);
12651     if (TrimLocationForIntersectingFeatures (&(sfp->location), overlap_list))
12652     {
12653       if (sfp->location == NULL)
12654       {
12655         fprintf (r->lip->fp, "Feature completely overlapped and removed:\n%s\n", feat_desc);
12656         sfp->idx.deleteme = TRUE;
12657         r->lip->data_in_log = TRUE;
12658       }
12659       else
12660       {
12661         fprintf (r->lip->fp, "Trimmed Feature: %sNew location:", feat_desc);
12662         LogTrimmedLocation (r->lip, sfp->location);
12663         fprintf (r->lip->fp, "\n");
12664       }
12665     }
12666     feat_desc = MemFree (feat_desc);
12667     overlap_list = ValNodeFree (overlap_list);
12668   }
12669 }
12670 
12671 
12672 typedef struct resolvefeatureoverlapsform {
12673   FORM_MESSAGE_BLOCK
12674   DialoG trim_type;
12675   DialoG trim_constraint;
12676   DialoG intersect_type;
12677   DialoG intersect_constraint;
12678   DialoG accept_cancel;
12679 
12680 } ResolveFeatureOverlapsFormData, PNTR ResolveFeatureOverlapsFormPtr;
12681 
12682 
SetResolveFeatureOverlapsFormAccept(Pointer data)12683 static void SetResolveFeatureOverlapsFormAccept (Pointer data)
12684 {
12685   ResolveFeatureOverlapsFormPtr dlg;
12686   ValNodePtr                    vnp1, vnp2;
12687 
12688   dlg = (ResolveFeatureOverlapsFormPtr) data;
12689   if (dlg == NULL) return;
12690 
12691   vnp1 = DialogToPointer (dlg->trim_type);
12692   vnp2 = DialogToPointer (dlg->intersect_type);
12693   if (vnp1 == NULL || vnp2 == NULL)
12694   {
12695     DisableAcceptCancelDialogAccept (dlg->accept_cancel);
12696   }
12697   else
12698   {
12699     EnableAcceptCancelDialogAccept (dlg->accept_cancel);
12700   }
12701 
12702   vnp1 = ValNodeFree (vnp1);
12703   vnp2 = ValNodeFree (vnp2);
12704 }
12705 
12706 
ChangeTrimFeatureType(Pointer data)12707 static void ChangeTrimFeatureType (Pointer data)
12708 {
12709   ResolveFeatureOverlapsFormPtr dlg;
12710   ValNodePtr                    vnp;
12711 
12712   dlg = (ResolveFeatureOverlapsFormPtr) data;
12713   if (dlg == NULL) return;
12714 
12715   vnp = DialogToPointer (dlg->trim_type);
12716   if (vnp != NULL) {
12717     ChangeComplexConstraintFieldType (dlg->trim_constraint, FieldType_feature_field, NULL, vnp->choice);
12718   }
12719   vnp = ValNodeFree (vnp);
12720   SetResolveFeatureOverlapsFormAccept (data);
12721 }
12722 
12723 
ChangeIntersectFeatureType(Pointer data)12724 static void ChangeIntersectFeatureType (Pointer data)
12725 {
12726   ResolveFeatureOverlapsFormPtr dlg;
12727   ValNodePtr                    vnp;
12728 
12729   dlg = (ResolveFeatureOverlapsFormPtr) data;
12730   if (dlg == NULL) return;
12731 
12732   vnp = DialogToPointer (dlg->intersect_type);
12733   if (vnp != NULL) {
12734     ChangeComplexConstraintFieldType (dlg->intersect_constraint, FieldType_feature_field, NULL, vnp->choice);
12735   }
12736   vnp = ValNodeFree (vnp);
12737   SetResolveFeatureOverlapsFormAccept (data);
12738 }
12739 
12740 
ResolveFeatureOverlapAction(Pointer data)12741 static Boolean ResolveFeatureOverlapAction (Pointer data)
12742 {
12743   ResolveFeatureOverlapsFormPtr dlg;
12744   ValNodePtr                    vnp1, vnp2;
12745   ResolveFeatureOverlapsData    r;
12746   SeqEntryPtr                   sep;
12747 
12748   dlg = (ResolveFeatureOverlapsFormPtr) data;
12749   if (dlg == NULL) return FALSE;
12750 
12751   vnp1 = DialogToPointer (dlg->trim_type);
12752   vnp2 = DialogToPointer (dlg->intersect_type);
12753 
12754   WatchCursor();
12755   Update();
12756   r.trim_type = vnp1->choice;
12757   r.trim_constraint = DialogToPointer (dlg->trim_constraint);
12758   r.intersect_type = vnp2->choice;
12759   r.intersect_constraint = DialogToPointer (dlg->intersect_constraint);
12760   r.lip = OpenLog ("Trimmed Features");
12761 
12762   sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
12763   VisitBioseqsInSep (sep, &r, ResolveFeatureOverlapsBioseqCallback);
12764 
12765   CloseLog (r.lip);
12766   FreeLog (r.lip);
12767 
12768   r.trim_constraint = ConstraintChoiceSetFree (r.trim_constraint);
12769   r.intersect_constraint = ConstraintChoiceSetFree (r.intersect_constraint);
12770 
12771   DeleteMarkedObjects (dlg->input_entityID, 0, NULL);
12772   ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
12773   ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
12774 
12775   ArrowCursor ();
12776   Update ();
12777   return TRUE;
12778 }
12779 
12780 
ResolveFeatureOverlaps(IteM i)12781 extern void ResolveFeatureOverlaps (IteM i)
12782 {
12783   BaseFormPtr        bfp;
12784   GrouP              h, g;
12785   SeqEntryPtr        sep;
12786   WindoW             w;
12787   ResolveFeatureOverlapsFormPtr dlg;
12788 
12789 #ifdef WIN_MAC
12790   bfp = currentFormDataPtr;
12791 #else
12792   bfp = GetObjectExtra (i);
12793 #endif
12794   if (bfp == NULL)
12795     return;
12796 
12797   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
12798   if (sep == NULL)
12799     return;
12800 
12801   dlg = (ResolveFeatureOverlapsFormPtr) MemNew (sizeof (ResolveFeatureOverlapsFormData));
12802   w = FixedWindow (-50, -33, -10, -10, "Resolve Feature Overlaps",
12803 		   StdCloseWindowProc);
12804   SetObjectExtra (w, dlg, StdCleanupFormProc);
12805   dlg->form = (ForM) w;
12806 
12807   dlg->input_entityID = bfp->input_entityID;
12808   dlg->input_itemID   = bfp->input_itemID;
12809   dlg->input_itemtype = bfp->input_itemtype;
12810 
12811   h = HiddenGroup (w, -1, 0, NULL);
12812   SetGroupSpacing (h, 10, 10);
12813 
12814   g = HiddenGroup (h, 3, 0, NULL);
12815   StaticPrompt (g, "Trim features of type", 0, popupMenuHeight, programFont, 'c');
12816   dlg->trim_type = FeatureSelectionDialogEx (g, FALSE, sep, ChangeTrimFeatureType, dlg);
12817   dlg->trim_constraint = ComplexConstraintDialog (g, NULL, NULL);
12818   ChangeComplexConstraintFieldType (dlg->trim_constraint, FieldType_feature_field, NULL, Macro_feature_type_any);
12819 
12820   StaticPrompt (g, "Where they overlap features of type", 0, popupMenuHeight, programFont, 'c');
12821   dlg->intersect_type = FeatureSelectionDialogEx (g, FALSE, sep, ChangeIntersectFeatureType, dlg);
12822   dlg->intersect_constraint = ComplexConstraintDialog (g, NULL, NULL);
12823   ChangeComplexConstraintFieldType (dlg->intersect_constraint, FieldType_feature_field, NULL, Macro_feature_type_any);
12824 
12825   /* Accept and Cancel buttons */
12826 
12827   dlg->accept_cancel = AcceptCancelDialog (h, ResolveFeatureOverlapAction, NULL,
12828                                           NULL, NULL, (Pointer) dlg, w);
12829 
12830   /* Line things up and display the window */
12831 
12832   AlignObjects (ALIGN_CENTER,
12833                 (HANDLE) g,
12834 		            (HANDLE) dlg->accept_cancel,
12835 		            NULL);
12836 
12837   RealizeWindow (w);
12838   Show (w);
12839   Select (w);
12840   Update ();
12841 }
12842 
12843 
IsExternalGeneralID(SeqIdPtr sip)12844 static Boolean IsExternalGeneralID (SeqIdPtr sip)
12845 {
12846   DbtagPtr dbtag;
12847 
12848   if (sip == NULL || sip->data.ptrvalue == NULL || sip->choice != SEQID_GENERAL) return FALSE;
12849   dbtag = (DbtagPtr) sip->data.ptrvalue;
12850   if (StringCmp (dbtag->db, "NCBIFILE") != 0
12851       && StringCmp (dbtag->db, "TMSMART") != 0)
12852   {
12853     return TRUE;
12854   }
12855   else
12856   {
12857     return FALSE;
12858   }
12859 }
12860 
12861 
ListBioseqsWithExternalGeneralID(BioseqPtr bsp,Pointer userdata)12862 static void ListBioseqsWithExternalGeneralID (BioseqPtr bsp, Pointer userdata)
12863 {
12864   SeqIdPtr sip;
12865 
12866   if (bsp != NULL && userdata != NULL)
12867   {
12868     for (sip = bsp->id; sip != NULL && !IsExternalGeneralID (sip); sip = sip->next)
12869     {
12870     }
12871     if (sip != NULL)
12872     {
12873       ValNodeAddPointer ((ValNodePtr PNTR) userdata, OBJ_BIOSEQ, bsp);
12874     }
12875   }
12876 }
12877 
12878 
LocalIdFromGeneralId(SeqIdPtr sip)12879 static SeqIdPtr LocalIdFromGeneralId (SeqIdPtr sip)
12880 {
12881   DbtagPtr dbtag;
12882   ObjectIdPtr oip;
12883   SeqIdPtr sip_new;
12884   Char     label[15];
12885 
12886   if (!IsExternalGeneralID (sip)) return NULL;
12887 
12888   dbtag = (DbtagPtr) sip->data.ptrvalue;
12889   if (dbtag->tag == NULL) return NULL;
12890 
12891   sip_new = ValNodeNew (NULL);
12892   sip_new->choice = SEQID_LOCAL;
12893   oip = ObjectIdNew ();
12894   if (dbtag->tag->id > 0)
12895   {
12896     sprintf (label, "%d", dbtag->tag->id);
12897     oip->str = StringSave (label);
12898   }
12899   else
12900   {
12901     oip->str = StringSave (dbtag->tag->str);
12902   }
12903   sip_new->data.ptrvalue = oip;
12904   return sip_new;
12905 }
12906 
ConvertGeneralIdToLocalID(IteM i)12907 extern void ConvertGeneralIdToLocalID (IteM i)
12908 {
12909   BaseFormPtr        bfp;
12910   SeqEntryPtr        sep;
12911   ValNodePtr         bsp_list = NULL, vnp;
12912   BioseqPtr          bsp;
12913   SeqIdPtr           sip_new, sip_next, sip_prev, sip_list, sip;
12914 
12915 #ifdef WIN_MAC
12916   bfp = currentFormDataPtr;
12917 #else
12918   bfp = GetObjectExtra (i);
12919 #endif
12920   if (bfp == NULL)
12921     return;
12922 
12923   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
12924   if (sep == NULL)
12925     return;
12926 
12927   VisitBioseqsInSep (sep, &bsp_list, ListBioseqsWithExternalGeneralID);
12928 
12929   for (vnp = bsp_list; vnp != NULL; vnp = vnp->next)
12930   {
12931     bsp = (BioseqPtr) vnp->data.ptrvalue;
12932     if (bsp == NULL) continue;
12933     sip = bsp->id;
12934     sip_prev = NULL;
12935     while (sip != NULL)
12936     {
12937       sip_next = sip->next;
12938       if (IsExternalGeneralID (sip) && (sip_new = LocalIdFromGeneralId (bsp->id)) != NULL)
12939       {
12940         sip_new->next = sip->next;
12941         sip->next = NULL;
12942         if (sip_prev == NULL)
12943         {
12944           bsp->id = sip_new;
12945         }
12946         else
12947         {
12948           sip_prev->next = sip_new;
12949         }
12950         sip_list = bsp->id;
12951         /* now use just old ID for replace */
12952         bsp->id = sip;
12953         BioseqReplaceID (bsp, sip_new);
12954         /* put list back */
12955         bsp->id = SeqIdFree (bsp->id);
12956         bsp->id = sip_list;
12957         SeqMgrReplaceInBioseqIndex (bsp);
12958       }
12959       else
12960       {
12961         sip_prev = sip;
12962       }
12963       sip = sip_next;
12964     }
12965   }
12966   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
12967   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
12968 }
12969 
12970 
AbbreviateCitSubAffilStates(IteM i)12971 extern void AbbreviateCitSubAffilStates (IteM i)
12972 {
12973   BaseFormPtr        bfp;
12974 
12975 #ifdef WIN_MAC
12976   bfp = currentFormDataPtr;
12977 #else
12978   bfp = GetObjectExtra (i);
12979 #endif
12980   if (bfp == NULL)
12981     return;
12982 
12983   FixUsaAndStateAbbreviations(bfp->input_entityID, NULL);
12984   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
12985   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
12986 }
12987 
12988 
12989 typedef struct flucommentlist {
12990   BioseqPtr bsp;
12991   BioSourcePtr biop;
12992 } FluCommentListData, PNTR FluCommentListPtr;
12993 
12994 
FluCommentListNew(BioseqPtr bsp,BioSourcePtr biop)12995 static FluCommentListPtr FluCommentListNew (BioseqPtr bsp, BioSourcePtr biop)
12996 {
12997   FluCommentListPtr f;
12998 
12999   f = (FluCommentListPtr) MemNew (sizeof (FluCommentListData));
13000   f->bsp = bsp;
13001   f->biop = biop;
13002   return f;
13003 }
13004 
13005 
SortFluCommentList(VoidPtr ptr1,VoidPtr ptr2)13006 static int LIBCALLBACK SortFluCommentList (VoidPtr ptr1, VoidPtr ptr2)
13007 
13008 {
13009   ValNodePtr    vnp1, vnp2;
13010   FluCommentListPtr f1, f2;
13011   Int4              rval = 0;
13012 
13013   if (ptr1 != NULL && ptr2 != NULL) {
13014     vnp1 = *((ValNodePtr PNTR) ptr1);
13015     vnp2 = *((ValNodePtr PNTR) ptr2);
13016     if (vnp1 != NULL && vnp2 != NULL) {
13017       f1 = (FluCommentListPtr) vnp1->data.ptrvalue;
13018       f2 = (FluCommentListPtr) vnp2->data.ptrvalue;
13019       if (f1 != NULL && f2 != NULL) {
13020         if (f1->biop == NULL && f2->biop == NULL) {
13021           rval = 0;
13022         } else if (f1->biop == NULL) {
13023           rval = -1;
13024         } else if (f2->biop == NULL) {
13025           rval = 1;
13026         } else if (f1->biop->org == NULL && f2->biop->org == NULL) {
13027           rval = 0;
13028         } else if (f1->biop->org == NULL) {
13029           rval = -1;
13030         } else if (f2->biop->org == NULL) {
13031           rval = 1;
13032         } else {
13033           rval = StringCmp (f1->biop->org->taxname, f2->biop->org->taxname);
13034         }
13035       }
13036     }
13037   }
13038   return rval;
13039 }
13040 
GetBioSourceAndSeqIdPairs(BioseqPtr bsp,Pointer data)13041 static void GetBioSourceAndSeqIdPairs (BioseqPtr bsp, Pointer data)
13042 {
13043   SeqDescrPtr sdp;
13044   SeqMgrDescContext context;
13045 
13046   if (bsp == NULL || ISA_aa (bsp->mol) || data == NULL) {
13047     return;
13048   }
13049 
13050   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &context);
13051   if (sdp != NULL) {
13052     ValNodeAddPointer ((ValNodePtr PNTR) data, 0, FluCommentListNew (bsp, sdp->data.ptrvalue));
13053   }
13054 }
13055 
13056 
MakeFluCommentIdList(ValNodePtr vnp_start,ValNodePtr vnp_end)13057 static CharPtr MakeFluCommentIdList (ValNodePtr vnp_start, ValNodePtr vnp_end)
13058 {
13059   FluCommentListPtr  f;
13060   ValNodePtr         id_list = NULL;
13061   ValNodePtr         vnp, vnp_a;
13062   Int4               prefix_len, count, last_number, new_number, id_len;
13063   Char               id_buf[255];
13064   CharPtr            id_start, id_next, last_id;
13065   SeqIdPtr           sip;
13066   Boolean            mismatch = FALSE;
13067   Int4               list_len = 0;
13068   CharPtr            list = NULL;
13069 
13070   if (vnp_start == NULL || vnp_start->next == vnp_end) {
13071     return NULL;
13072   }
13073 
13074   /* make temporary list of id strings */
13075   for (vnp_a = vnp_start; vnp_a != vnp_end; vnp_a = vnp_a->next) {
13076     f = (FluCommentListPtr) vnp_a->data.ptrvalue;
13077     sip = SeqIdFindBest (f->bsp->id, SEQID_GENBANK);
13078     SeqIdWrite (sip, id_buf, PRINTID_TEXTID_ACC_ONLY, sizeof (id_buf) - 1);
13079     ValNodeAddPointer (&id_list, 0, StringSave (id_buf));
13080   }
13081 
13082   /* sort id_list */
13083   id_list = ValNodeSort (id_list, SortVnpByString);
13084 
13085   /* calculate length of id list */
13086   vnp_a = id_list;
13087   while (vnp_a != NULL) {
13088     id_start = vnp_a->data.ptrvalue;
13089     list_len += StringLen (vnp_a->data.ptrvalue) + 2;
13090     prefix_len = StringCSpn (id_start, "1234567890");
13091     if (prefix_len == 0) {
13092       vnp_a = vnp_a->next;
13093     } else if (StringSpn (id_start + prefix_len, "1234567890") != StringLen (id_start + prefix_len)) {
13094       vnp_a = vnp_a->next;
13095     } else {
13096       last_number = atoi (id_start + prefix_len);
13097       count = 1;
13098       vnp = vnp_a->next;
13099       mismatch = FALSE;
13100       while (vnp != NULL && !mismatch) {
13101         id_next = vnp->data.ptrvalue;
13102         if (StringNICmp (id_next, id_start, prefix_len) != 0) {
13103           mismatch = TRUE;
13104         } else if (StringSpn (id_next + prefix_len, "1234567890") != StringLen (id_next + prefix_len)) {
13105           mismatch = TRUE;
13106         } else if ((new_number = atoi (id_next + prefix_len)) != last_number + 1) {
13107           mismatch = TRUE;
13108         } else {
13109           count++;
13110           last_number = new_number;
13111           id_len = StringLen (id_next);
13112           vnp = vnp->next;
13113         }
13114       }
13115       if (count > 1) {
13116         list_len += id_len + 2;
13117       }
13118       vnp_a = vnp;
13119     }
13120   }
13121 
13122   /* allocate memory */
13123   list = (CharPtr) MemNew (sizeof (Char) * list_len);
13124   list[0] = 0;
13125 
13126   /* make list */
13127   vnp_a = id_list;
13128   while (vnp_a != NULL) {
13129     if (list[0] != 0) {
13130       StringCat (list, ", ");
13131     }
13132     id_start = vnp_a->data.ptrvalue;
13133     StringCat (list, id_start);
13134     prefix_len = StringCSpn (id_start, "1234567890");
13135     if (prefix_len == 0) {
13136       vnp_a = vnp_a->next;
13137     } else if (StringSpn (id_start + prefix_len, "1234567890") != StringLen (id_start + prefix_len)) {
13138       vnp_a = vnp_a->next;
13139     } else {
13140       last_number = atoi (id_start + prefix_len);
13141       count = 1;
13142       vnp = vnp_a->next;
13143       mismatch = FALSE;
13144       while (vnp != NULL && !mismatch) {
13145         id_next = vnp->data.ptrvalue;
13146         if (StringNICmp (id_next, id_start, prefix_len) != 0) {
13147           mismatch = TRUE;
13148         } else if (StringSpn (id_next + prefix_len, "1234567890") != StringLen (id_next + prefix_len)) {
13149           mismatch = TRUE;
13150         } else if ((new_number = atoi (id_next + prefix_len)) != last_number + 1) {
13151           mismatch = TRUE;
13152         } else {
13153           count++;
13154           last_number = new_number;
13155           last_id = id_next;
13156           id_len = StringLen (id_next);
13157           vnp = vnp->next;
13158         }
13159       }
13160       if (count > 1) {
13161         if (count == 2) {
13162           StringCat (list, ", ");
13163           StringCat (list, last_id);
13164         } else {
13165           StringCat (list, "-");
13166           StringCat (list, last_id);
13167         }
13168       }
13169       vnp_a = vnp;
13170     }
13171   }
13172 
13173   id_list = ValNodeFreeData (id_list);
13174 
13175   return list;
13176 }
13177 
13178 
AddCommentsToList(ValNodePtr vnp_start,ValNodePtr vnp_end,CharPtr last_taxname)13179 static void AddCommentsToList (ValNodePtr vnp_start, ValNodePtr vnp_end, CharPtr last_taxname)
13180 {
13181   CharPtr            id_list_txt;
13182   CharPtr            comment_fmt = "GenBank Accession Numbers %s represent sequences from the %d segments of %s";
13183   CharPtr            comment;
13184   Int4               num_segments = 0;
13185   SeqDescrPtr        sdp;
13186   FluCommentListPtr  f;
13187   ValNodePtr         vnp_a;
13188 
13189   if (vnp_start == NULL || StringHasNoText (last_taxname)) {
13190     return;
13191   } else if (vnp_start->next == vnp_end) {
13192     /* only one in the group, don't bother with comment */
13193   } else {
13194     /* get number of segments */
13195     for (vnp_a = vnp_start; vnp_a != vnp_end; vnp_a = vnp_a->next) {
13196       num_segments++;
13197     }
13198 
13199     id_list_txt = MakeFluCommentIdList (vnp_start, vnp_end);
13200 
13201     /* make comment */
13202     comment = (CharPtr) MemNew (sizeof (Char) * (StringLen (comment_fmt) + 15 + StringLen (id_list_txt) + StringLen (last_taxname) ));
13203     sprintf (comment, comment_fmt, id_list_txt, num_segments, last_taxname);
13204     id_list_txt = MemFree (id_list_txt);
13205     /* add comments */
13206     for (vnp_a = vnp_start; vnp_a != vnp_end; vnp_a = vnp_a->next) {
13207       f = (FluCommentListPtr) vnp_a->data.ptrvalue;
13208       if (f != NULL && f->bsp != NULL) {
13209         sdp = CreateNewDescriptorOnBioseq (f->bsp, Seq_descr_comment);
13210         sdp->data.ptrvalue = StringSave (comment);
13211       }
13212     }
13213     comment = MemFree (comment);
13214   }
13215 }
13216 
13217 
AddFluComments(IteM i)13218 NLM_EXTERN void AddFluComments (IteM i)
13219 {
13220   BaseFormPtr        bfp;
13221   SeqEntryPtr        sep;
13222   ValNodePtr         list = NULL, vnp, vnp_start;
13223   CharPtr            last_taxname = NULL;
13224   FluCommentListPtr  f;
13225 
13226 #ifdef WIN_MAC
13227   bfp = currentFormDataPtr;
13228 #else
13229   bfp = GetObjectExtra (i);
13230 #endif
13231   if (bfp == NULL)
13232     return;
13233 
13234   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13235   if (sep == NULL)
13236     return;
13237 
13238   /* get list of biosources and sequence IDs */
13239   VisitBioseqsInSep (sep, &list, GetBioSourceAndSeqIdPairs);
13240   /* sort so that identical organisms are together */
13241   list = ValNodeSort (list, SortFluCommentList);
13242   /* create comments for all sequences with the same organism name */
13243   vnp_start = NULL;
13244   vnp = list;
13245   while (vnp != NULL) {
13246     f = (FluCommentListPtr) vnp->data.ptrvalue;
13247 
13248     if (f == NULL || f->biop == NULL || f->biop->org == NULL) {
13249       /* skip this one */
13250     } else if (last_taxname == NULL) {
13251       last_taxname = f->biop->org->taxname;
13252       vnp_start = vnp;
13253     } else if (StringCmp (last_taxname, f->biop->org->taxname) != 0) {
13254       if (vnp_start->next == vnp) {
13255         /* only one in the group, don't bother with comment */
13256       } else {
13257         AddCommentsToList (vnp_start, vnp, last_taxname);
13258       }
13259       vnp_start = vnp;
13260       f = (FluCommentListPtr) vnp->data.ptrvalue;
13261       last_taxname = f->biop->org->taxname;
13262     }
13263     vnp = vnp->next;
13264   }
13265   AddCommentsToList (vnp_start, NULL, last_taxname);
13266 
13267   list = ValNodeFreeData (list);
13268 
13269   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13270   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13271 }
13272 
13273 
13274 static CharPtr RNA_words[] = {
13275   "ITS1",
13276   "ITS2",
13277   "internal transcribed spacer 1",
13278   "internal transcribed spacer 2",
13279   "5.8S",
13280   "16S",
13281   "18S",
13282   "28S",
13283   "5.8S ribosomal RNA",
13284   "16S ribosomal RNA",
13285   "18S ribosomal RNA",
13286   "28S ribosomal RNA"
13287 };
13288 
13289 static const Int4 k_num_RNA_words = sizeof (RNA_words) / sizeof (CharPtr);
13290 
13291 
RNAWordsFromString(CharPtr str,TextFsaPtr tags)13292 static ValNodePtr RNAWordsFromString (CharPtr str, TextFsaPtr tags)
13293 {
13294   Int4        state;
13295   Char        ch;
13296   CharPtr     ptr;
13297   ValNodePtr  matches;
13298   CharPtr     last_hit = NULL, last_pos = NULL;
13299   Int4        match_len;
13300   ValNodePtr  tokens = NULL, last_match = NULL;
13301 
13302   if (StringHasNoText (str) || tags == NULL) {
13303     return NULL;
13304   }
13305 
13306   state = 0;
13307   ptr = str;
13308   ch = *ptr;
13309   while (ch != '\0') {
13310     matches = NULL;
13311     state = TextFsaNext (tags, state, ch, &matches);
13312     if (matches != NULL && (isspace (*(ptr + 1)) || ispunct (*(ptr + 1)) || *(ptr + 1) == 0) && (match_len = StringLen (matches->data.ptrvalue)) > 0
13313         && (ptr - match_len + 1 == str || isspace (*(ptr - match_len)) || ispunct (*(ptr - match_len)))) {
13314       if (last_match == NULL || last_match->data.ptrvalue != ptr - match_len + 1) {
13315         last_match = ValNodeAddPointer (&tokens, 0, ptr - match_len + 1);
13316       }
13317       last_pos = ptr;
13318       last_hit = (CharPtr) matches->data.ptrvalue;
13319     }
13320     ptr++;
13321     ch = *ptr;
13322   }
13323   return tokens;
13324 }
13325 
13326 
ExpandFeatureForIntervals(SeqFeatPtr sfp)13327 static void ExpandFeatureForIntervals (SeqFeatPtr sfp)
13328 {
13329   SeqLocPtr   slp, slp_next, orig;
13330   SeqFeatPtr  sfp_new;
13331   Boolean     part5, part3;
13332 
13333   orig = sfp->location;
13334   sfp->location = orig->data.ptrvalue;
13335   orig->data.ptrvalue = NULL;
13336   orig = SeqLocFree (orig);
13337   slp = sfp->location->next;
13338   sfp->location->next = NULL;
13339   sfp->partial = CheckSeqLocForPartial (sfp->location, &part5, &part3);
13340   while (slp != NULL) {
13341     sfp_new = SeqFeatCopy (sfp);
13342     sfp_new->next = sfp->next;
13343     sfp->next = sfp_new;
13344     sfp_new->location = SeqLocFree (sfp_new->location);
13345     slp_next = slp->next;
13346     slp->next = NULL;
13347     sfp_new->location = slp;
13348     sfp_new->partial = CheckSeqLocForPartial (sfp_new->location, &part5, &part3);
13349     slp = slp_next;
13350     sfp = sfp_new;
13351   }
13352 }
13353 
13354 
13355 /* TODO - for each string, remove trailing delimiters and spaces, replace abbreviations */
13356 
FixExplodedRNAProduct(CharPtr PNTR pProduct)13357 static void FixExplodedRNAProduct (CharPtr PNTR pProduct)
13358 {
13359   CharPtr cp;
13360   Int4    len, i;
13361   Char    repl_buf[200];
13362   CharPtr repl_fmt = "%s ribosomal RNA";
13363 
13364   if (pProduct == NULL || *pProduct == NULL || StringHasNoText (*pProduct)) {
13365     return;
13366   }
13367 
13368   FindReplaceString (pProduct, " and ", "", FALSE, FALSE);
13369 
13370   len = StringLen (*pProduct);
13371   cp = *pProduct + len - 1;
13372 
13373   while (ispunct (*cp) || isspace (*cp)) {
13374     *cp = 0;
13375     cp--;
13376   }
13377 
13378   if (StringStr (*pProduct, " ribosomal RNA") != NULL || StringStr (*pProduct, "internal transcribed spacer") != NULL) {
13379     return;
13380   }
13381   for (i = 2; i < k_num_RNA_words; i++) {
13382     sprintf (repl_buf, repl_fmt, RNA_words[i]);
13383     FindReplaceString (pProduct, RNA_words[i], repl_buf, FALSE, TRUE);
13384   }
13385 }
13386 
13387 
FixOneExplodedRNA(SeqFeatPtr sfp,CharPtr new_product,Int4 len)13388 static void FixOneExplodedRNA (SeqFeatPtr sfp, CharPtr new_product, Int4 len)
13389 {
13390   RnaRefPtr rrp;
13391   RNAGenPtr rgp;
13392   CharPtr   adjusted_product;
13393 
13394   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || (rrp = (RnaRefPtr) sfp->data.value.ptrvalue) == NULL) {
13395     return;
13396   }
13397 
13398   if (len < 0) {
13399     adjusted_product = StringSave (new_product);
13400   } else {
13401     adjusted_product = (CharPtr) MemNew (sizeof (Char) * (len + 1));
13402     StringNCpy (adjusted_product, new_product, len);
13403     adjusted_product[len] = 0;
13404   }
13405   FixExplodedRNAProduct (&adjusted_product);
13406 
13407   if (rrp->ext.choice == 1) {
13408     rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
13409     rrp->ext.value.ptrvalue = adjusted_product;
13410   } else if (rrp->ext.choice == 3) {
13411     rgp = rrp->ext.value.ptrvalue;
13412     rgp->product = MemFree (rgp->product);
13413     rgp->product = StringSave (adjusted_product);
13414   } else if (rrp->ext.choice == 0) {
13415     rrp->ext.choice = 1;
13416     rrp->ext.value.ptrvalue = adjusted_product;
13417   }
13418   if (StringStr (adjusted_product, "internal transcribed spacer") != NULL) {
13419     rrp->type = RNA_TYPE_other;
13420   } else {
13421     rrp->type = RNA_TYPE_rRNA;
13422   }
13423 }
13424 
13425 
ExplodeRNACallback(SeqFeatPtr sfp,Pointer data)13426 static void ExplodeRNACallback (SeqFeatPtr sfp, Pointer data)
13427 {
13428   TextFsaPtr  tags;
13429   Int4        num_interval = 0;
13430   SeqLocPtr   tmp;
13431   ValNodePtr  tokens = NULL, vnp;
13432   RnaRefPtr   rrp;
13433   RNAGenPtr   rgp;
13434   SeqFeatPtr  sfp_new;
13435   CharPtr     orig_product;
13436 
13437   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || (tags = (TextFsaPtr) data) == NULL
13438       || sfp->location == NULL
13439       || (sfp->location->choice != SEQLOC_MIX && sfp->location->choice != SEQLOC_PACKED_INT)) {
13440     return;
13441   }
13442 
13443   for (tmp = sfp->location->data.ptrvalue; tmp != NULL; tmp = tmp->next) {
13444     num_interval++;
13445   }
13446 
13447   if (!StringHasNoText (sfp->comment)
13448       && (tokens = RNAWordsFromString (sfp->comment, tags)) != NULL
13449       && (num_interval == ValNodeLen (tokens))) {
13450     orig_product = sfp->comment;
13451     sfp->comment = NULL;
13452     ExpandFeatureForIntervals (sfp);
13453     for (vnp = tokens, sfp_new = sfp; vnp != NULL && sfp_new != NULL; vnp = vnp->next, sfp_new = sfp_new->next) {
13454       FixOneExplodedRNA (sfp_new, vnp->data.ptrvalue,
13455                          vnp->next == NULL ? -1 : (CharPtr)vnp->next->data.ptrvalue - (CharPtr) vnp->data.ptrvalue);
13456     }
13457     tokens = ValNodeFree (tokens);
13458     orig_product = MemFree (orig_product);
13459   } else if ((rrp = (RnaRefPtr) sfp->data.value.ptrvalue) != NULL) {
13460     if (rrp->ext.choice == 1) {
13461       orig_product = rrp->ext.value.ptrvalue;
13462       rrp->ext.value.ptrvalue = NULL;
13463       tokens = RNAWordsFromString (orig_product, tags);
13464       if (num_interval == ValNodeLen (tokens)) {
13465         ExpandFeatureForIntervals (sfp);
13466         for (vnp = tokens, sfp_new = sfp; vnp != NULL && sfp_new != NULL; vnp = vnp->next, sfp_new = sfp_new->next) {
13467           FixOneExplodedRNA (sfp_new, vnp->data.ptrvalue,
13468                              vnp->next == NULL ? -1 : (CharPtr)vnp->next->data.ptrvalue - (CharPtr) vnp->data.ptrvalue);
13469         }
13470       }
13471       tokens = ValNodeFree (tokens);
13472       orig_product = MemFree (orig_product);
13473     } else if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL) {
13474       orig_product = rgp->product;
13475       rgp->product = NULL;
13476       tokens = RNAWordsFromString (orig_product, tags);
13477       if (num_interval == ValNodeLen (tokens)) {
13478         ExpandFeatureForIntervals (sfp);
13479         for (vnp = tokens, sfp_new = sfp; vnp != NULL && sfp_new != NULL; vnp = vnp->next, sfp_new = sfp_new->next) {
13480           FixOneExplodedRNA (sfp_new, vnp->data.ptrvalue,
13481                              vnp->next == NULL ? -1 : (CharPtr)vnp->next->data.ptrvalue - (CharPtr) vnp->data.ptrvalue);
13482         }
13483       }
13484       tokens = ValNodeFree (tokens);
13485       orig_product = MemFree (orig_product);
13486     }
13487   }
13488 }
13489 
13490 
ExplodeRNA(IteM i)13491 NLM_EXTERN void ExplodeRNA (IteM i)
13492 {
13493   BaseFormPtr        bfp;
13494   SeqEntryPtr        sep;
13495   TextFsaPtr         tags;
13496   Int4               j;
13497 
13498 #ifdef WIN_MAC
13499   bfp = currentFormDataPtr;
13500 #else
13501   bfp = GetObjectExtra (i);
13502 #endif
13503   if (bfp == NULL)
13504     return;
13505 
13506   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13507   if (sep == NULL)
13508     return;
13509 
13510 
13511   tags = TextFsaNew();
13512 
13513   for (j = 0; j < k_num_RNA_words; j++) {
13514     TextFsaAdd (tags, RNA_words[j]);
13515   }
13516 
13517   VisitFeaturesInSep (sep, tags, ExplodeRNACallback);
13518 
13519   tags = TextFsaFree (tags);
13520 
13521   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13522   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13523 }
13524 
13525 
RemoveFeaturesLikeGapsCallback(BioseqPtr bsp,Pointer userdata)13526 static void RemoveFeaturesLikeGapsCallback (BioseqPtr bsp, Pointer userdata)
13527 {
13528   SeqFeatPtr           sfp, gap_feat;
13529   SeqMgrFeatContext    context;
13530   DeltaSeqPtr          dsp;
13531   SeqLitPtr            slip;
13532   SeqLocPtr            slp;
13533   Int4                 pos = 0, len;
13534   CharPtr              new_note;
13535   ImpFeatPtr           imp;
13536   GBQualPtr            gbq;
13537   Char                 buf[15];
13538 
13539   if (bsp == NULL || bsp->repr != Seq_repr_delta) {
13540     return;
13541   }
13542 
13543   dsp = (DeltaSeqPtr)(bsp->seq_ext);
13544   sfp = SeqMgrGetNextFeature(bsp, NULL, 0, 0, &context);
13545   while (dsp != NULL && sfp != NULL) {
13546     while (dsp != NULL && !IsDeltaSeqGap(dsp)) {
13547       if (dsp->choice == 1) {
13548         pos += SeqLocLen (dsp->data.ptrvalue);
13549       } else if (dsp->choice == 2) {
13550         pos += ((SeqLitPtr)dsp->data.ptrvalue)->length;
13551       }
13552       dsp = dsp->next;
13553     }
13554     if (dsp != NULL) {
13555       slip = (SeqLitPtr)dsp->data.ptrvalue;
13556       len = slip->length;
13557       while (context.left < pos && sfp != NULL) {
13558         sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
13559       }
13560       if (sfp != NULL) {
13561         gap_feat = NULL;
13562         new_note = NULL;
13563         while (context.left == pos && sfp != NULL) {
13564           if (context.right == pos + len - 1) {
13565             if (sfp->idx.subtype == FEATDEF_gap) {
13566               if (!context.external) {
13567                 gap_feat = sfp;
13568               }
13569             } else {
13570               if (sfp->comment != NULL) {
13571                 SetStringValue(&new_note, sfp->comment, ExistingTextOption_append_semi);
13572               }
13573               sfp->idx.deleteme = TRUE;
13574             }
13575           }
13576           sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
13577         }
13578         /* only need to instantiate gap if there is a note to add */
13579         if (new_note != NULL) {
13580           if (gap_feat == NULL) {
13581             slp = SeqLocIntNew (pos, pos + len - 1, Seq_strand_plus, SeqIdFindWorst (bsp->id));
13582             gap_feat = CreateNewFeatureOnBioseq (bsp, SEQFEAT_IMP, slp);
13583             imp = ImpFeatNew ();
13584             imp->key = StringSave ("gap");
13585             gap_feat->data.value.ptrvalue = imp;
13586             gbq = GBQualNew();
13587             gbq->qual = StringSave("estimated_length");
13588             if (slip->fuzz != NULL) {
13589               gbq->val = StringSave("unknown");
13590             } else {
13591               sprintf (buf, "%d", slip->length);
13592               gbq->val = StringSave(buf);
13593             }
13594             gbq->next = gap_feat->qual;
13595             gap_feat->qual = gbq;
13596           }
13597           if (gap_feat->comment == NULL) {
13598             gap_feat->comment = new_note;
13599           } else {
13600             SetStringValue (&(gap_feat->comment), new_note, ExistingTextOption_append_semi);
13601             new_note = MemFree (new_note);
13602           }
13603         }
13604       }
13605       pos += len;
13606       dsp = dsp->next;
13607     }
13608   }
13609 }
13610 
13611 
RemoveFeaturesLikeGaps(IteM i)13612 NLM_EXTERN void RemoveFeaturesLikeGaps (IteM i)
13613 {
13614   BaseFormPtr          bfp;
13615   SeqEntryPtr          sep;
13616 
13617 #ifdef WIN_MAC
13618   bfp = currentFormDataPtr;
13619 #else
13620   bfp = GetObjectExtra (i);
13621 #endif
13622   if (bfp == NULL) {
13623     return;
13624   }
13625 
13626   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13627   VisitBioseqsInSep (sep, NULL, RemoveFeaturesLikeGapsCallback);
13628 
13629   DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
13630   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13631   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13632 }
13633 
13634 
SplitPCRPrimersByPositionMenuItem(IteM i)13635 NLM_EXTERN void SplitPCRPrimersByPositionMenuItem (IteM i)
13636 {
13637   BaseFormPtr          bfp;
13638   SeqEntryPtr          sep;
13639 
13640 #ifdef WIN_MAC
13641   bfp = currentFormDataPtr;
13642 #else
13643   bfp = GetObjectExtra (i);
13644 #endif
13645   if (bfp == NULL) {
13646     return;
13647   }
13648 
13649   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13650   SplitPCRPrimersByPosition (sep);
13651 
13652   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13653   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13654 }
13655 
13656 
13657 typedef struct splitpcrprimersbyconstraintform {
13658   FORM_MESSAGE_BLOCK
13659 
13660   DialoG fwd_constraint;
13661   DialoG rev_constraint;
13662 } SplitPCRPrimersByConstraintFormData, PNTR SplitPCRPrimersByConstraintFormPtr;
13663 
13664 
SplitPCRPrimersByConstraintAccept(ButtoN b)13665 static void SplitPCRPrimersByConstraintAccept (ButtoN b)
13666 {
13667   SplitPCRPrimersByConstraintFormPtr frm;
13668   StringConstraintPtr fwd_scp, rev_scp;
13669   SeqEntryPtr sep;
13670 
13671   frm = (SplitPCRPrimersByConstraintFormPtr) GetObjectExtra (b);
13672   if (frm == NULL) {
13673     return;
13674   }
13675 
13676   fwd_scp = DialogToPointer (frm->fwd_constraint);
13677   rev_scp = DialogToPointer (frm->rev_constraint);
13678   sep = GetTopSeqEntryForEntityID (frm->input_entityID);
13679 
13680   SplitPCRPrimersByConstraints (sep, fwd_scp, rev_scp);
13681   fwd_scp = StringConstraintFree (fwd_scp);
13682   rev_scp = StringConstraintFree (rev_scp);
13683   ObjMgrSetDirtyFlag (frm->input_entityID, TRUE);
13684   ObjMgrSendMsg (OM_MSG_UPDATE, frm->input_entityID, 0, 0);
13685   Remove (frm->form);
13686 }
13687 
13688 
SplitPCRPrimersByConstraintsMenuItem(IteM i)13689 NLM_EXTERN void SplitPCRPrimersByConstraintsMenuItem (IteM i)
13690 {
13691   BaseFormPtr          bfp;
13692   SplitPCRPrimersByConstraintFormPtr frm;
13693   WindoW              w;
13694   GrouP               h, g, c;
13695   ButtoN              b;
13696   PrompT              ppt;
13697 
13698 #ifdef WIN_MAC
13699   bfp = currentFormDataPtr;
13700 #else
13701   bfp = GetObjectExtra (i);
13702 #endif
13703   if (bfp == NULL) {
13704     return;
13705   }
13706 
13707   frm = (SplitPCRPrimersByConstraintFormPtr) MemNew (sizeof (SplitPCRPrimersByConstraintFormData));
13708 
13709   w = FixedWindow (-50, -33, -10, -10, "Convert BioSource Dbxrefs to Feature Dbxrefs", StdCloseWindowProc);
13710   SetObjectExtra (w, frm, StdCleanupExtraProc);
13711   frm->form = (ForM) w;
13712   frm->input_entityID = bfp->input_entityID;
13713 
13714   h = HiddenGroup (w, -1, 0, NULL);
13715   SetGroupSpacing (h, 10, 10);
13716 
13717   ppt = StaticPrompt (h, "Choose string constraints for forward and reverse primer names for new sets", 0, dialogTextHeight, programFont, 'l');
13718   g = HiddenGroup (h, 0, 2, NULL);
13719   SetGroupSpacing (g, 10, 10);
13720   frm->fwd_constraint = StringConstraintDialog (g, "Forward", FALSE, NULL, NULL);
13721   frm->rev_constraint = StringConstraintDialog (g, "Reverse", FALSE, NULL, NULL);
13722 
13723   c = HiddenGroup (h, 2, 0, NULL);
13724   b = PushButton (c, "Accept", SplitPCRPrimersByConstraintAccept);
13725   SetObjectExtra (b, frm, NULL);
13726   PushButton (c, "Cancel", StdCancelButtonProc);
13727   AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) g, (HANDLE) c, NULL);
13728   Show (w);
13729   Select (w);
13730 }
13731 
13732 
MergePCRPrimerSetsMenuItem(IteM i)13733 NLM_EXTERN void MergePCRPrimerSetsMenuItem (IteM i)
13734 {
13735   BaseFormPtr          bfp;
13736   SeqEntryPtr          sep;
13737 
13738 #ifdef WIN_MAC
13739   bfp = currentFormDataPtr;
13740 #else
13741   bfp = GetObjectExtra (i);
13742 #endif
13743   if (bfp == NULL) {
13744     return;
13745   }
13746 
13747   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13748   MergePCRPrimers (sep);
13749 
13750   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13751   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13752 }
13753 
13754 
ConvertToDelayedGenProdSetQualifiersCallback(SeqFeatPtr sfp,Pointer data)13755 static void ConvertToDelayedGenProdSetQualifiersCallback (SeqFeatPtr sfp, Pointer data)
13756 {
13757   GBQualPtr gbq;
13758 
13759   if (sfp == NULL) {
13760     return;
13761   } else if (sfp->idx.subtype != FEATDEF_CDS && sfp->idx.subtype != FEATDEF_mRNA) {
13762     return;
13763   }
13764 
13765   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
13766     if (StringICmp (gbq->qual, "protein_id") == 0) {
13767       gbq->qual = MemFree (gbq->qual);
13768       gbq->qual = StringSave ("orig_protein_id");
13769     } else if (StringICmp (gbq->qual, "transcript_id") == 0) {
13770       gbq->qual = MemFree (gbq->qual);
13771       gbq->qual = StringSave ("orig_transcript_id");
13772     }
13773   }
13774 }
13775 
13776 
ConvertToDelayedGenProdSetQualifiers(IteM i)13777 NLM_EXTERN void ConvertToDelayedGenProdSetQualifiers (IteM i)
13778 {
13779   BaseFormPtr          bfp;
13780   SeqEntryPtr          sep;
13781 
13782 #ifdef WIN_MAC
13783   bfp = currentFormDataPtr;
13784 #else
13785   bfp = GetObjectExtra (i);
13786 #endif
13787   if (bfp == NULL) {
13788     return;
13789   }
13790 
13791   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
13792   VisitFeaturesInSep (sep, NULL, ConvertToDelayedGenProdSetQualifiersCallback);
13793   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
13794   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
13795 }
13796 
13797 
13798 #define NUM_FEAT_ED_PAGES 2
13799 
13800 #define NUM_FEAT_ED_ACTIONS 8
13801 
13802 typedef struct feated
13803 {
13804   FORM_MESSAGE_BLOCK
13805   DialoG  feature_type;
13806   DialoG  constraint;
13807   DialoG  accept_cancel;
13808 
13809   /* for evidence */
13810   Int4    evidence_val;
13811 
13812   /* for exceptions */
13813   PopuP   explanation_choice;
13814   ButtoN  move_to_comment;
13815   GrouP   product_choice;
13816   TexT    other_explanation;
13817   CharPtr explanation_text;
13818   Boolean do_move_to_comment;
13819   Int4    product_val;
13820 
13821   /* for partials */
13822   PopuP  convert_choice;
13823   PopuP  partial5_choice;
13824   ButtoN extend5_btn;
13825   PopuP  partial3_choice;
13826   ButtoN extend3_btn;
13827   ButtoN retranslate_btn;
13828   ButtoN adjust_gene_btn;
13829   Int4   orderjoinpolicy;
13830   Int4   leftpolicy;
13831   Int4   rightpolicy;
13832   Boolean extend5;
13833   Boolean extend3;
13834   Boolean retranslate;
13835   Boolean adjust_gene;
13836 
13837   /* for strand */
13838   PopuP  from_strand;
13839   PopuP  to_strand;
13840   Uint1  from_strand_val;
13841   Uint1  to_strand_val;
13842 
13843   GrouP  action_grps [NUM_FEAT_ED_ACTIONS];
13844   ButtoN action_btns [NUM_FEAT_ED_ACTIONS];
13845   GrouP  action_choice_grp;
13846 
13847   /* for citations */
13848   DialoG     citation_list;
13849   ButtoN     explanation_constraint;
13850   PopuP      explanation_constraint_choice;
13851   ButtoN     citation_translation;
13852   Boolean    use_explanation_constraint;
13853   Int4       explanation_constraint_choice_val;
13854   Boolean    use_product_match;
13855 
13856   /* for experiment */
13857   GrouP      experiment_action;
13858   TexT       experiment_text;
13859 
13860   /* for pseudo */
13861   PopuP      pseudo_action;
13862   Boolean    pseudo_val;
13863   CharPtr    pseudo_str;
13864 
13865   /* for inferences */
13866   DialoG     inference_dlg;
13867 } FeatEdData, PNTR FeatEdPtr;
13868 
13869 
FeatEdChangeNotify(Pointer userdata)13870 static void FeatEdChangeNotify (Pointer userdata)
13871 {
13872   FeatEdPtr mp;
13873   ValNodePtr      err_list = NULL;
13874   CharPtr         str;
13875 
13876   mp = (FeatEdPtr) userdata;
13877   if (mp == NULL) return;
13878 
13879   if (mp->explanation_choice != NULL)
13880   {
13881     if (GetValue (mp->explanation_choice) == 9
13882         && ((mp->action_btns[1] == NULL && mp->action_choice_grp == NULL)
13883             || (mp->action_btns[1] != NULL && GetStatus (mp->action_btns[1]))
13884             || (mp->action_choice_grp != NULL && GetValue (mp->action_choice_grp) == 2)))
13885     {
13886       Enable (mp->other_explanation);
13887       str = SaveStringFromText (mp->other_explanation);
13888       if (StringHasNoText (str))
13889       {
13890         DisableAcceptCancelDialogAccept (mp->accept_cancel);
13891         str = MemFree (str);
13892         return;
13893       }
13894       str = MemFree (str);
13895     }
13896     else
13897     {
13898       Disable (mp->other_explanation);
13899     }
13900   }
13901 
13902   if (GetValue (mp->action_choice_grp) == FEAT_ED_INFERENCE)
13903   {
13904     ValNodeLink (&err_list, TestDialog (mp->inference_dlg));
13905   }
13906 
13907   if (err_list == NULL)
13908   {
13909     EnableAcceptCancelDialogAccept (mp->accept_cancel);
13910   }
13911   else
13912   {
13913     DisableAcceptCancelDialogAccept (mp->accept_cancel);
13914   }
13915   ValNodeFree (err_list);
13916 }
13917 
13918 
FeatEdClear(Pointer data)13919 static void FeatEdClear (Pointer data)
13920 {
13921   FeatEdPtr mp;
13922 
13923   mp = (FeatEdPtr) data;
13924   if (mp == NULL) return;
13925 
13926   SetFeatureTypeInFeatureTypeDialog(mp->feature_type, Macro_feature_type_any);
13927   PointerToDialog (mp->constraint, NULL);
13928 
13929   if (mp->explanation_choice != NULL)
13930   {
13931     SetValue (mp->explanation_choice, 1);
13932   }
13933   if (mp->move_to_comment != NULL)
13934   {
13935     SetStatus (mp->move_to_comment, FALSE);
13936   }
13937   if (mp->product_choice != NULL)
13938   {
13939     SetValue (mp->product_choice, 3);
13940   }
13941   if (mp->other_explanation != NULL)
13942   {
13943     SetTitle (mp->other_explanation, "");
13944     Disable (mp->other_explanation);
13945   }
13946 
13947   if (mp->convert_choice != NULL)
13948   {
13949     SetValue (mp->convert_choice, 1);
13950   }
13951   if (mp->partial5_choice != NULL)
13952   {
13953     SetValue (mp->partial5_choice, 8);
13954   }
13955   if (mp->extend5_btn != NULL)
13956   {
13957     SetStatus (mp->extend5_btn, FALSE);
13958   }
13959   if (mp->partial3_choice != NULL)
13960   {
13961     SetValue (mp->partial3_choice, 7);
13962   }
13963   if (mp->extend3_btn != NULL)
13964   {
13965     SetStatus (mp->extend3_btn, FALSE);
13966   }
13967   if (mp->retranslate_btn != NULL)
13968   {
13969     SetStatus (mp->retranslate_btn, FALSE);
13970   }
13971   if (mp->adjust_gene_btn != NULL)
13972   {
13973     SetStatus (mp->adjust_gene_btn, FALSE);
13974   }
13975 
13976   /* for strand */
13977   if (mp->from_strand != NULL)
13978   {
13979     SetValue (mp->from_strand, 1);
13980   }
13981   if (mp->to_strand != NULL)
13982   {
13983     SetValue (mp->to_strand, 1);
13984   }
13985 
13986   /* for experiment */
13987   if (mp->experiment_text != NULL)
13988   {
13989     SetTitle (mp->experiment_text, "");
13990   }
13991 
13992   /* for pseudo */
13993   if (mp->pseudo_action != NULL)
13994   {
13995     SetValue (mp->pseudo_action, 1);
13996   }
13997 
13998   FeatEdChangeNotify (mp);
13999 }
14000 
14001 
FeatEdClearText(Pointer data)14002 static void FeatEdClearText (Pointer data)
14003 {
14004   FeatEdPtr     mp;
14005 
14006   mp = (FeatEdPtr) data;
14007   if (mp == NULL) return;
14008 
14009   /* for explanation */
14010   if (mp->other_explanation != NULL)
14011   {
14012     SetTitle (mp->other_explanation, "");
14013   }
14014 
14015   /* for experiment */
14016   if (mp->experiment_text != NULL)
14017   {
14018     SetTitle (mp->experiment_text, "");
14019   }
14020 
14021   FeatEdChangeNotify (mp);
14022 }
14023 
FeaturePseudoGroup(GrouP h,FeatEdPtr mp)14024 static GrouP FeaturePseudoGroup (GrouP h, FeatEdPtr mp)
14025 {
14026   GrouP g;
14027 
14028   if (mp == NULL)
14029   {
14030     return NULL;
14031   }
14032 
14033   g = HiddenGroup (h, 0, 0, NULL);
14034   mp->pseudo_action = PopupList (g, TRUE, NULL);
14035   InitEnumPopup (mp->pseudo_action, legacy_pseudogene_alist, NULL);
14036 
14037   return g;
14038 }
14039 
FeatureEvidenceGroup(GrouP h,FeatEdPtr mp)14040 static GrouP FeatureEvidenceGroup (GrouP h, FeatEdPtr mp)
14041 {
14042   GrouP g;
14043 
14044   if (mp == NULL)
14045   {
14046     return NULL;
14047   }
14048 
14049   g = HiddenGroup (h, 2, 0, NULL);
14050   SetGroupSpacing (g, 10, 10);
14051 
14052   StaticPrompt (g, "Click Accept to clear feature evidence.", 0, dialogTextHeight, systemFont, 'l');
14053 
14054   return g;
14055 }
14056 
14057 
FeatExplanationChange(PopuP p)14058 static void FeatExplanationChange (PopuP p)
14059 {
14060   FeatEdPtr mp;
14061 
14062   mp = (FeatEdPtr) GetObjectExtra (p);
14063   if (mp == NULL) return;
14064 
14065   if (GetValue (mp->explanation_choice) == 9)
14066   {
14067     Enable (mp->other_explanation);
14068   }
14069   else
14070   {
14071     Disable (mp->other_explanation);
14072   }
14073 
14074   FeatEdChangeNotify (mp);
14075 }
14076 
FeatOtherExplanationChange(TexT t)14077 static void FeatOtherExplanationChange (TexT t)
14078 {
14079   FeatEdPtr mp;
14080 
14081   mp = (FeatEdPtr) GetObjectExtra (t);
14082   FeatEdChangeNotify (mp);
14083 }
14084 
14085 static CharPtr exception_explanations[] =
14086 {
14087   "RNA Editing", "reasons given in citation", "ribosomal slippage",
14088   "trans splicing", "artificial frameshift", "nonconsensus splice site",
14089   "rearrangement required", "other->"
14090 };
14091 
14092 static Int4 num_exception_explanations = sizeof (exception_explanations) / sizeof (CharPtr);
14093 
FeatureExceptionGroup(GrouP h,FeatEdPtr mp)14094 static GrouP FeatureExceptionGroup (GrouP h, FeatEdPtr mp)
14095 {
14096   GrouP  g, k1, k2;
14097   Int4   i;
14098 
14099   if (mp == NULL)
14100   {
14101     return NULL;
14102   }
14103   g = HiddenGroup (h, -1, 0, NULL);
14104   SetGroupSpacing (g, 10, 10);
14105 
14106   k1 = HiddenGroup (g, 3, 0, NULL);
14107   SetGroupSpacing (k1, 10, 10);
14108   StaticPrompt (k1, "Set Explanation to ", 0, dialogTextHeight, systemFont, 'l');
14109   mp->explanation_choice = PopupList (k1, TRUE, FeatExplanationChange);
14110   SetObjectExtra (mp->explanation_choice, mp, NULL);
14111   PopupItem (mp->explanation_choice, " ");
14112   for (i = 0; i < num_exception_explanations; i++)
14113   {
14114     PopupItem (mp->explanation_choice, exception_explanations [i]);
14115   }
14116   SetValue (mp->explanation_choice, 1);
14117   mp->other_explanation = DialogText (k1, "", 10, FeatOtherExplanationChange);
14118   Disable (mp->other_explanation);
14119   SetObjectExtra (mp->other_explanation, mp, NULL);
14120 
14121   k2 = HiddenGroup (g, 2, 0, NULL);
14122   SetGroupSpacing (k2, 10, 10);
14123   StaticPrompt (k2, "Where feature product is", 0, dialogTextHeight, systemFont, 'l');
14124   mp->product_choice = HiddenGroup (k2, 3, 0, NULL);
14125   RadioButton (mp->product_choice, "Present");
14126   RadioButton (mp->product_choice, "Absent");
14127   RadioButton (mp->product_choice, "Either");
14128   SetValue (mp->product_choice, 3);
14129 
14130   mp->move_to_comment = CheckBox (g, "Move explanation to comment", NULL);
14131 
14132   AlignObjects (ALIGN_CENTER, (HANDLE) k1,
14133                               (HANDLE) k2,
14134                               (HANDLE) mp->move_to_comment,
14135                               NULL);
14136 
14137   return g;
14138 }
14139 
ChangeExplanationConstraint(ButtoN b)14140 static void ChangeExplanationConstraint (ButtoN b)
14141 {
14142   FeatEdPtr mp;
14143 
14144   mp = (FeatEdPtr) GetObjectExtra (b);
14145   if (mp == NULL)
14146   {
14147     return;
14148   }
14149   if (GetStatus (mp->explanation_constraint))
14150   {
14151     Enable (mp->explanation_constraint_choice);
14152   }
14153   else
14154   {
14155     Disable (mp->explanation_constraint_choice);
14156   }
14157 }
14158 
FeatureEditorCitationGroup(GrouP h,FeatEdPtr mp)14159 static GrouP FeatureEditorCitationGroup (GrouP h, FeatEdPtr mp)
14160 {
14161   GrouP  g, k1, k2;
14162   Int4   i;
14163 
14164   if (mp == NULL)
14165   {
14166     return NULL;
14167   }
14168   g = HiddenGroup (h, -1, 0, NULL);
14169   SetGroupSpacing (g, 10, 10);
14170 
14171   /* need citation selector */
14172   mp->citation_list = FeatCitEditDialog (g, mp->input_entityID);
14173   PointerToDialog (mp->citation_list, NULL);
14174 
14175   k1 = HiddenGroup (g, 3, 0, NULL);
14176   SetGroupSpacing (k1, 10, 10);
14177   mp->explanation_constraint = CheckBox (k1, "Where explanation is", ChangeExplanationConstraint);
14178   SetObjectExtra (mp->explanation_constraint, mp, NULL);
14179   SetStatus (mp->explanation_constraint, TRUE);
14180   mp->explanation_constraint_choice = PopupList (k1, TRUE, NULL);
14181   PopupItem (mp->explanation_constraint_choice, "Any");
14182   PopupItem (mp->explanation_constraint_choice, " ");
14183   for (i = 0; i < num_exception_explanations; i++)
14184   {
14185     PopupItem (mp->explanation_constraint_choice, exception_explanations [i]);
14186   }
14187   SetValue (mp->explanation_constraint_choice, 4);
14188 
14189   k2 = HiddenGroup (g, 2, 0, NULL);
14190   SetGroupSpacing (k2, 10, 10);
14191   mp->citation_translation = CheckBox (k2, "Where translation does not match product", NULL);
14192 
14193   AlignObjects (ALIGN_CENTER, (HANDLE) mp->citation_list,
14194                               (HANDLE) k1,
14195                               (HANDLE) k2,
14196                               (HANDLE) mp->citation_translation,
14197                               NULL);
14198 
14199   return g;
14200 }
14201 
14202 
FeatureEditorPartialGroup(GrouP h,FeatEdPtr mp)14203 static GrouP FeatureEditorPartialGroup (GrouP h, FeatEdPtr mp)
14204 {
14205   GrouP g, g1, g2,k1, k2, top;
14206 
14207   if (mp == NULL)
14208   {
14209     return NULL;
14210   }
14211 
14212   top = HiddenGroup (h, -1, 0, NULL);
14213   SetGroupSpacing (top, 10, 10);
14214 
14215   g = HiddenGroup (top, 2, 0, NULL);
14216   SetGroupSpacing (g, 10, 10);
14217 
14218   StaticPrompt (g, "Partials:", 0, dialogTextHeight, systemFont, 'l');
14219   g1 = NormalGroup (g, 1, 0, "", programFont, NULL);
14220   k1 = HiddenGroup (g1, 2, 0, NULL);
14221 
14222   SetGroupSpacing (k1, 10, 10);
14223   StaticPrompt (k1, "5' partial:", 0, dialogTextHeight, systemFont, 'l');
14224   mp->partial5_choice = PopupList (k1, TRUE, NULL);
14225   PopupItem (mp->partial5_choice, "Set");
14226   PopupItem (mp->partial5_choice, "Set only if at 5' end");
14227   PopupItem (mp->partial5_choice, "Set if bad start codon");
14228   PopupItem (mp->partial5_choice, "Set if CDS frame > 1");
14229   PopupItem (mp->partial5_choice, "Clear");
14230   PopupItem (mp->partial5_choice, "Clear if not at 5' end");
14231   PopupItem (mp->partial5_choice, "Clear if good start codon");
14232   PopupItem (mp->partial5_choice, "Do not change");
14233   SetValue (mp->partial5_choice, 8);
14234 
14235   mp->extend5_btn = CheckBox (g1, "Extend to 5' end of sequence if setting 5' partial", NULL);
14236 
14237   StaticPrompt (g1, "", 0, dialogTextHeight, systemFont, 'l');
14238 
14239   k2 = HiddenGroup (g1, 2, 0, NULL);
14240   SetGroupSpacing (k2, 10, 10);
14241   StaticPrompt (k2, "3' partial:", 0, dialogTextHeight, systemFont, 'l');
14242   mp->partial3_choice = PopupList (k2, TRUE, NULL);
14243   PopupItem (mp->partial3_choice, "Set");
14244   PopupItem (mp->partial3_choice, "Set only if at 3' end");
14245   PopupItem (mp->partial3_choice, "Set if bad stop codon");
14246   PopupItem (mp->partial3_choice, "Clear");
14247   PopupItem (mp->partial3_choice, "Clear if not at 3' end");
14248   PopupItem (mp->partial3_choice, "Clear if good stop codon");
14249   PopupItem (mp->partial3_choice, "Do not change");
14250   SetValue (mp->partial3_choice, 7);
14251 
14252   mp->extend3_btn = CheckBox (g1, "Extend to 3' end of sequence if setting 3' partial", NULL);
14253 
14254   StaticPrompt (g, "Join/Order/Merge:", 0, dialogTextHeight, systemFont, 'l');
14255   g2 = NormalGroup (g, 1, 0, "", programFont, NULL);
14256   mp->convert_choice = PopupList (g2, TRUE, NULL);
14257   PopupItem (mp->convert_choice, "Do not convert location");
14258   PopupItem (mp->convert_choice, "Convert location to join");
14259   PopupItem (mp->convert_choice, "Convert location to order");
14260   PopupItem (mp->convert_choice, "Convert location to single interval");
14261   SetValue (mp->convert_choice, 1);
14262 
14263   mp->retranslate_btn = CheckBox (top, "Retranslate coding regions", NULL);
14264   mp->adjust_gene_btn = CheckBox (top, "Adjust gene location", NULL);
14265 
14266   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) mp->retranslate_btn, (HANDLE) mp->adjust_gene_btn, NULL);
14267 
14268   return top;
14269 }
14270 
14271 #define FEATED_STRAND_ANY_REVERSE 1
14272 #define FEATED_STRAND_UNKNOWN     2
14273 #define FEATED_STRAND_PLUS        3
14274 #define FEATED_STRAND_MINUS       4
14275 #define FEATED_STRAND_BOTH        5
14276 
FeatureEditorStrandGroup(GrouP h,FeatEdPtr mp)14277 static GrouP FeatureEditorStrandGroup (GrouP h, FeatEdPtr mp)
14278 {
14279   GrouP  g;
14280 
14281   if (mp == NULL)
14282   {
14283     return NULL;
14284   }
14285   g = HiddenGroup (h, 5, 0, NULL);
14286   SetGroupSpacing (g, 10, 10);
14287   StaticPrompt (g, "Convert location strand", 0, dialogTextHeight, systemFont, 'l');
14288   StaticPrompt (g, "From", 0, dialogTextHeight, systemFont, 'l');
14289   mp->from_strand = PopupList (g, TRUE, NULL);
14290   PopupItem (mp->from_strand, "Any");
14291   PopupItem (mp->from_strand, "Unknown");
14292   PopupItem (mp->from_strand, "Plus");
14293   PopupItem (mp->from_strand, "Minus");
14294   PopupItem (mp->from_strand, "Both");
14295   SetValue (mp->from_strand, FEATED_STRAND_PLUS);
14296   StaticPrompt (g, "To", 0, dialogTextHeight, systemFont, 'l');
14297   mp->to_strand = PopupList (g, TRUE, NULL);
14298   PopupItem (mp->to_strand, "Reverse");
14299   PopupItem (mp->to_strand, "Unknown");
14300   PopupItem (mp->to_strand, "Plus");
14301   PopupItem (mp->to_strand, "Minus");
14302   PopupItem (mp->to_strand, "Both");
14303   SetValue (mp->to_strand, FEATED_STRAND_MINUS);
14304   return g;
14305 }
14306 
14307 
ChangeExperimentAction(GrouP g)14308 static void ChangeExperimentAction (GrouP g)
14309 {
14310   FeatEdPtr mp;
14311   mp = (FeatEdPtr) GetObjectExtra (g);
14312   if (mp != NULL)
14313   {
14314     if (GetValue (mp->experiment_action) == 1)
14315     {
14316       Enable (mp->experiment_text);
14317     }
14318     else
14319     {
14320       Disable (mp->experiment_text);
14321     }
14322   }
14323 }
14324 
FeatureEditorExperimentGroup(GrouP h,FeatEdPtr mp)14325 static GrouP FeatureEditorExperimentGroup (GrouP h, FeatEdPtr mp)
14326 {
14327   if (mp == NULL)
14328   {
14329     return NULL;
14330   }
14331   mp->experiment_action = HiddenGroup (h, 2, 0, ChangeExperimentAction);
14332   SetObjectExtra (mp->experiment_action, mp, NULL);
14333   SetGroupSpacing (mp->experiment_action, 10, 10);
14334   RadioButton (mp->experiment_action, "Set Experiment");
14335   mp->experiment_text = DialogText (mp->experiment_action, "", 20, NULL);
14336   RadioButton (mp->experiment_action, "Remove Experiment");
14337   SetValue (mp->experiment_action, 1);
14338   return mp->experiment_action;
14339 }
14340 
FeatureEditorInferenceGroup(GrouP h,FeatEdPtr mp)14341 static GrouP FeatureEditorInferenceGroup (GrouP h, FeatEdPtr mp)
14342 {
14343   GrouP g;
14344 
14345   g = HiddenGroup (h, 1, 0, NULL);
14346   SetGroupSpacing (g, 10, 10);
14347 
14348   mp->inference_dlg = CreateInferenceEditDialog (g, FeatEdChangeNotify, mp);
14349   return g;
14350 }
14351 
ChangeFeatureEditorActionGroup(GrouP g)14352 static void ChangeFeatureEditorActionGroup (GrouP g)
14353 {
14354   FeatEdPtr mp;
14355   Int4            i;
14356 
14357   mp = (FeatEdPtr) GetObjectExtra (g);
14358   if (mp == NULL)
14359   {
14360     return;
14361   }
14362 
14363   for (i = 0; i < NUM_FEAT_ED_ACTIONS; i++)
14364   {
14365     Hide (mp->action_grps[i]);
14366   }
14367 
14368   i = GetValue (mp->action_choice_grp);
14369   if (i > 0 && i < NUM_FEAT_ED_ACTIONS + 1)
14370   {
14371     Show (mp->action_grps [i-1]);
14372   }
14373 
14374   FeatEdChangeNotify (mp);
14375 
14376 }
14377 
FeatureEditorActionGroup(GrouP h,FeatEdPtr mp,Int4 first_action)14378 static GrouP FeatureEditorActionGroup (GrouP h, FeatEdPtr mp, Int4 first_action)
14379 {
14380   GrouP g, k, n = NULL;
14381   PrompT p1;
14382   SeqEntryPtr sep;
14383 
14384   if (mp == NULL)
14385   {
14386     return NULL;
14387   }
14388   g = HiddenGroup (h, -1, 0, NULL);
14389 
14390   sep = GetTopSeqEntryForEntityID(mp->input_entityID);
14391   p1 = StaticPrompt (g, "For", 0, dialogTextHeight, systemFont, 'l');
14392   mp->feature_type = FeatureTypeDialogMulti (g, FeatEdChangeNotify, mp);
14393 
14394   k = HiddenGroup (g, -1, 0, NULL);
14395   mp->action_choice_grp = HiddenGroup (g, NUM_FEAT_ED_ACTIONS, 0, ChangeFeatureEditorActionGroup);
14396   SetObjectExtra (mp->action_choice_grp, mp, NULL);
14397   RadioButton (mp->action_choice_grp, "Evidence");
14398   RadioButton (mp->action_choice_grp, "Exceptions");
14399   RadioButton (mp->action_choice_grp, "Location");
14400   RadioButton (mp->action_choice_grp, "Strands");
14401   RadioButton (mp->action_choice_grp, "Citations");
14402   RadioButton (mp->action_choice_grp, "Experiment");
14403   RadioButton (mp->action_choice_grp, "Inference");
14404   RadioButton (mp->action_choice_grp, "Pseudo");
14405   if (first_action >= 1 && first_action <= NUM_FEAT_ED_ACTIONS)
14406   {
14407     SetValue (mp->action_choice_grp, first_action);
14408   }
14409   else
14410   {
14411     SetValue (mp->action_choice_grp, FEAT_ED_PSEUDO);
14412   }
14413 
14414   n = HiddenGroup (g, 0, 0, NULL);
14415   mp->action_grps [0] = FeatureEvidenceGroup (n, mp);
14416   mp->action_grps[1] = FeatureExceptionGroup (n, mp);
14417   mp->action_grps[2] = FeatureEditorPartialGroup (n, mp);
14418   mp->action_grps[3] = FeatureEditorStrandGroup (n, mp);
14419   mp->action_grps[4] = FeatureEditorCitationGroup (n, mp);
14420   mp->action_grps[5] = FeatureEditorExperimentGroup (n, mp);
14421   mp->action_grps[6] = FeatureEditorInferenceGroup (n, mp);
14422   mp->action_grps[7] = FeaturePseudoGroup (n, mp);
14423   AlignObjects (ALIGN_CENTER, (HANDLE) mp->action_grps [0],
14424                               (HANDLE) mp->action_grps [1],
14425                               (HANDLE) mp->action_grps [2],
14426                               (HANDLE) mp->action_grps [3],
14427                               (HANDLE) mp->action_grps [4],
14428                                             (HANDLE) mp->action_grps [5],
14429                                             (HANDLE) mp->action_grps [6],
14430                                             (HANDLE) mp->action_grps [7],
14431                               NULL);
14432   AlignObjects (ALIGN_CENTER, (HANDLE) mp->action_choice_grp, (HANDLE) n, NULL);
14433 
14434   AlignObjects (ALIGN_CENTER, (HANDLE) p1,
14435                               (HANDLE) mp->feature_type,
14436                               (HANDLE) k, (HANDLE) n, NULL);
14437 
14438   return g;
14439 }
14440 
14441 
DoesInferenceMatchCategory(CharPtr inf_cat,CharPtr match_cat)14442 static Boolean DoesInferenceMatchCategory (CharPtr inf_cat, CharPtr match_cat)
14443 {
14444   if (StringHasNoText (inf_cat)) return FALSE;
14445 
14446   if (StringHasNoText (match_cat)
14447       || StringICmp (match_cat, "ANY") == 0
14448       || StringICmp (inf_cat, match_cat) == 0)
14449   {
14450     return TRUE;
14451   }
14452   else
14453   {
14454     return FALSE;
14455   }
14456 
14457 }
14458 
14459 
DoInferenceFeatureProc(SeqFeatPtr sfp,Pointer userdata)14460 static void DoInferenceFeatureProc (SeqFeatPtr sfp, Pointer userdata)
14461 {
14462   InferenceEditPtr iep;
14463   GBQualPtr        gbqual, gbqual_last = NULL, gbqual_next;
14464   CharPtr          new_val;
14465   InferenceParsePtr ipp;
14466   Boolean           changed;
14467   ApplyValueData    avd;
14468 
14469   iep = (InferenceEditPtr) userdata;
14470 
14471   if (iep == NULL || sfp == NULL) return;
14472 
14473   /* apply requested changes */
14474   gbqual = sfp->qual;
14475   while (gbqual != NULL)
14476   {
14477     gbqual_next = gbqual->next;
14478     if (StringCmp (gbqual->qual, "inference") == 0)
14479     {
14480       if (iep->action == eInferenceRemove)
14481       {
14482         if (gbqual_last == NULL)
14483         {
14484           sfp->qual = gbqual->next;
14485         }
14486         else
14487         {
14488           gbqual_last->next = gbqual->next;
14489         }
14490         gbqual->next = NULL;
14491         GBQualFree (gbqual);
14492       }
14493       else
14494       {
14495         /* perform editing here */
14496         ipp = ParseInferenceText (gbqual->val);
14497         changed = FALSE;
14498         if (ipp != NULL)
14499         {
14500           switch (iep->action)
14501           {
14502             case eInferenceEditCategory:
14503               if (DoesInferenceMatchCategory(ipp->category, iep->category_from))
14504               {
14505                 ipp->category = MemFree (ipp->category);
14506                 ipp->category = StringSave (iep->category_to);
14507                 changed = TRUE;
14508               }
14509               break;
14510             case eInferenceEditType:
14511               if (DoesInferenceMatchCategory(ipp->type, iep->type_from))
14512               {
14513                 ipp->type = MemFree (ipp->type);
14514                 ipp->type = StringSave (iep->type_to);
14515                 changed = TRUE;
14516               }
14517               break;
14518             case eInferenceApplyTypeFields:
14519             case eInferenceEditTypeFields:
14520               if (iep->field_edit != NULL
14521                   && iep->field_edit->edit_apply != NULL
14522                   && DoesInferenceMatchCategory (ipp->type, iep->field_edit->field_type))
14523               {
14524                 avd.where_to_replace = EditApplyFindLocation_anywhere;
14525                 avd.field_list = NULL;
14526                 avd.etp = NULL;
14527                 AddEditApplyDataToApplyValue (iep->action == eInferenceApplyTypeFields ? 1 : 2,
14528                                               iep->field_edit->edit_apply, &avd);
14529                 if (iep->field_edit->field_choice == 0)
14530                 {
14531                   ipp->first_field = HandleApplyValue (ipp->first_field, &avd);
14532                 }
14533                 else
14534                 {
14535                   ipp->second_field = HandleApplyValue (ipp->second_field, &avd);
14536                 }
14537                 avd.text_to_replace = MemFree (avd.text_to_replace);
14538                 avd.new_text = MemFree (avd.new_text);
14539                 changed = TRUE;
14540               }
14541               break;
14542             default:
14543               break;
14544           }
14545           if (changed)
14546           {
14547             new_val = InferenceTextFromStruct (ipp);
14548             gbqual->val = MemFree (gbqual->val);
14549             gbqual->val = new_val;
14550           }
14551         }
14552         gbqual_last = gbqual;
14553       }
14554     }
14555     else
14556     {
14557       gbqual_last = gbqual;
14558     }
14559     gbqual = gbqual_next;
14560   }
14561 }
14562 
14563 
DoEvidenceFeatureProc(SeqFeatPtr sfp,Pointer userdata)14564 static void DoEvidenceFeatureProc (SeqFeatPtr sfp, Pointer userdata)
14565 {
14566   FeatEdPtr mp;
14567 
14568   if (sfp == NULL || userdata == NULL)
14569   {
14570     return;
14571   }
14572 
14573   mp = (FeatEdPtr) userdata;
14574 
14575   sfp->exp_ev = (Uint1) mp->evidence_val;
14576 }
14577 
14578 
DoExceptionFeatureProc(SeqFeatPtr sfp,Pointer userdata)14579 static void DoExceptionFeatureProc (SeqFeatPtr sfp, Pointer userdata)
14580 {
14581   FeatEdPtr  mp;
14582   ExistingTextData etd;
14583   CharPtr          old_explanation = NULL;
14584 
14585   if (sfp == NULL || userdata == NULL)
14586   {
14587     return;
14588   }
14589 
14590   mp = (FeatEdPtr) userdata;
14591 
14592   if ((mp->product_val == 1 && sfp->product != NULL)
14593       || (mp->product_val == 2 && sfp->product == NULL)
14594       || mp->product_val == 3)
14595   {
14596     /* first, take care of any pre-existing exception explanation */
14597     old_explanation = sfp->except_text;
14598     sfp->except_text = NULL;
14599     if (mp->do_move_to_comment)
14600     {
14601       etd.existing_text_choice = eExistingTextChoiceAppendSemi;
14602       sfp->comment = HandleExistingText (sfp->comment, old_explanation, &etd);
14603       old_explanation = NULL;
14604     }
14605     else
14606     {
14607       old_explanation = MemFree (old_explanation);
14608     }
14609 
14610     if (StringHasNoText (mp->explanation_text))
14611     {
14612       sfp->excpt = FALSE;
14613     }
14614     else
14615     {
14616       sfp->excpt = TRUE;
14617       sfp->except_text = StringSave (mp->explanation_text);
14618     }
14619   }
14620 }
14621 
14622 #define DO_NOT_CONVERT             1
14623 #define CONVERT_TO_JOIN            2
14624 #define CONVERT_TO_ORDER           3
14625 #define CONVERT_TO_SINGLE_INTERVAL 4
14626 
DoPartialFeatureProc(SeqFeatPtr sfp,Pointer userdata)14627 static void DoPartialFeatureProc (SeqFeatPtr sfp, Pointer userdata)
14628 {
14629   FeatEdPtr mp;
14630   Boolean      partial5, partial3;
14631   Boolean      dash_at_end = FALSE;
14632   Boolean      star_at_end = FALSE;
14633   ByteStorePtr bs;
14634   CharPtr      prot;
14635   CharPtr      ptr;
14636   Char         first_char = '\0', ch;
14637   Boolean      hasNulls;
14638   SeqLocPtr    slp, firstSlp = NULL, lastSlp = NULL;
14639   Uint1        strand;
14640   Boolean      atEnd, moved5 = FALSE;
14641   BioseqPtr    bsp;
14642   CdRegionPtr  crp = NULL;
14643   SeqFeatPtr   gene = NULL;
14644 
14645   if (sfp == NULL || sfp->location == NULL || userdata == NULL)
14646   {
14647     return;
14648   }
14649 
14650   mp = (FeatEdPtr) userdata;
14651 
14652   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
14653   bsp = BioseqFindFromSeqLoc (sfp->location);
14654 
14655   if (mp->adjust_gene && sfp->data.choice != SEQFEAT_GENE) {
14656     gene = GetGeneForFeature (sfp);
14657   }
14658 
14659   if (sfp->idx.subtype == FEATDEF_CDS)
14660   {
14661     crp = (CdRegionPtr) sfp->data.value.ptrvalue;
14662     bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
14663     if (bs != NULL)
14664     {
14665       prot = BSMerge (bs, NULL);
14666       bs = BSFree (bs);
14667       if (prot != NULL)
14668       {
14669         first_char = *prot;
14670         ptr = prot;
14671         ch = *ptr;
14672         if (ch == '-')
14673         {
14674           dash_at_end = TRUE;
14675         }
14676         while (ch != '\0')
14677         {
14678           /* *ptr = TO_UPPER (ch); */
14679           if (ch == '*')
14680           {
14681             star_at_end = TRUE;
14682           } else {
14683             star_at_end = FALSE;
14684           }
14685           ptr++;
14686           ch = *ptr;
14687         }
14688       }
14689       prot = MemFree (prot);
14690     }
14691   }
14692 
14693     /* If requested, convert joins to orders */
14694     /* or orders to joins.                   */
14695 
14696     hasNulls = LocationHasNullsBetween (sfp->location);
14697     switch (mp->orderjoinpolicy)
14698     {
14699       case CONVERT_TO_JOIN :
14700         if (hasNulls)
14701         {
14702           slp = SeqLocMerge (bsp, sfp->location, NULL, FALSE, FALSE, FALSE);
14703             sfp->location = SeqLocFree (sfp->location);
14704             sfp->location = slp;
14705             if (bsp->repr == Seq_repr_seg)
14706             {
14707               slp = SegLocToPartsEx (bsp, sfp->location, FALSE);
14708               sfp->location = SeqLocFree (sfp->location);
14709               sfp->location = slp;
14710               hasNulls = LocationHasNullsBetween (sfp->location);
14711               sfp->partial = (sfp->partial || hasNulls);
14712             }
14713             FreeAllFuzz (sfp->location);
14714             SetSeqLocPartial (sfp->location, partial5, partial3);
14715         }
14716         break;
14717       case CONVERT_TO_ORDER :
14718         if (!hasNulls)
14719         {
14720             slp = SeqLocMerge (bsp, sfp->location, NULL, FALSE, FALSE, TRUE);
14721         sfp->location = SeqLocFree (sfp->location);
14722             sfp->location = slp;
14723             if (bsp->repr == Seq_repr_seg)
14724             {
14725               slp = SegLocToPartsEx (bsp, sfp->location, TRUE);
14726               sfp->location = SeqLocFree (sfp->location);
14727               sfp->location = slp;
14728               hasNulls = LocationHasNullsBetween (sfp->location);
14729               sfp->partial = (sfp->partial || hasNulls);
14730             }
14731             FreeAllFuzz (sfp->location);
14732             SetSeqLocPartial (sfp->location, partial5, partial3);
14733         }
14734         break;
14735       case CONVERT_TO_SINGLE_INTERVAL :
14736         slp = SeqLocMerge (bsp, sfp->location, NULL, TRUE, FALSE, FALSE);
14737         sfp->location = SeqLocFree (sfp->location);
14738         sfp->location = slp;
14739           SetSeqLocPartial (sfp->location, partial5, partial3);
14740       default:
14741         break;
14742     }
14743 
14744   /* find first and last location parts in a multi-part location */
14745   slp = SeqLocFindNext (sfp->location, NULL);
14746   while (slp != NULL)
14747   {
14748     if (firstSlp == NULL)
14749     {
14750       firstSlp = slp;
14751     }
14752     lastSlp = slp;
14753     slp = SeqLocFindNext (sfp->location, slp);
14754   }
14755 
14756   /* Set the 5' partial */
14757 
14758   if (firstSlp != NULL)
14759   {
14760     strand = SeqLocStrand (firstSlp);
14761     atEnd = FALSE;
14762     if (strand == Seq_strand_minus)
14763     {
14764       if (GetOffsetInBioseq (firstSlp, bsp, SEQLOC_START) == bsp->length - 1)
14765           {
14766         atEnd = TRUE;
14767       }
14768     } else {
14769       if (GetOffsetInBioseq (firstSlp, bsp, SEQLOC_START) == 0)
14770       {
14771         atEnd = TRUE;
14772       }
14773     }
14774     switch (mp->leftpolicy)
14775     {
14776       case 1 :
14777         partial5 = TRUE;
14778         if (! atEnd && mp->extend5)
14779         {
14780           moved5 = TRUE;
14781           ExtendSeqLocToEnd (sfp->location, bsp, TRUE);
14782         }
14783         break;
14784       case 2 :
14785         if (atEnd)
14786         {
14787           partial5 = TRUE;
14788         }
14789         break;
14790       case 3 :
14791         if (crp != NULL && (crp->frame > 1 || first_char != 'M'))
14792         {
14793           partial5 = TRUE;
14794           if (! atEnd && mp->extend5)
14795           {
14796             ExtendSeqLocToEnd (sfp->location, bsp, TRUE);
14797             moved5 = TRUE;
14798           }
14799         }
14800         break;
14801       case 4:
14802         if (crp != NULL && crp->frame > 1)
14803         {
14804           partial5 = TRUE;
14805           if (! atEnd && mp->extend5)
14806           {
14807             ExtendSeqLocToEnd (sfp->location, bsp, TRUE);
14808             moved5 = TRUE;
14809           }
14810         }
14811         break;
14812       case 5 :
14813         partial5 = FALSE;
14814         break;
14815       case 6 :
14816         if (! atEnd)
14817         {
14818           partial5 = FALSE;
14819         }
14820         break;
14821       case 7 :
14822         if (crp != NULL && (crp->frame == 1 || crp->frame == 0) && first_char == 'M')
14823         {
14824           partial5 = FALSE;
14825         }
14826         break;
14827       default :
14828         break;
14829     }
14830   }
14831 
14832   /* Set the 3' partial */
14833 
14834   if (lastSlp != NULL)
14835   {
14836     strand = SeqLocStrand (firstSlp);
14837     atEnd = FALSE;
14838     if (strand == Seq_strand_minus)
14839     {
14840       if (GetOffsetInBioseq (lastSlp, bsp, SEQLOC_STOP) == 0)
14841       {
14842         atEnd = TRUE;
14843       }
14844     }
14845     else
14846     {
14847       if (GetOffsetInBioseq (lastSlp, bsp, SEQLOC_STOP) == bsp->length - 1)
14848       {
14849         atEnd = TRUE;
14850       }
14851     }
14852     switch (mp->rightpolicy)
14853     {
14854       case 1 :
14855         partial3 = TRUE;
14856         if (! atEnd && mp->extend3)
14857         {
14858           ExtendSeqLocToEnd (sfp->location, bsp, FALSE);
14859         }
14860         break;
14861       case 2 :
14862         if (atEnd)
14863         {
14864           partial3 = TRUE;
14865         }
14866         break;
14867       case 3 :
14868         if ((! star_at_end) && crp != NULL)
14869         {
14870           partial3 = TRUE;
14871           if (! atEnd && mp->extend3)
14872           {
14873             ExtendSeqLocToEnd (sfp->location, bsp, FALSE);
14874           }
14875         }
14876         break;
14877       case 4 :
14878         partial3 = FALSE;
14879         break;
14880       case 5 :
14881         if (! atEnd)
14882         {
14883           partial3 = FALSE;
14884         }
14885         break;
14886       case 6 :
14887         if (star_at_end && crp != NULL)
14888         {
14889           partial3 = FALSE;
14890         }
14891         break;
14892       default :
14893         break;
14894     }
14895   }
14896 
14897   SetSeqLocPartial (sfp->location, partial5, partial3);
14898   sfp->partial = (partial5 || partial3 ||
14899                   LocationHasNullsBetween (sfp->location));
14900   if (partial5 && moved5)
14901   {
14902        SetBestFrame (sfp);
14903   }
14904 
14905   /* set protein partials for coding regions */
14906   if (sfp->idx.subtype == FEATDEF_CDS)
14907   {
14908     ResynchCDSPartials (sfp, NULL);
14909   }
14910 
14911   if (mp->retranslate) {
14912     RetranslateOneCDS (sfp, sfp->idx.entityID, TRUE, TRUE);
14913   }
14914   if (gene != NULL) {
14915     gene->location = SeqLocFree (gene->location);
14916     gene->location = SeqLocMerge (bsp, sfp->location, NULL, TRUE, FALSE, FALSE);
14917     SetSeqLocPartial (gene->location, partial5, partial3);
14918     gene->partial = partial5 || partial3;
14919   }
14920 }
14921 
14922 
DoesStrandMatch(Int4 strand_choice,Uint1 strand_val)14923 static Boolean DoesStrandMatch (Int4 strand_choice, Uint1 strand_val)
14924 {
14925   Boolean rval = FALSE;
14926 
14927   switch (strand_choice)
14928   {
14929     case FEATED_STRAND_ANY_REVERSE:
14930       rval = TRUE;
14931       break;
14932     case FEATED_STRAND_UNKNOWN:
14933       if (strand_val == Seq_strand_unknown)
14934       {
14935         rval = TRUE;
14936       }
14937       break;
14938     case FEATED_STRAND_PLUS:
14939       if (strand_val == Seq_strand_plus)
14940       {
14941         rval = TRUE;
14942       }
14943       break;
14944     case FEATED_STRAND_MINUS:
14945       if (strand_val == Seq_strand_minus)
14946       {
14947         rval = TRUE;
14948       }
14949       break;
14950     case FEATED_STRAND_BOTH:
14951       if (strand_val == Seq_strand_both)
14952       {
14953         rval = TRUE;
14954       }
14955       break;
14956   }
14957   return rval;
14958 }
14959 
GetNewStrandValue(Int4 strand_choice,Uint1 strand_val)14960 static Uint1 GetNewStrandValue (Int4 strand_choice, Uint1 strand_val)
14961 {
14962   Uint1 rval = Seq_strand_unknown;
14963 
14964   switch (strand_choice)
14965   {
14966     case FEATED_STRAND_ANY_REVERSE:
14967       switch (strand_val)
14968       {
14969         case Seq_strand_plus:
14970           rval = Seq_strand_minus;
14971           break;
14972         case Seq_strand_minus:
14973           rval = Seq_strand_plus;
14974           break;
14975         default:
14976           rval = strand_val;
14977           break;
14978       }
14979       break;
14980     case FEATED_STRAND_UNKNOWN:
14981       rval = Seq_strand_unknown;
14982       break;
14983     case FEATED_STRAND_PLUS:
14984       rval = Seq_strand_plus;
14985       break;
14986     case FEATED_STRAND_MINUS:
14987       rval = Seq_strand_minus;
14988       break;
14989     case FEATED_STRAND_BOTH:
14990       rval = Seq_strand_both;
14991       break;
14992   }
14993   return rval;
14994 }
14995 
ConvertLocationStrand(SeqLocPtr slp,Int4 fromStrand,Int4 toStrand)14996 static void ConvertLocationStrand (SeqLocPtr slp, Int4 fromStrand, Int4 toStrand)
14997 {
14998   SeqLocPtr      loc;
14999   PackSeqPntPtr  psp;
15000   SeqBondPtr     sbp;
15001   SeqIntPtr      sinp;
15002   SeqPntPtr      spp;
15003 
15004   while (slp != NULL) {
15005     switch (slp->choice) {
15006       case SEQLOC_NULL :
15007         break;
15008       case SEQLOC_EMPTY :
15009       case SEQLOC_WHOLE :
15010         break;
15011       case SEQLOC_INT :
15012         sinp = (SeqIntPtr) slp->data.ptrvalue;
15013         if (sinp != NULL && DoesStrandMatch (fromStrand, sinp->strand))
15014         {
15015           sinp->strand = GetNewStrandValue (toStrand, sinp->strand);
15016         }
15017         break;
15018       case SEQLOC_PNT :
15019         spp = (SeqPntPtr) slp->data.ptrvalue;
15020         if (spp != NULL && DoesStrandMatch (fromStrand, spp->strand))
15021         {
15022           spp->strand = GetNewStrandValue (toStrand, spp->strand);
15023         }
15024         break;
15025       case SEQLOC_PACKED_PNT :
15026         psp = (PackSeqPntPtr) slp->data.ptrvalue;
15027         if (psp != NULL && DoesStrandMatch (fromStrand, psp->strand))
15028         {
15029           psp->strand = GetNewStrandValue (toStrand, psp->strand);
15030         }
15031         break;
15032       case SEQLOC_PACKED_INT :
15033       case SEQLOC_MIX :
15034       case SEQLOC_EQUIV :
15035         loc = (SeqLocPtr) slp->data.ptrvalue;
15036         while (loc != NULL) {
15037           ConvertLocationStrand (loc, fromStrand, toStrand);
15038           loc = loc->next;
15039         }
15040         break;
15041       case SEQLOC_BOND :
15042         sbp = (SeqBondPtr) slp->data.ptrvalue;
15043         if (sbp != NULL) {
15044           spp = (SeqPntPtr) sbp->a;
15045           if (spp != NULL && DoesStrandMatch (fromStrand, spp->strand))
15046           {
15047             spp->strand = GetNewStrandValue (toStrand, spp->strand);
15048           }
15049           spp = (SeqPntPtr) sbp->b;
15050           if (spp != NULL && DoesStrandMatch (fromStrand, spp->strand))
15051           {
15052             spp->strand = GetNewStrandValue (toStrand, spp->strand);
15053           }
15054         }
15055         break;
15056       case SEQLOC_FEAT :
15057         break;
15058       default :
15059         break;
15060     }
15061     slp = slp->next;
15062   }
15063 }
15064 
DoStrandFeatureProc(SeqFeatPtr sfp,Pointer userdata)15065 static void DoStrandFeatureProc (SeqFeatPtr sfp, Pointer userdata)
15066 {
15067   FeatEdPtr mp;
15068 
15069   if (sfp == NULL || userdata == NULL)
15070   {
15071     return;
15072   }
15073 
15074   mp = (FeatEdPtr) userdata;
15075 
15076   ConvertLocationStrand (sfp->location, mp->from_strand_val, mp->to_strand_val);
15077 
15078 }
15079 
DoCitationFeatureProc(SeqFeatPtr sfp,Pointer userdata)15080 static void DoCitationFeatureProc (SeqFeatPtr sfp, Pointer userdata)
15081 {
15082   FeatEdPtr mp;
15083   ByteStorePtr    bs;
15084   BioseqPtr       protbsp;
15085   CharPtr         seq1 = NULL, seq2 = NULL;
15086   Boolean         add_citations = TRUE;
15087 
15088   if (sfp == NULL || userdata == NULL)
15089   {
15090     return;
15091   }
15092 
15093   mp = (FeatEdPtr) userdata;
15094 
15095   if (mp->use_explanation_constraint && mp->explanation_constraint_choice_val != 1)
15096   {
15097     /* do not continue unless feature matches explanation constraint */
15098     if (StringHasNoText (sfp->except_text))
15099     {
15100       if (mp->explanation_constraint_choice_val != 2)
15101       {
15102         add_citations = FALSE;
15103       }
15104     }
15105     else if (mp->explanation_constraint_choice_val > num_exception_explanations + 2)
15106     {
15107       add_citations = FALSE;
15108     }
15109     else if (StringICmp (sfp->except_text,
15110              exception_explanations [mp->explanation_constraint_choice_val - 3]) != 0)
15111     {
15112       add_citations = FALSE;
15113     }
15114   }
15115 
15116   if (mp->use_product_match)
15117   {
15118     /* do not continue unless translation does not match product */
15119     if (sfp->data.choice != SEQFEAT_CDREGION)
15120     {
15121       add_citations = FALSE;
15122     }
15123     else if (sfp->product != NULL)
15124     {
15125       protbsp = BioseqFindFromSeqLoc (sfp->product);
15126       seq1 = GetSequenceByBsp (protbsp);
15127       bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
15128       if (bs != NULL)
15129       {
15130         seq2 = BSMerge (bs, NULL);
15131       }
15132       bs = BSFree (bs);
15133       if (StringICmp (seq1, seq2) == 0)
15134       {
15135         add_citations = FALSE;
15136       }
15137       seq1 = MemFree (seq1);
15138       seq2 = MemFree (seq2);
15139     }
15140   }
15141 
15142   /* add citations to feature */
15143   if (add_citations)
15144   {
15145     sfp->cit = PubSetFree (sfp->cit);
15146     sfp->cit = DialogToPointer (mp->citation_list);
15147   }
15148 
15149 }
15150 
15151 
MakeRemoveFeatureFieldAction(Uint2 ftype,Int4 legalqual,DialoG constraint_dlg)15152 static ValNodePtr MakeRemoveFeatureFieldAction (Uint2 ftype, Int4 legalqual, DialoG constraint_dlg)
15153 {
15154   ValNodePtr      single_macro = NULL;
15155   RemoveActionPtr remove;
15156   AECRActionPtr   act;
15157 
15158   remove = RemoveActionNew();
15159   remove->field = MakeFeatureFieldField (ftype, legalqual);
15160   act = AECRActionNew();
15161   act->constraint = DialogToPointer (constraint_dlg);
15162   act->action = ValNodeNew (NULL);
15163   act->action->choice = ActionChoice_remove;
15164   act->action->data.ptrvalue = remove;
15165   single_macro = ValNodeNew (NULL);
15166   single_macro->choice = MacroActionChoice_aecr;
15167   single_macro->data.ptrvalue = act;
15168   return single_macro;
15169 }
15170 
15171 
15172 static ValNodePtr
MakeApplyFeatureFieldAction(Uint2 ftype,Int4 legalqual,CharPtr val,DialoG constraint_dlg,SeqEntryPtr sep)15173 MakeApplyFeatureFieldAction
15174 (Uint2 ftype, Int4 legalqual, CharPtr val, DialoG constraint_dlg, SeqEntryPtr sep)
15175 {
15176   ValNodePtr      single_macro = NULL;
15177   ApplyActionPtr  apply;
15178   AECRActionPtr   act;
15179   ValNodePtr      sample_list;
15180   AECRSamplePtr   sample;
15181 
15182   apply = ApplyActionNew();
15183   apply->field = MakeFeatureFieldField (ftype, legalqual);
15184   apply->value = StringSave (val);
15185   act = AECRActionNew();
15186   act->constraint = DialogToPointer (constraint_dlg);
15187   act->action = ValNodeNew (NULL);
15188   act->action->choice = ActionChoice_apply;
15189   act->action->data.ptrvalue = apply;
15190   apply->existing_text = ExistingTextOption_replace_old;
15191   if (sep != NULL) {
15192     sample_list = GetAECRSampleList (act, sep);
15193     sample = GetFieldSampleFromList (sample_list, apply->field);
15194     sample_list = AECRSampleListFree (sample_list);
15195     if (sample != NULL && sample->num_found > 0) {
15196       apply->existing_text = TwoStepExistingText (sample->num_found, IsFieldTypeNonText(apply->field), AllowFieldMulti (apply->field));
15197     }
15198     sample = AECRSampleFree (sample);
15199   }
15200   if (apply->existing_text == 0) {
15201     act = AECRActionFree (act);
15202   } else {
15203     single_macro = ValNodeNew (NULL);
15204     single_macro->choice = MacroActionChoice_aecr;
15205     single_macro->data.ptrvalue = act;
15206   }
15207   return single_macro;
15208 }
15209 
15210 
15211 static void
FeatureEditorDoOneAction(SeqEntryPtr sep,Uint2 ftype,FeatEdPtr mp,Int4 action_choice)15212 FeatureEditorDoOneAction
15213 (SeqEntryPtr     sep,
15214  Uint2           ftype,
15215  FeatEdPtr mp,
15216  Int4            action_choice)
15217 {
15218   Int4            exception_choice;
15219   ValNodePtr      vnp;
15220   MsgAnswer       ans;
15221   Boolean         also_remove_evidence = FALSE;
15222   InferenceEditPtr iep;
15223   ValNodePtr      sample_list;
15224   ValNodePtr      single_field;
15225   AECRSamplePtr   sample;
15226   ValNodePtr      macro_list = NULL;
15227   ValNodePtr      object_list = NULL;
15228   CharPtr         val;
15229   VisitFeaturesFunc callback_func = NULL;
15230 
15231   switch (action_choice)
15232   {
15233     case FEAT_ED_EXPERIMENT:
15234       if (TextHasNoText (mp->experiment_text)) {
15235         macro_list = MakeRemoveFeatureFieldAction (ftype, Feat_qual_legal_experiment, mp->constraint);
15236       } else {
15237         val = SaveStringFromText (mp->experiment_text);
15238         macro_list = MakeApplyFeatureFieldAction (ftype, Feat_qual_legal_experiment, val, mp->constraint, sep);
15239         val = MemFree (val);
15240       }
15241       break;
15242     case FEAT_ED_INFERENCE:
15243       iep = DialogToPointer (mp->inference_dlg);
15244       if (iep->action == eInferenceRemove)
15245       {
15246         macro_list = MakeRemoveFeatureFieldAction (ftype, Feat_qual_legal_inference, mp->constraint);
15247         vnp = MakeApplyFeatureFieldAction (ftype, Feat_qual_legal_evidence, "X", mp->constraint, NULL);
15248         sample_list = GetAECRSampleList (vnp->data.ptrvalue, sep);
15249         single_field = MakeFeatureFieldField (ftype, Feat_qual_legal_evidence);
15250         sample = GetFieldSampleFromList (sample_list, single_field);
15251         single_field = FieldTypeFree (single_field);
15252         sample_list = AECRSampleListFree (sample_list);
15253         if (sample != NULL && sample->num_found > 0) {
15254           ans = Message (MSG_YNC, "There are evidence qualifiers on your features, which are displayed as inference qualifiers in the flat file.  Would you like to remove them as well?");
15255           if (ans == ANS_CANCEL)
15256           {
15257             macro_list = MacroActionListFree (macro_list);
15258           }
15259           else if (ans == ANS_YES)
15260           {
15261             also_remove_evidence = TRUE;
15262             mp->evidence_val = 0;
15263           }
15264         }
15265         sample = AECRSampleFree (sample);
15266       }
15267       else
15268       {
15269         macro_list = MakeApplyFeatureFieldAction (ftype, Feat_qual_legal_inference, "X", mp->constraint, NULL);
15270       }
15271       if (macro_list != NULL)
15272       {
15273         object_list = GetObjectListForAECRAction (sep, macro_list->data.ptrvalue);
15274         macro_list = MacroActionListFree (macro_list);
15275         for (vnp = object_list; vnp != NULL; vnp = vnp->next)
15276         {
15277           DoInferenceFeatureProc (vnp->data.ptrvalue, iep);
15278           if (also_remove_evidence)
15279           {
15280             DoEvidenceFeatureProc (vnp->data.ptrvalue, mp);
15281           }
15282         }
15283         object_list = FreeObjectList (object_list);
15284 
15285       }
15286       iep = InferenceEditFree (iep);
15287 
15288       break;
15289     case FEAT_ED_PSEUDO:
15290       val = GetEnumPopupByName (mp->pseudo_action, legacy_pseudogene_alist);
15291       if (StringHasNoText (val))
15292       {
15293         macro_list = MakeRemoveFeatureFieldAction (ftype, Feat_qual_legal_pseudo, mp->constraint);
15294       }
15295       else
15296       {
15297         macro_list = MakeApplyFeatureFieldAction (ftype, Feat_qual_legal_pseudo, val, mp->constraint, NULL);
15298       }
15299       val = MemFree (val);
15300       break;
15301     case FEAT_ED_EVIDENCE:
15302       macro_list = MakeRemoveFeatureFieldAction (ftype, Feat_qual_legal_evidence, mp->constraint);
15303       break;
15304     case FEAT_ED_EXCEPTION:
15305       mp->do_move_to_comment = GetStatus (mp->move_to_comment);
15306       mp->product_val = GetValue (mp->product_choice);
15307       exception_choice = GetValue (mp->explanation_choice);
15308       if (exception_choice == 1)
15309       {
15310         mp->explanation_text = NULL;
15311       }
15312       else if (exception_choice > 1 && exception_choice < num_exception_explanations + 1)
15313       {
15314         mp->explanation_text = StringSave (exception_explanations [exception_choice - 2]);
15315       }
15316       else if (exception_choice == num_exception_explanations + 1)
15317       {
15318         mp->explanation_text = SaveStringFromText (mp->other_explanation);
15319       }
15320       callback_func = DoExceptionFeatureProc;
15321       break;
15322     case FEAT_ED_PARTIAL:
15323       mp->orderjoinpolicy = GetValue (mp->convert_choice);
15324       mp->leftpolicy = GetValue (mp->partial5_choice);
15325       mp->rightpolicy = GetValue (mp->partial3_choice);
15326       mp->extend5 = GetStatus (mp->extend5_btn);
15327       mp->extend3 = GetStatus (mp->extend3_btn);
15328       mp->retranslate = GetStatus (mp->retranslate_btn);
15329       mp->adjust_gene = GetStatus (mp->adjust_gene_btn);
15330       callback_func = DoPartialFeatureProc;
15331       break;
15332     case FEAT_ED_STRAND:
15333       mp->from_strand_val = (Uint1) GetValue (mp->from_strand);
15334       mp->to_strand_val = (Uint1) GetValue (mp->to_strand);
15335       callback_func = DoStrandFeatureProc;
15336       break;
15337     case FEAT_ED_CITATION:
15338       mp->use_explanation_constraint = GetStatus (mp->explanation_constraint);
15339       mp->explanation_constraint_choice_val = GetValue (mp->explanation_constraint_choice);
15340       mp->use_product_match = GetStatus (mp->citation_translation);
15341       callback_func = DoCitationFeatureProc;
15342       break;
15343   }
15344 
15345   if (callback_func != NULL)
15346   {
15347     macro_list = MakeApplyFeatureFieldAction (ftype, Feat_qual_legal_note, "X", mp->constraint, NULL);
15348     object_list = GetObjectListForAECRAction (sep, macro_list->data.ptrvalue);
15349     macro_list = MacroActionListFree (macro_list);
15350     for (vnp = object_list; vnp != NULL; vnp = vnp->next)
15351     {
15352       callback_func (vnp->data.ptrvalue, mp);
15353     }
15354     object_list = FreeObjectList (object_list);
15355   }
15356 
15357   if (macro_list != NULL)
15358   {
15359     ApplyMacroToSeqEntryEx (sep, macro_list, NULL, Sequin_GlobalAlign2Seq);
15360     macro_list = MacroActionListFree (macro_list);
15361   }
15362 
15363   mp->explanation_text = MemFree (mp->explanation_text);
15364   if (action_choice == FEAT_ED_PARTIAL)
15365   {
15366     ResynchCodingRegionPartials (sep);
15367   }
15368 }
15369 
FeatureEditorAction(Pointer userdata)15370 static Boolean FeatureEditorAction (Pointer userdata)
15371 {
15372   FeatEdPtr mp;
15373   Uint2           ftype;
15374   Int4            action_choice;
15375   SeqEntryPtr     sep;
15376 
15377   mp = (FeatEdPtr) userdata;
15378   if (mp == NULL)
15379   {
15380     return FALSE;
15381   }
15382 
15383   sep = GetTopSeqEntryForEntityID (mp->input_entityID);
15384   if (sep == NULL)
15385   {
15386     return FALSE;
15387   }
15388 
15389   WatchCursor ();
15390   Update ();
15391 
15392   ftype = GetFeatureTypeFromFeatureTypeDialog (mp->feature_type);
15393 
15394   action_choice = GetValue (mp->action_choice_grp);
15395   FeatureEditorDoOneAction (sep, ftype, mp, action_choice);
15396   ArrowCursor ();
15397   Update ();
15398   ObjMgrSetDirtyFlag (mp->input_entityID, TRUE);
15399   ObjMgrSendMsg (OM_MSG_UPDATE, mp->input_entityID, 0, 0);
15400   return TRUE;
15401 }
15402 
FeatureEditorBaseForm(BaseFormPtr bfp,Int4 first_action)15403 NLM_EXTERN void FeatureEditorBaseForm (BaseFormPtr bfp, Int4 first_action)
15404 {
15405   FeatEdPtr mp;
15406   WindoW          w;
15407   GrouP           h, g;
15408 
15409   if (bfp == NULL) return;
15410   mp = (FeatEdPtr) MemNew (sizeof (FeatEdData));
15411   if (mp == NULL) return;
15412 
15413   w = FixedWindow (-50, -33, -10, -10, "Feature Editor", StdCloseWindowProc);
15414   SetObjectExtra (w, mp, StdCleanupFormProc);
15415   mp->form = (ForM) w;
15416   mp->input_entityID = bfp->input_entityID;
15417 
15418   h = HiddenGroup (w, -1, 0, NULL);
15419 
15420   g = FeatureEditorActionGroup (h, mp, first_action);
15421 
15422   mp->constraint = ComplexConstraintDialog (h, NULL, NULL);
15423   SetComplexConstraintType (mp->constraint, eComplexConstraintType_string);
15424   mp->accept_cancel = AcceptCancelDialog (h, FeatureEditorAction, NULL,
15425                                           FeatEdClear,
15426                                           FeatEdClearText,
15427                                           (Pointer)mp, w);
15428   AlignObjects (ALIGN_CENTER, (HANDLE) g,
15429                               (HANDLE) mp->constraint,
15430                               (HANDLE) mp->accept_cancel, NULL);
15431 
15432   ChangeFeatureEditorActionGroup (mp->action_choice_grp);
15433   Show (w);
15434 }
15435