NCBI C Toolkit Cross Reference

C/sequin/sequin6.c


  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.347 $
 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 
 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 static ENUM_ALIST (publication_field_alist)
 86   {" ",                0},
 87   {"Published",        PUBLICATION_PUBLISHED_FIELD},
 88   {"In Press",         PUBLICATION_INPRESS_FIELD},
 89   {"Unpublished",      PUBLICATION_UNPUB_FIELD},
 90 END_ENUM_ALIST
 91 
 92 
 93 #define GENE_LOCUS_FIELD        1
 94 #define GENE_DESCRIPTION_FIELD  2
 95 #define GENE_ALLELE_FIELD       3
 96 #define GENE_MAPLOC_FIELD       4
 97 #define GENE_LOCUS_TAG_FIELD    5
 98 #define GENE_SYNONYM_FIELD      6
 99 #define GENE_COMMENT_FIELD      7
100 
101 static ENUM_ALIST(gene_field_alist)
102   {" ",                    0},
103   {"Gene locus",           GENE_LOCUS_FIELD},
104   {"Gene description",     GENE_DESCRIPTION_FIELD},
105   {"Gene allele",          GENE_ALLELE_FIELD},
106   {"Gene maploc",          GENE_MAPLOC_FIELD},
107   {"Locus_tag",            GENE_LOCUS_TAG_FIELD},
108   {"Gene synonym",         GENE_SYNONYM_FIELD},
109   {"Gene comment",         GENE_COMMENT_FIELD},
110 END_ENUM_ALIST
111 
112 #define CDS_COMMENT   1
113 #define CDS_GENE_XREF 2
114 #define CDS_DB_XREF   3
115 
116 static ENUM_ALIST(cds_field_alist)
117   {" ",                    0},
118   {"CDS comment",          CDS_COMMENT},
119   {"gene xref",            CDS_GENE_XREF},
120   {"db_xref",              CDS_DB_XREF},
121 END_ENUM_ALIST
122 
123 static ENUM_ALIST(cds_short_field_alist)
124   {" ",                    0},
125   {"CDS comment",          CDS_COMMENT},
126 END_ENUM_ALIST
127 
128 #define PROT_NAME_FIELD        1
129 #define PROT_DESCRIPTION_FIELD 2
130 #define PROT_ECNUM_FIELD       3
131 #define PROT_ACTIVITY_FIELD    4
132 #define PROT_COMMENT_FIELD     5
133 
134 static ENUM_ALIST(prot_field_alist)
135   {" ",                    0},
136   {"Protein name",         PROT_NAME_FIELD},
137   {"Protein description",  PROT_DESCRIPTION_FIELD},
138   {"Protein E.C. number",  PROT_ECNUM_FIELD},
139   {"Protein activity",     PROT_ACTIVITY_FIELD},
140   {"Protein comment",      PROT_COMMENT_FIELD},
141 END_ENUM_ALIST
142 
143 #define RNA_NAME_FIELD       1
144 #define RNA_COMMENT_FIELD    2
145 #define RNA_GENE_XREF_FIELD  3
146 
147 static ENUM_ALIST(rnax_field_alist)
148   {" ",                    0},
149   {"RNA Name",             RNA_NAME_FIELD},
150   {"RNA Comment",          RNA_COMMENT_FIELD},
151   {"gene xref",            RNA_GENE_XREF_FIELD},
152 END_ENUM_ALIST
153 
154 static ENUM_ALIST(rnax_short_field_alist)
155   {" ",                    0},
156   {"RNA Name",             RNA_NAME_FIELD},
157   {"RNA Comment",          RNA_COMMENT_FIELD},
158   {"gene xref",            RNA_GENE_XREF_FIELD},
159 END_ENUM_ALIST
160 
161 #define ORGREF_SCI_NAME_FIELD    1
162 #define ORGREF_COMMON_NAME_FIELD 2
163 #define ORGREF_LINEAGE_FIELD     3
164 #define ORGREF_DIVISION_FIELD    4
165 
166 static ENUM_ALIST(orgref_field_alist)
167   {" ",                    0},
168   {"Scientific Name",      ORGREF_SCI_NAME_FIELD},
169   {"Common Name",          ORGREF_COMMON_NAME_FIELD},
170   {"Lineage",              ORGREF_LINEAGE_FIELD},
171   {"Division",             ORGREF_DIVISION_FIELD},
172 END_ENUM_ALIST
173 
174 #define IMPORT_GBQUAL_FIELD  1
175 #define IMPORT_COMMENT_FIELD 2
176 
177 static ENUM_ALIST(impfeat_field_alist)
178   {" ",        0},
179   {"GBQual",   IMPORT_GBQUAL_FIELD},
180   {"Comment",  IMPORT_COMMENT_FIELD},
181 END_ENUM_ALIST
182 
183 
184 #define NUM_SUBTARGET_POPUPS 12
185 
186 static GbFeatName ParseQualifierList[] = {
187  {"allele", Class_text}, {"anticodon", Class_pos_aa},
188  {"bound_moiety", Class_text},
189  {"chromosome", Class_text},
190  {"citation", Class_bracket_int},
191  {"codon", Class_seq_aa},
192  {"codon_start", Class_int_or}, {"cons_splice", Class_site},
193  {"db_xref", Class_text},
194  {"direction", Class_L_R_B}, {"EC_number", Class_ecnum},
195  {"evidence", Class_exper}, {"exception", Class_text},
196  {"frequency", Class_text}, {"function", Class_text},
197  {"gene", Class_text}, {"gdb_xref", Class_text},
198  {"insertion_seq", Class_text},
199  {"label", Class_token},
200  {"map", Class_text},
201  {"mod_base", Class_token}, {"note", Class_note},
202  {"number", Class_number}, {"organism", Class_text},
203  {"partial", Class_none}, {"PCR_conditions", Class_text},
204  {"phenotype", Class_text},
205  {"plasmid", Class_text}, {"product", Class_text},
206  {"pseudo", Class_none},
207  {"rearranged", Class_none}, { "replace", Class_text},
208  {"rpt_family", Class_text}, {"rpt_type", Class_rpt},
209  {"rpt_unit", Class_token},
210  {"sequenced_mol", Class_text},
211  {"standard_name", Class_text},
212  {"translation", Class_text}, {"transl_except", Class_pos_aa},
213  {"transl_table", Class_int}, {"transposon", Class_text},
214  {"usedin", Class_token},
215  {"focus", Class_none},
216  {"protein_id", Class_text},
217  {"organelle", Class_text}, {"transcript_id", Class_text},
218  {"transgenic", Class_none}, {"environmental_sample", Class_none},
219  {"locus_tag", Class_text}, {"mol_type", Class_text},
220 };
221 
222 const Int4 NumParseQualifiers = sizeof (ParseQualifierList) / sizeof (GbFeatName);
223 
224 
225 static void PopulateParseQualPopup (PopuP p)
226 {
227   Int4 i;
228   for (i = 0; i < NumParseQualifiers; i++) {
229     PopupItem (p, ParseQualifierList[i].name);
230   }
231 }
232 
233 
234 static DialoG ImpFeatSelectDialog (GrouP g, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
235 {
236   EnumFieldAssocPtr list, ap;
237   ValNodePtr   choice_list = NULL;
238 
239   list = import_featdef_alist (FALSE, FALSE, FALSE);
240   SortEnumFieldAssocPtrArray (list, CompareImpFeatEnumFieldAssoc);
241   for (ap = list; ap->name != NULL; ap++) {
242     if (ap == list) {
243       ValNodeAddPointer (&choice_list, 0, StringSave ("All import features"));
244     } else {
245       ValNodeAddPointer (&choice_list, 0, StringSave (ap->name));
246     }
247   }
248   return ValNodeSelectionDialog (g, choice_list, TALL_SELECTION_LIST,
249                                                 ValNodeStringName,
250                                 ValNodeSimpleDataFree, ValNodeStringCopy,
251                                 ValNodeChoiceMatch, "Import Feature Type",
252                                 change_notify, change_userdata, FALSE);
253 }
254 
255 typedef enum {
256   eFieldTypeGene = 0,
257   eFieldTypeCDS,
258   eFieldTypeProtein,
259   eFieldTypeRNA,
260   eFieldTypeBioSource,
261   eFieldTypeOrgModSubSource,
262   eFieldTypeImport,
263   eFieldTypeDefline,
264   eFieldTypeCommentDescriptor,
265   eFieldTypeFeatureNote,
266   eFieldTypePublication,
267   eFieldType_Max
268 } SegregateFieldType;
269 
270 static CharPtr field_type_names[] = {
271   "Gene",
272   "CDS",
273   "Protein",
274   "RNA",
275   "BioSource",
276   "OrgMod and SubSource",
277   "Import Feature",
278   "DefLine",
279   "Comment Descriptor",
280   "Feature Note",
281   "Publication" };
282 
283 
284 typedef struct fieldsubfield {
285   Int4 field;
286   Int4 subfield;
287   CharPtr impfeat_key;
288   ValNodePtr subfield_list;
289 } FieldSubfieldData, PNTR FieldSubfieldPtr;
290 
291 
292 static FieldSubfieldPtr FieldSubfieldFree (FieldSubfieldPtr f)
293 {
294   if (f != NULL) {
295     f->subfield_list = ValNodeFree (f->subfield_list);
296     f->impfeat_key = MemFree (f->impfeat_key);
297     f = MemFree (f);
298   }
299   return f;
300 }
301 
302 
303 typedef struct fieldsubfielddlg {
304   DIALOG_MESSAGE_BLOCK
305   PopuP field_list;
306   DialoG subfield_dlg[eFieldType_Max];
307   DialoG impfeat_type;
308   Boolean allowed_fields[eFieldType_Max];
309   Nlm_ChangeNotifyProc     change_notify;
310   Pointer                  change_userdata;
311 } FieldSubfieldDlgData, PNTR FieldSubfieldDlgPtr;
312 
313 
314 static Int4 FieldNumFromListVal (Int4 list_val, BoolPtr allowed_fields)
315 {
316   Int4 i;
317   Int4 field_num = -1;
318 
319   if (list_val < 1) return -1;
320 
321   for (i = 0; i < eFieldType_Max && field_num < 0; i++) {
322     if (allowed_fields[i]) {
323       if (list_val - 1 == i) {
324         field_num = i;
325       }
326     } else {
327       list_val++;
328     }
329   }
330   return field_num;
331 }
332 
333 
334 static Int4 ListValFromFieldNum (Int4 field_num, BoolPtr allowed_fields)
335 {
336   Int4 list_val = 0, i = 0;
337 
338   if (field_num < 0) return 0;
339 
340   while (i <= field_num) {
341     if (allowed_fields[i]) {
342       list_val++;
343     }
344     i++;
345   }
346   return list_val;
347 }
348 
349 
350 static void ChangeFieldType (PopuP p)
351 {
352   FieldSubfieldDlgPtr dlg;
353   Int4                list_val, field_num, i;
354 
355   dlg = (FieldSubfieldDlgPtr) GetObjectExtra (p);
356   if (dlg == NULL) return;
357 
358   list_val = GetValue (dlg->field_list);
359   field_num = FieldNumFromListVal (list_val, dlg->allowed_fields);
360 
361   for (i = 0; i < eFieldType_Max; i++) {
362     if (dlg->subfield_dlg[i] == NULL) continue;
363     if (i == field_num) {
364       Show (dlg->subfield_dlg[i]);
365     } else {
366       Hide (dlg->subfield_dlg[i]);
367     }
368   }
369   if (field_num == eFieldTypeImport) {
370     Show (dlg->impfeat_type);
371   } else {
372     Hide (dlg->impfeat_type);
373   }
374   if (dlg->change_notify != NULL) {
375     (dlg->change_notify) (dlg->change_userdata);
376   }
377 }
378 
379 
380 static void FieldSubfieldToDialog (DialoG d, Pointer data)
381 {
382   FieldSubfieldDlgPtr dlg;
383   FieldSubfieldPtr    f;
384   Int4                list_val;
385   ValNode             vn;
386 
387   dlg = (FieldSubfieldDlgPtr) GetObjectExtra (d);
388   if (dlg == NULL) return;
389 
390   f = (FieldSubfieldPtr) data;
391   if (f == NULL || f->field < 0) {
392     SetValue (dlg->field_list, 0);
393   } else {
394     list_val = ListValFromFieldNum (f->field, dlg->allowed_fields);
395     SetValue (dlg->field_list, list_val);
396     if (dlg->subfield_dlg[f->field] != NULL) {    
397       if (list_val == eFieldTypeFeatureNote) {
398         PointerToDialog (dlg->subfield_dlg[eFieldTypeFeatureNote], f->subfield_list);
399       } else {
400         vn.choice = f->subfield;
401         vn.data.ptrvalue = NULL;
402         vn.next = NULL;
403         PointerToDialog (dlg->subfield_dlg[f->field], &vn);
404         if (f->field == eFieldTypeImport) {
405           vn.choice = 0;
406           vn.data.ptrvalue = f->impfeat_key;
407           PointerToDialog (dlg->impfeat_type, &vn);
408         }
409       }
410     }
411   }
412   ChangeFieldType (dlg->field_list);
413 }
414 
415 
416 static Pointer DialogToFieldSubfield (DialoG d)
417 {
418   FieldSubfieldDlgPtr dlg;
419   FieldSubfieldPtr f;
420   Int4             val;
421   ValNodePtr       vnp;
422   SourceQualDescPtr sqdp;
423 
424   dlg = (FieldSubfieldDlgPtr) GetObjectExtra (d);
425   if (dlg == NULL) return NULL;
426 
427   f = (FieldSubfieldPtr) MemNew (sizeof (FieldSubfieldData));
428   f->field = -1;
429   f->subfield = -1;
430   f->subfield_list = NULL;
431   f->impfeat_key = NULL;
432 
433   val = GetValue (dlg->field_list);
434   if (val > 0) {
435     f->field = FieldNumFromListVal (val, dlg->allowed_fields);    
436     if (dlg->subfield_dlg[f->field] == NULL) {
437       f->subfield = 0;
438     } else {
439       if (f->field == eFieldTypeFeatureNote) {
440         f->subfield_list = DialogToPointer (dlg->subfield_dlg[f->field]);
441       } else {
442         vnp = DialogToPointer (dlg->subfield_dlg[f->field]);
443         if (vnp != NULL) {
444           if (f->field == eFieldTypeOrgModSubSource) {
445             sqdp = (SourceQualDescPtr) vnp->data.ptrvalue;
446             if (sqdp != NULL) {
447               f->subfield = sqdp->subtype;
448               if (!sqdp->isOrgMod) {
449                 f->subfield += 1000;
450               }
451             }
452           } else {
453             f->subfield = vnp->choice;
454             vnp = ValNodeFree (vnp);
455           }
456         }
457         if (f->field == eFieldTypeImport) {
458           vnp = DialogToPointer (dlg->impfeat_type);
459           if (vnp != NULL) {    
460             f->impfeat_key = StringSave (vnp->data.ptrvalue);
461             vnp = ValNodeFree (vnp);
462           }
463         }
464       }
465     }
466   }
467 
468   return f;
469 }
470 
471 
472 static ValNodePtr TestFieldSubfieldDialog (DialoG d)
473 {
474   ValNodePtr          err_list = NULL;
475   FieldSubfieldPtr    f;
476   
477   f = DialogToPointer (d);
478   if (f == NULL || f->field < 0 
479       || (f->subfield < 0 && f->subfield_list == NULL)
480       || (f->field == eFieldTypeImport && f->impfeat_key == NULL)) {
481     ValNodeAddPointer (&err_list, 0, "Must choose field");
482   }
483   f = FieldSubfieldFree (f);
484   return err_list;  
485 }
486 
487 
488 static DialoG 
489 CreateFieldSubfieldDlg 
490 (GrouP h,
491  BoolPtr allowed_fields,
492  Nlm_ChangeNotifyProc     change_notify,
493  Pointer                  change_userdata)
494 {
495   FieldSubfieldDlgPtr dlg;
496   GrouP               p, g, g2;
497   Int4                i;
498   ValNode             vn;
499   
500   dlg = (FieldSubfieldDlgPtr) MemNew (sizeof (FieldSubfieldDlgData));
501   if (dlg == NULL)
502   {
503     return NULL;
504   }
505   
506   p = HiddenGroup (h, 2, 0, NULL);
507   SetObjectExtra (p, dlg, StdCleanupExtraProc);
508 
509   dlg->dialog = (DialoG) p;
510   dlg->todialog = FieldSubfieldToDialog;
511   dlg->fromdialog = DialogToFieldSubfield;
512   dlg->testdialog = TestFieldSubfieldDialog;
513   dlg->change_notify = change_notify;
514   dlg->change_userdata = change_userdata;
515 
516   if (allowed_fields == NULL) {
517     MemSet (dlg->allowed_fields, TRUE, sizeof (dlg->allowed_fields));
518   } else {
519     for (i = 0; i < eFieldType_Max; i++) {      
520       dlg->allowed_fields[i] = allowed_fields[i];
521     }
522   }
523 
524   dlg->field_list = PopupList (p, TRUE, ChangeFieldType);
525   SetObjectExtra (dlg->field_list, dlg, NULL);
526   for (i = 0; i < eFieldType_Max; i++) {
527     if (dlg->allowed_fields[i]) {
528       PopupItem (dlg->field_list, field_type_names[i]);
529     }
530   }
531 
532   g = HiddenGroup (p, 0, 0, NULL);
533   dlg->subfield_dlg[eFieldTypeGene] = EnumAssocSelectionDialog (g, gene_field_alist, 
534                                                                 NULL, FALSE, 
535                                                                 dlg->change_notify, 
536                                                                 dlg->change_userdata);
537   dlg->subfield_dlg[eFieldTypeCDS] = EnumAssocSelectionDialog (g, cds_field_alist,
538                                                                 NULL, FALSE, 
539                                                                 dlg->change_notify, 
540                                                                 dlg->change_userdata);
541   dlg->subfield_dlg[eFieldTypeProtein] = EnumAssocSelectionDialog (g, prot_field_alist,
542                                                                 NULL, FALSE, 
543                                                                 dlg->change_notify, 
544                                                                 dlg->change_userdata);
545   dlg->subfield_dlg[eFieldTypeRNA] = EnumAssocSelectionDialog (g, rnax_field_alist,
546                                                                 NULL, FALSE, 
547                                                                 dlg->change_notify, 
548                                                                 dlg->change_userdata);
549   dlg->subfield_dlg[eFieldTypeBioSource] = EnumAssocSelectionDialog (g, orgref_field_alist,
550                                                                 NULL, FALSE, 
551                                                                 dlg->change_notify, 
552                                                                 dlg->change_userdata);
553   /* Set default BioSource field to scientific name */
554   vn.choice = ORGREF_SCI_NAME_FIELD;
555   vn.next = NULL;
556   vn.data.ptrvalue = NULL;
557   PointerToDialog (dlg->subfield_dlg[eFieldTypeBioSource], &vn);
558 
559   dlg->subfield_dlg[eFieldTypeOrgModSubSource] = SourceQualTypeSelectionDialog (g, FALSE,
560                                                                                 dlg->change_notify,
561                                                                                 dlg->change_userdata);
562                                                                                   
563   if (dlg->allowed_fields[eFieldTypeImport]) {
564     g2 = HiddenGroup (g, 2, 0, NULL);
565     dlg->impfeat_type = ImpFeatSelectDialog (g2, change_notify, change_userdata);
566     Hide (dlg->impfeat_type);
567 
568     dlg->subfield_dlg[eFieldTypeImport] = EnumAssocSelectionDialog (g2, impfeat_field_alist,
569                                                                 NULL, FALSE, 
570                                                                 dlg->change_notify, 
571                                                                 dlg->change_userdata);
572   }
573   dlg->subfield_dlg[eFieldTypeFeatureNote] = FeatureSelectionDialog (g, TRUE, dlg->change_notify, dlg->change_userdata);
574 
575   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->subfield_dlg[eFieldTypeGene],
576                               (HANDLE) dlg->subfield_dlg[eFieldTypeCDS],
577                               (HANDLE) dlg->subfield_dlg[eFieldTypeProtein],
578                               (HANDLE) dlg->subfield_dlg[eFieldTypeRNA],
579                               (HANDLE) dlg->subfield_dlg[eFieldTypeBioSource],
580                               (HANDLE) dlg->subfield_dlg[eFieldTypeOrgModSubSource],
581                               (HANDLE) dlg->subfield_dlg[eFieldTypeFeatureNote],
582                               (HANDLE) g2,
583                               NULL);
584 
585   for (i = 0; i < eFieldType_Max; i++) {
586     Hide (dlg->subfield_dlg[i]);
587   }
588   return (DialoG) p;
589 }
590 
591 
592 typedef struct convertformdata {
593   FEATURE_FORM_BLOCK
594 
595   TexT               deleteText;
596   CharPtr            deleteStr;
597   GrouP              deleteLevel;
598   Int2               deleteLevelInt;
599   DialoG             target_dlg;
600   Int2               impfeat_type;
601   ButtoN             accept;
602   ButtoN             leaveDlgUp;
603   Int2               type;
604   Int2               subtype;
605 
606   DialoG             textportion_dlg;
607   TextPortionXPtr     textportion;
608   Boolean            remove_inside;
609 
610   CharPtr            foundstr;
611   GrouP              repeat_remove_grp;
612 
613   Boolean            isDirty;
614   Boolean            repeat_remove;
615   GrouP              ifNotFoundGroup;
616   Int2               ifNotFound;
617   BioseqSetPtr       target_set;
618   Nlm_ChangeNotifyProc set_accept_proc;
619   ValNodePtr         id_list;
620 
621 } ConvertFormData, PNTR ConvertFormPtr;
622 
623 static ConvertFormPtr ConvertFormNew (void)
624 {
625   ConvertFormPtr cfp;
626 
627   cfp = (ConvertFormPtr) MemNew (sizeof (ConvertFormData));
628   if (cfp == NULL) return NULL;
629   MemSet (cfp, 0, sizeof (ConvertFormData));
630   return cfp;
631 }
632 
633 
634 /* Values for ifNotFound field */
635 
636 #define DO_NOTHING       2
637 #define REMOVE_ALL_TEXT  3
638 
639 /* End values for string trimming */
640 
641 #define TRIM_LEFT_END    1
642 #define TRIM_RIGHT_END   2
643 
644 /*-------------------------------------------------------------------------*/
645 /*                                                                         */
646 /* TrimOffEndQuotes () -- Trim double-quotes off the ends of a string.     */
647 /*                                                                         */
648 /*-------------------------------------------------------------------------*/
649 
650 static Boolean TrimOffEndQuotes (CharPtr trimString, 
651                                  Int2    whichEnd)
652 {
653   Int4 strLen;
654   Int4 i;
655 
656   strLen = StringLen(trimString);
657   if (strLen == 0)
658     return FALSE;
659 
660   /* If there is a quote at the end, remove it */
661 
662   if (TRIM_RIGHT_END == whichEnd) {
663     if (trimString[strLen-1] == '"') {
664       strLen--;
665       trimString [strLen] = '\0';
666       return TRUE;
667     }
668   }
669 
670   /* If there is a quote at the beginning, remove it */
671 
672   else {
673     if (trimString[0] == '"') {
674       for (i = 0; trimString[i] != '\0'; i++)
675         trimString[i] = trimString [i+1];
676       return TRUE;
677     }
678   }
679 
680   return FALSE;
681 }
682 
683 /*-------------------------------------------------------------------------*/
684 /*                                                                         */
685 /* SaveStringFromTextNoStripSpaces () -                                    */
686 /*                                                                         */
687 /*-------------------------------------------------------------------------*/
688 
689 static CharPtr SaveStringFromTextNoStripSpaces (TexT t)
690 
691 {
692   size_t   len;
693   CharPtr  str;
694 
695   len = TextLength (t);
696   if (len > 0) {
697     str = (CharPtr) MemNew(len + 1);
698     if (str != NULL) {
699       GetTitle (t, str, len + 1);
700       return str;
701     } else {
702       return NULL;
703     }
704   } else {
705     return NULL;
706   }
707 }
708 
709 static void ConvertFormTextCallback (TexT t)
710 {
711   ConvertFormPtr cfp;
712 
713   cfp = (ConvertFormPtr) GetObjectExtra (t);
714   if (cfp != NULL && cfp->set_accept_proc != NULL) {
715     (cfp->set_accept_proc) (cfp);
716   }
717 }
718 
719 
720 /*-------------------------------------------------------------------------*/
721 /*                                                                         */
722 /* SetDeleteAcceptButton () -- Enable/Disable the Accept button depending  */
723 /*                             on the condition of other window objects.   */
724 /*                                                                         */
725 /*-------------------------------------------------------------------------*/
726 
727 static void SetDeleteAcceptButton (Pointer data)
728 
729 {
730   ConvertFormPtr  cfp;
731   ValNodePtr      vnp;
732 
733   cfp = (ConvertFormPtr) data;
734   if (cfp == NULL)
735     return;
736 
737   /* Disable if a target or subtarget has not been selected */
738   vnp = TestDialog (cfp->target_dlg);
739   if (vnp != NULL) {
740     vnp = ValNodeFree (vnp);
741     SafeDisable (cfp->accept);
742   } else if (TextHasNoText (cfp->deleteText)) {
743     /* Disable if there is no delete string */
744     SafeDisable (cfp->accept);
745   } else {
746     SafeEnable (cfp->accept);
747   }
748 }
749 
750 
751 static void ChangeTargetFields (Pointer data)
752 
753 {
754   ConvertFormPtr  cfp;
755 
756   cfp = (ConvertFormPtr) data;
757   if (cfp == NULL) return;
758 
759   if (cfp->set_accept_proc != NULL) {
760     cfp->set_accept_proc (cfp);
761   }
762 }
763 
764 
765 /*=========================================================================*/
766 /*                                                                         */
767 /* CheckForString () -- Searches for a given string with another string.   */
768 /*                                                                         */
769 /*=========================================================================*/
770 
771 static Boolean CheckForString (CharPtr searchStr,
772                                CharPtr sourceStr)
773 {
774   if (NULL == SearchForString (sourceStr, searchStr, FALSE, FALSE))
775     return FALSE;
776   else
777     return TRUE;
778 }
779 
780 /*=========================================================================*/
781 /*                                                                         */
782 /* GeneRefPtr () -- Search a GeneRef feature for a given string.           */
783 /*                                                                         */
784 /*=========================================================================*/
785 
786 static Boolean SearchGeneRef (GeneRefPtr     grp,
787                               SeqFeatPtr     sfp,
788                               ConvertFormPtr cfp)
789 {
790   ValNodePtr vnp;
791 
792   /* Check parameters */
793 
794   if ((NULL == grp) || (NULL == sfp))
795     return FALSE;
796 
797   /* Check each text field for the given string */
798 
799   switch (cfp->subtype) {
800   case 1 :
801     return CheckForString (cfp->deleteStr, grp->locus);
802     break;
803   case 2 :
804     return CheckForString (cfp->deleteStr, grp->desc);
805     break;
806   case 3 :
807     return CheckForString (cfp->deleteStr, grp->allele);
808     break;
809   case 4 :
810     return CheckForString (cfp->deleteStr, grp->maploc);
811     break;
812   case 5 :
813     return CheckForString (cfp->deleteStr, grp->locus_tag);
814     break;
815   case 6 :
816     for (vnp = grp->syn; vnp != NULL; vnp = vnp->next) {
817       if (TRUE == CheckForString (cfp->deleteStr,
818                                   vnp->data.ptrvalue))
819         return TRUE;
820     }
821     return FALSE;
822     break;
823   case 7 :
824     return CheckForString (cfp->deleteStr, sfp->comment);
825     break;
826   default :
827     break;
828   }
829 
830   return FALSE;
831 }
832 
833 /*=========================================================================*/
834 /*                                                                         */
835 /* SearchCDSFeat () -- Search a CDS feature for a given string.            */
836 /*                                                                         */
837 /*=========================================================================*/
838 
839 static Boolean SearchCDSFeat (SeqFeatPtr     sfp,
840                               ConvertFormPtr cfp)
841 {
842 
843   /* Check parameters */
844 
845   if (NULL == sfp)
846     return FALSE;
847 
848   /* Check each text field for the given string */
849 
850   switch (cfp->subtype) {
851   case 1 :
852     return CheckForString (cfp->deleteStr, sfp->comment);
853     break;
854   case 2 :
855   default :
856     break;
857   }
858 
859   /* If no match found, return FALSE */
860 
861   return FALSE;
862 }
863 
864 /*=========================================================================*/
865 /*                                                                         */
866 /* SearchRnaRef () -- Search an RnaRef feature for a given string.         */
867 /*                                                                         */
868 /*=========================================================================*/
869 
870 static Boolean SearchRnaRef (RnaRefPtr      rrp,
871                              SeqFeatPtr     sfp,
872                              ConvertFormPtr cfp)
873 {
874   /* Check parameters */
875 
876   if ((NULL == rrp) || (NULL == sfp))
877     return FALSE;
878 
879   /* Check each text field for the given string */
880 
881   switch (cfp->subtype) {
882   case 1 :
883     if ((0 == rrp->ext.choice) || (1 == rrp->ext.choice)) {
884       return CheckForString (cfp->deleteStr, rrp->ext.value.ptrvalue);
885     }
886     break;
887   case 2 :
888     return CheckForString (cfp->deleteStr, sfp->comment);
889     break;
890   case 3 :
891   default :
892     break;
893   }
894 
895   /* If no match found, return FALSE */
896 
897   return FALSE;
898 }
899 
900 /*=========================================================================*/
901 /*                                                                         */
902 /* SearchProtRef () -- Search a ProtRef feature for a given string.        */
903 /*                                                                         */
904 /*=========================================================================*/
905 
906 static Boolean SearchProtRef (ProtRefPtr     prp,
907                               SeqFeatPtr     sfp,
908                               ConvertFormPtr cfp)
909 {
910   ValNodePtr vnp;
911 
912   /* Check parameters */
913 
914   if (NULL == prp)
915     return FALSE;
916 
917   /* Check each text field for the given string */
918 
919   switch (cfp->subtype) {
920 
921     /* Search the name field */  
922 
923   case 1 :
924     for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
925       if (TRUE == CheckForString (cfp->deleteStr,
926                                   (CharPtr) vnp->data.ptrvalue))
927         return TRUE;
928     }
929     break;
930 
931     /* Search the desc field */
932 
933   case 2 :
934     return CheckForString (cfp->deleteStr, prp->desc);
935     break;
936 
937     /* Search the ec field */
938 
939   case 3 :
940     for (vnp = prp->ec; vnp != NULL; vnp = vnp->next) {
941       if (TRUE == CheckForString (cfp->deleteStr, vnp->data.ptrvalue))
942         return TRUE;
943     }
944     break;
945 
946     /* Search the activity field */
947 
948   case 4 :
949     for (vnp = prp->activity; vnp != NULL; vnp = vnp->next) {
950       if (TRUE == CheckForString (cfp->deleteStr, vnp->data.ptrvalue))
951         return TRUE;
952     }
953     break;
954 
955     /* Search the comment field */
956 
957   case 5 :
958     return CheckForString (cfp->deleteStr, sfp->comment);
959     break;
960 
961     /* Default check */
962 
963   default :
964     break;
965   }
966 
967   /* If we made it this far no match was found */
968 
969   return FALSE;
970 }
971 
972 /*=========================================================================*/
973 /*                                                                         */
974 /* SearchImpFeat () -- Search an ImpFeat feature for a given string.       */
975 /*                                                                         */
976 /*=========================================================================*/
977 
978 static Boolean SearchImpFeat (SeqFeatPtr     sfp,
979                               ConvertFormPtr cfp)
980 {
981   GBQualPtr       gbqp;
982 
983   /* Check parameters */
984 
985   if (NULL == sfp)
986     return FALSE;
987 
988   switch (cfp->subtype) {
989 
990     /* Search the GB Quals */
991 
992   case IMPORT_GBQUAL_FIELD :
993     gbqp = sfp->qual;
994     while (NULL != gbqp) {
995       if (NULL != gbqp->val)
996         if (TRUE == CheckForString (cfp->deleteStr, gbqp->val))
997           return TRUE;
998       gbqp = gbqp->next;
999     }
1000     return FALSE;
1001     break;
1002 
1003     /* Search the comment field */
1004 
1005   case IMPORT_COMMENT_FIELD :
1006     return CheckForString (cfp->deleteStr, sfp->comment);
1007     break;
1008   default :
1009     break;
1010   }
1011 
1012   return FALSE;
1013 }
1014 
1015 /*=========================================================================*/
1016 /*                                                                         */
1017 /* MarkObjectsByText_Callback () - Called for each object in a SeqEntry    */
1018 /*                                 this will mark the item for deletion    */
1019 /*                                 if it matches the given criteria.       */
1020 /*                                                                         */
1021 /*=========================================================================*/
1022 
1023 static void DeleteFeaturesByText_Callback (SeqEntryPtr sep,
1024                                            Pointer     mydata,
1025                                            Int4        index,
1026                                            Int2        indent)
1027 {
1028   ConvertFormPtr cfp;
1029   BioseqPtr      bsp = NULL;
1030   BioseqSetPtr   bssp = NULL;
1031   SeqAnnotPtr    sap;
1032   SeqFeatPtr     sfp;
1033   GeneRefPtr     grp;
1034   ProtRefPtr     prp;
1035   RnaRefPtr      rrp;
1036   Boolean        found = FALSE;
1037 
1038   /* Check parameters */
1039 
1040   if ((NULL == sep) || (NULL == sep->data.ptrvalue))
1041     return;
1042 
1043   cfp = (ConvertFormPtr) mydata;
1044   if (NULL == cfp)
1045     return;
1046 
1047   /* Get the list of annotations */
1048 
1049   if (IS_Bioseq (sep)) {
1050     bsp = (BioseqPtr) sep->data.ptrvalue;
1051     sap = bsp->annot;
1052   }
1053   else if (IS_Bioseq_set (sep)) {
1054     bssp = (BioseqSetPtr) sep->data.ptrvalue;
1055     sap = bssp->annot;
1056   }
1057   else
1058     return;
1059 
1060   /* Search the requested item for the given string */
1061 
1062   while (sap != NULL) {
1063     if (sap->type == 1) {
1064       sfp = (SeqFeatPtr) sap->data;
1065       while (sfp != NULL) {
1066         if (sfp->data.choice == SEQFEAT_GENE && cfp->type == eFieldTypeGene) {
1067           grp = (GeneRefPtr) sfp->data.value.ptrvalue;
1068           found = SearchGeneRef (grp, sfp, cfp);
1069         }
1070         else if (sfp->data.choice == SEQFEAT_CDREGION &&
1071                  cfp->type == eFieldTypeCDS) {
1072           found = SearchCDSFeat (sfp, cfp);
1073         }
1074         else if (sfp->data.choice == SEQFEAT_PROT &&
1075                  cfp->type == eFieldTypeProtein) {
1076           prp = (ProtRefPtr) sfp->data.value.ptrvalue;
1077           found = SearchProtRef (prp, sfp, cfp);
1078         }
1079         else if (sfp->data.choice == SEQFEAT_RNA && cfp->type == eFieldTypeRNA) {
1080           rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
1081           found = SearchRnaRef (rrp, sfp, cfp);
1082         }
1083         else if (sfp->data.choice == SEQFEAT_IMP &&
1084                  cfp->type == eFieldTypeImport) {
1085           found = SearchImpFeat (sfp, cfp);
1086         }
1087         if (TRUE == found)
1088           break;
1089         else
1090           sfp = sfp->next;
1091       }
1092     }
1093     if (TRUE == found)
1094       break;
1095     else
1096       sap = sap->next;
1097   }
1098 
1099   /* If we found the string, do the deletion */
1100 
1101   if (TRUE == found) {
1102     cfp->isDirty = TRUE;
1103     switch (cfp->deleteLevelInt) {
1104     case 1 :
1105       sfp->idx.deleteme = TRUE;
1106       break;
1107     case 2 :
1108       if (bsp != NULL)
1109         bsp->idx.deleteme = TRUE;
1110       break;
1111     case 3 :
1112       if (bssp != NULL)
1113         bssp->idx.deleteme = TRUE;
1114       else if (bsp != NULL) {
1115         if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
1116           bssp = (BioseqSetPtr) bsp->idx.parentptr;
1117           bssp->idx.deleteme = TRUE;
1118         }
1119       }
1120       break;
1121     default:
1122       break;
1123     }
1124   }
1125 
1126   /* Return successfully */
1127 
1128   return;
1129 }
1130 
1131 static Boolean DoesBioSourceContainText 
1132 (BioSourcePtr biop,
1133  ConvertFormPtr cfp)
1134 {
1135   OrgRefPtr     orp;
1136   Boolean       found;
1137   OrgNamePtr    onp;
1138 
1139   if (biop == NULL || cfp == NULL) return FALSE;
1140 
1141   found = FALSE;
1142 
1143   orp = biop->org;
1144   if (orp == NULL) return FALSE;
1145   switch (cfp->subtype) {
1146     case ORGREF_SCI_NAME_FIELD :
1147       found = CheckForString (cfp->deleteStr, orp->taxname);
1148       break;
1149     case ORGREF_COMMON_NAME_FIELD :
1150           found = CheckForString (cfp->deleteStr, orp->common);
1151       break;
1152     case ORGREF_LINEAGE_FIELD :
1153       onp = orp->orgname;
1154       if (onp == NULL) {
1155         onp = OrgNameNew ();
1156         orp->orgname = onp;
1157       }
1158       if (onp != NULL)
1159             found = CheckForString (cfp->deleteStr, onp->lineage);
1160           else
1161             found = FALSE;
1162       break;
1163     case ORGREF_DIVISION_FIELD :
1164       onp = orp->orgname;
1165       if (onp == NULL) {
1166         onp = OrgNameNew ();
1167         orp->orgname = onp;
1168       }
1169       if (onp != NULL)
1170         found = CheckForString (cfp->deleteStr, onp->div);
1171           else
1172             found = FALSE;
1173       break;
1174     default :
1175       break;
1176   }
1177   return found;
1178 }
1179 
1180 static Boolean DoSubSourcesContainText 
1181 (BioSourcePtr biop,
1182  ConvertFormPtr cfp)
1183 {
1184   OrgRefPtr     orp;
1185   OrgModPtr     mod;
1186   SubSourcePtr  ssp;
1187   OrgNamePtr    onp;
1188   Boolean found = FALSE;
1189 
1190   if (biop == NULL || cfp == NULL) return FALSE;
1191   if (cfp->subtype < 1000) {
1192         orp = biop->org;
1193         if (orp == NULL) {
1194           orp = OrgRefNew ();
1195           biop->org = orp;
1196         }
1197         if (orp != NULL) {
1198           onp = orp->orgname;
1199           if (onp == NULL) {
1200             onp = OrgNameNew ();
1201             orp->orgname = onp;
1202           }
1203           if (onp != NULL) {
1204             mod = onp->mod;
1205             while (mod != NULL && mod->subtype != cfp->subtype) {
1206               mod = mod->next;
1207             }
1208             if (mod != NULL)
1209               found = CheckForString (cfp->deleteStr, mod->subname);
1210             else
1211               found = FALSE;
1212           }
1213           else
1214             found = FALSE;
1215         }
1216   } else {
1217         ssp = biop->subtype;
1218         while (ssp != NULL && ssp->subtype != (cfp->subtype - 1000)) {
1219           ssp = ssp->next;
1220         }
1221         while (ssp != NULL) {
1222           if (ssp->subtype == (cfp->subtype - 1000)) {
1223             found = CheckForString (cfp->deleteStr, ssp->name);
1224             if (found)
1225               break;
1226           }
1227           ssp = ssp->next;
1228         }
1229         if (NULL == ssp)
1230           found = FALSE;
1231   }
1232   return found;
1233 }
1234 
1235 /*=========================================================================*/
1236 /*                                                                         */
1237 /* DeleteSourceByText () - Given a text string, delete all items of a      */
1238 /*                         given type that contain that string.            */
1239 /*                                                                         */
1240 /*=========================================================================*/
1241 
1242 static void DeleteSourceByText (SeqDescrPtr    sdp,
1243                                 SeqEntryPtr    sep,
1244                                 BioseqPtr      bsp,
1245                                 ConvertFormPtr cfp)
1246 
1247 {
1248   Boolean       found = FALSE;
1249   BioseqSetPtr  bssp;
1250   BioSourcePtr  biop;
1251 
1252   /* Check parameters */
1253 
1254   if (sdp == NULL || cfp == NULL)
1255     return;
1256 
1257   if (Seq_descr_source != sdp->choice)
1258     return;
1259 
1260   biop = sdp->data.ptrvalue;
1261   if (NULL == biop)
1262     return;
1263 
1264   /* Search the source for the given string */
1265 
1266   switch (cfp->type) {
1267     case eFieldTypeBioSource :
1268       found = DoesBioSourceContainText (biop, cfp);
1269       break;
1270     case eFieldTypeOrgModSubSource :
1271       found = DoSubSourcesContainText (biop, cfp);
1272     default:
1273       break;
1274   }
1275 
1276   /* If we found anything to delete then */
1277   /* delete it and set the dirty flag.   */
1278 
1279   if (TRUE == found) {
1280     cfp->isDirty = TRUE;
1281     switch (cfp->deleteLevelInt) {
1282     case 1 :
1283       break;
1284     case 2 :
1285       if (IS_Bioseq (sep))
1286         bsp->idx.deleteme = TRUE;
1287       break;
1288     case 3 :
1289       if (IS_Bioseq_set (sep)) {
1290         bssp = (BioseqSetPtr) sep->data.ptrvalue;
1291         bssp->idx.deleteme = TRUE;
1292       } else {
1293         if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
1294           bssp = (BioseqSetPtr) bsp->idx.parentptr;
1295           bssp->idx.deleteme = TRUE;
1296         }
1297       }
1298       break;
1299     default:
1300       break;
1301     }
1302   }
1303 
1304   /* Return successfully */
1305 
1306   return;
1307 
1308 }
1309 
1310 
1311 static void DeleteSimpleDescriptorsByString (BioseqPtr bsp, CharPtr deleteStr, Uint1 desc_choice, BoolPtr isDirty)
1312 {
1313   SeqMgrDescContext dcontext;
1314   SeqDescrPtr        sdp;
1315   
1316   for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, desc_choice, &dcontext);
1317        sdp != NULL;
1318        sdp = SeqMgrGetNextDescriptor (bsp, sdp, desc_choice, &dcontext))
1319   {
1320     if (CheckForString (deleteStr, sdp->data.ptrvalue)) {
1321       if (sdp->extended != 0) {
1322         ((ObjValNodePtr)sdp)->idx.deleteme = TRUE;
1323         if (isDirty != NULL) {
1324           *isDirty = TRUE;
1325         }
1326       }
1327     }
1328   }
1329 }
1330 
1331 
1332 /*=========================================================================*/
1333 /*                                                                         */
1334 /* DeleteItemsByText () - Given a text string, delete all items of a given */
1335 /*                        type that contain that string.                   */
1336 /*                                                                         */
1337 /*=========================================================================*/
1338 
1339 static void DeleteItemsByText (SeqEntryPtr    sep,
1340                                ConvertFormPtr cfp)
1341 {
1342   BioseqSetPtr      bssp;
1343   BioseqPtr         bsp;
1344   SeqMgrDescContext descContext;
1345   /*
1346   Uint2             parenttype;
1347   Pointer           parentptr;
1348   SeqEntryPtr       parentSep;
1349   */
1350   SeqDescrPtr       sdp;
1351 
1352   /* If we have a Bioseq Set, then recurse until */
1353   /* we get down to an actual Bioseq.            */
1354 
1355   if (IS_Bioseq_set (sep)) {
1356 
1357     bssp = (BioseqSetPtr) sep->data.ptrvalue;
1358     if (NULL == bssp)
1359       return;
1360 
1361     for (sep = bssp->seq_set; sep != NULL; sep = sep->next)
1362       DeleteItemsByText (sep, cfp);
1363 
1364     return;
1365   }
1366 
1367   /* If we made it this far, then we have a Bioseq */
1368 
1369   bsp = (BioseqPtr) sep->data.ptrvalue;
1370 
1371   switch (cfp->type) {
1372     case  eFieldTypeGene :
1373     case eFieldTypeCDS :
1374     case eFieldTypeProtein :
1375     case eFieldTypeRNA :
1376     case eFieldTypeImport :
1377       SeqEntryExplore (sep, (Pointer) cfp, DeleteFeaturesByText_Callback);
1378       break;
1379     case eFieldTypeBioSource :
1380     case eFieldTypeOrgModSubSource :
1381       sdp = SeqMgrGetNextDescriptor (bsp, NULL, 0, &descContext);
1382       while (NULL != sdp) {
1383             sdp = SeqMgrGetNextDescriptor (bsp, sdp, 0, &descContext);
1384             DeleteSourceByText (sdp, sep, bsp, cfp);
1385       }
1386       /*
1387       SeqEntryToBioSource (sep, NULL, NULL, 0, &biop);
1388       if (NULL == biop) {
1389         GetSeqEntryParent (sep, &parentptr, &parenttype);
1390         SeqEntryToBioSource (parentSep, NULL, NULL, 0, &biop);
1391       }
1392       DeleteSourceByText (sep, bsp, biop, cfp);
1393       */
1394       break;
1395     case eFieldTypeDefline :
1396       DeleteSimpleDescriptorsByString (bsp, cfp->deleteStr, Seq_descr_title, &(cfp->isDirty));
1397       break;
1398     case eFieldTypeCommentDescriptor :
1399       DeleteSimpleDescriptorsByString (bsp, cfp->deleteStr, Seq_descr_comment, &(cfp->isDirty));
1400       break;
1401     default:
1402       break;
1403   }
1404 
1405   /* Return succesfully */
1406 
1407   return;
1408 }
1409 
1410 /*=========================================================================*/
1411 /*                                                                         */
1412 /* DeleteByText_Callback () - Finds and deletes all items of a selected    */
1413 /*                            type that contain a given text phrase.       */
1414 /*                                                                         */
1415 /*=========================================================================*/
1416 
1417 static void DeleteByText_Callback (ButtoN b)
1418 {
1419   ConvertFormPtr  cfp;
1420   SeqEntryPtr     sep;
1421   FieldSubfieldPtr f;
1422 
1423   /* Check the initial conditions and get the sequence */
1424 
1425   cfp = (ConvertFormPtr) GetObjectExtra (b);
1426   if (cfp == NULL || cfp->input_entityID == 0) {
1427     Remove (cfp->form);
1428     return;
1429   }
1430 
1431   sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
1432   if (sep == NULL) {
1433     Remove (cfp->form);
1434     return;
1435   }
1436 
1437   /* Get the string to search for */
1438 
1439   cfp->deleteStr = SaveStringFromTextNoStripSpaces (cfp->deleteText);
1440   if (StringHasNoText (cfp->deleteStr)){ 
1441     Remove (cfp->form);
1442     return;
1443   }
1444 
1445   /* Get the type of items to search */
1446   f = DialogToPointer (cfp->target_dlg);
1447   if (f == NULL || f->field < 0 || (f->subfield < 0 && f->subfield_list == NULL)) {
1448     Remove (cfp->form);
1449     f = FieldSubfieldFree (f);
1450     return;
1451   } else {
1452     cfp->type = f->field + 1;
1453     cfp->subtype = f->subfield;
1454   }
1455 
1456   /* Get the delete level */
1457 
1458   cfp->deleteLevelInt = GetValue (cfp->deleteLevel);
1459 
1460   /* Display the 'working' cursor */
1461 
1462   WatchCursor ();
1463   Update ();
1464 
1465   /* Do the search and mark and found objects for deletion */
1466 
1467   cfp->isDirty = FALSE;
1468   DeleteItemsByText (sep, cfp);
1469 
1470   /* Remove the window and update things */
1471 
1472   if (cfp->isDirty) {
1473     DeleteMarkedObjects (cfp->input_entityID, 0, NULL);
1474     ObjMgrSetDirtyFlag (cfp->input_entityID, TRUE);
1475     ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID, 0, 0);
1476   }
1477 
1478   ArrowCursor ();
1479   Update ();
1480   Remove (cfp->form);
1481 
1482   /* Return successfully */
1483 
1484   return;
1485 }
1486 
1487 static void CleanupDeleteByTextConvertForm (GraphiC g, VoidPtr data)
1488 {
1489   ConvertFormPtr  cfp;
1490 
1491   cfp = (ConvertFormPtr) data;
1492   StdCleanupFormProc (g, data);
1493 }
1494 
1495 /*=========================================================================*/
1496 /*                                                                         */
1497 /* CreateDeleteByTextWindow () - Creates and then display the window for   */
1498 /*                               getting delete by text info from the user.*/
1499 /*                                                                         */
1500 /*=========================================================================*/
1501 
1502 extern Int2 LIBCALLBACK CreateDeleteByTextWindow (Pointer data)
1503 {
1504   GrouP              c;
1505   ConvertFormPtr     cfp;
1506   GrouP              g;
1507   GrouP              h;
1508   GrouP              k;
1509   OMProcControlPtr   ompcp;
1510   GrouP              p;
1511   StdEditorProcsPtr  sepp;
1512   WindoW             w;
1513   Boolean            allowed[eFieldType_Max];
1514 
1515   /* Check parameters and get a pointer to the current data */
1516 
1517   ompcp = (OMProcControlPtr) data;
1518   if (ompcp == NULL)
1519     return OM_MSG_RET_ERROR;
1520 
1521   /* Create a new window, and a struct */
1522   /* to pass around the data in.       */
1523 
1524   cfp = ConvertFormNew ();
1525   if (cfp == NULL)
1526     return OM_MSG_RET_ERROR;
1527   cfp->set_accept_proc = SetDeleteAcceptButton;
1528 
1529   w = FixedWindow (-50, -33, -10, -10, "Delete By Text String",
1530                    StdCloseWindowProc);
1531   SetObjectExtra (w, cfp, CleanupDeleteByTextConvertForm);
1532   cfp->form = (ForM) w;
1533 
1534   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
1535   if (sepp != NULL) {
1536     SetActivate (w, sepp->activateForm);
1537     cfp->appmessage = sepp->handleMessages;
1538   }
1539 
1540   cfp->input_entityID = ompcp->input_entityID;
1541   cfp->input_itemID = ompcp->input_itemID;
1542   cfp->input_itemtype = ompcp->input_itemtype;
1543 
1544   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
1545   if (sepp != NULL) {
1546     SetActivate (w, sepp->activateForm);
1547     cfp->appmessage = sepp->handleMessages;
1548   }
1549 
1550   /* Add the popup lists */
1551 
1552   h = HiddenGroup (w, -1, 0, NULL);
1553   SetGroupSpacing (h, 10, 10);
1554 
1555   k = HiddenGroup (h, 3, 0, NULL);
1556 
1557   StaticPrompt (k, "Delete at the level of", 0, dialogTextHeight,
1558                 programFont, 'l');
1559   cfp->deleteLevel = HiddenGroup (k, 2, 0, NULL);
1560   RadioButton (cfp->deleteLevel, "Feature");
1561   RadioButton (cfp->deleteLevel, "Bioseq");
1562   RadioButton (cfp->deleteLevel, "Bioseq Set");
1563   SetValue (cfp->deleteLevel, 1);
1564 
1565   g = HiddenGroup (h, 3, 0, NULL);
1566 
1567   StaticPrompt (g, "Delete objects with the string", 0, dialogTextHeight,
1568                 programFont, 'l');
1569   cfp->deleteText = DialogText (g, "", 10, ConvertFormTextCallback);
1570   SetObjectExtra (cfp->deleteText, cfp, NULL);
1571 
1572   p = HiddenGroup (h, 6, 0, NULL);
1573   StaticPrompt (p, "Find string in", 0, popupMenuHeight, programFont, 'l');
1574   MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
1575   allowed[eFieldTypeCommentDescriptor] = FALSE;
1576   allowed[eFieldTypeFeatureNote] = FALSE;
1577   allowed[eFieldTypePublication] = FALSE;
1578 
1579   cfp->target_dlg = CreateFieldSubfieldDlg (p, allowed, ChangeTargetFields, cfp);
1580 
1581   /* Add Accept and Cancel buttons */
1582 
1583   c = HiddenGroup (h, 4, 0, NULL);
1584   cfp->accept = DefaultButton (c, "Accept", DeleteByText_Callback);
1585   SetObjectExtra (cfp->accept, cfp, NULL);
1586   Disable (cfp->accept);
1587   PushButton (c, "Cancel", StdCancelButtonProc);
1588 
1589   /* Line things up nicely */
1590 
1591   AlignObjects (ALIGN_LEFT, (HANDLE) p, (HANDLE) c, (HANDLE) h,
1592                 (HANDLE) k, NULL);
1593 
1594   /* Display the window now */
1595 
1596   RealizeWindow (w);
1597   Show (w);
1598   Select (w);
1599   Select (cfp->accept);
1600   Update ();
1601   return OM_MSG_RET_OK;
1602 }
1603 
1604 typedef Boolean (LIBCALLBACK *wantSegregateNucProtSetFunction) 
1605 ( BioseqSetPtr bssp,
1606   Pointer      userdata);
1607 
1608 typedef Boolean (LIBCALLBACK *wantSegregateSequenceFunction) 
1609 ( BioseqPtr bsp,
1610   Pointer   userdata);
1611   
1612 /*=========================================================================*/
1613 /*                                                                         */
1614 /* SegregateItemsRecursor () - Given a functions for determining which bioseqs     */
1615 /*                     meet conditions, segregate bioseqs into separate    */
1616 /*                     sets.                                               */
1617 /*                                                                         */
1618 /*=========================================================================*/
1619 
1620 static void SegregateItemsRecursor 
1621 (SeqEntryPtr                     seqlist,
1622  BioseqSetPtr                    set1,
1623  BioseqSetPtr                    set2,
1624  wantSegregateNucProtSetFunction do_np,
1625  wantSegregateSequenceFunction   do_seq,
1626  Pointer                         userdata
1627  )
1628 {
1629   
1630   BioseqPtr         bsp;
1631   BioseqSetPtr      this_bssp;
1632   SeqEntryPtr       this_list;
1633   SeqEntryPtr       sep, next_sep;
1634   SeqEntryPtr       set1last, set2last;
1635 
1636 
1637   if (set1 == NULL || set2 == NULL || seqlist == NULL)
1638     return;
1639 
1640   set1last = set1->seq_set;
1641   while (set1last != NULL && set1last->next != NULL) {
1642     set1last = set1last->next;
1643   }
1644   set2last = set2->seq_set;
1645   while (set2last != NULL && set2last->next != NULL) {
1646     set2last = set2last->next;
1647   }
1648 
1649   sep = seqlist;
1650   while (sep != NULL) {
1651     next_sep = sep->next;
1652     if (IS_Bioseq_set (sep)) {
1653       this_bssp = (BioseqSetPtr) sep->data.ptrvalue;
1654       if (this_bssp->_class == BioseqseqSet_class_nuc_prot) {
1655         if (do_np != NULL && do_np (this_bssp, userdata)) {
1656           if (set2last == NULL) {
1657             set2->seq_set = sep;
1658           } else {
1659             set2last->next = sep;
1660           }
1661           set2last = sep;
1662         } else {
1663           if (set1last == NULL) {
1664             set1->seq_set = sep;
1665           } else {
1666             set1last->next = sep;
1667           }
1668           set1last = sep;
1669         }
1670         sep->next = NULL;
1671       } else {
1672         /* copy class types from this set if class types are not set */
1673         if (set1->_class == BioseqseqSet_class_genbank 
1674             && set2->_class == BioseqseqSet_class_genbank) {
1675           set1->_class = this_bssp->_class;
1676           set2->_class = this_bssp->_class;
1677         }
1678         /* copy descriptors from this set */
1679         if (this_bssp != set1) {
1680           ValNodeLink (&(set1->descr),
1681                        AsnIoMemCopy ((Pointer) this_bssp->descr,
1682                                      (AsnReadFunc) SeqDescrAsnRead,
1683                                      (AsnWriteFunc) SeqDescrAsnWrite));
1684         }
1685         if (this_bssp != set2) {
1686           ValNodeLink (&(set2->descr),
1687                        AsnIoMemCopy ((Pointer) this_bssp->descr,
1688                                      (AsnReadFunc) SeqDescrAsnRead,
1689                                      (AsnWriteFunc) SeqDescrAsnWrite));
1690         }
1691         if (this_bssp != set1 && this_bssp != set2) {
1692           this_bssp->descr = SeqDescrFree (this_bssp->descr);
1693         }
1694         
1695         this_list = this_bssp->seq_set;
1696         this_bssp->seq_set = NULL;
1697         SegregateItemsRecursor (this_list, set1, set2, do_np, do_seq, userdata);
1698       }
1699     } else if (IS_Bioseq (sep)) {
1700       bsp = (BioseqPtr) sep->data.ptrvalue;
1701       if (do_seq != NULL && do_seq (bsp, userdata)) {
1702         if (set2last == NULL) {
1703           set2->seq_set = sep;
1704         } else {
1705           set2last->next = sep;
1706         }
1707         set2last = sep;
1708       } else {
1709         if (set1last == NULL) {
1710           set1->seq_set = sep;
1711         } else {
1712           set1last->next = sep;
1713         }
1714         set1last = sep;
1715       }
1716       sep->next = NULL;
1717     }
1718     sep = next_sep;
1719   }
1720 }
1721 
1722 
1723 static Boolean DoFeaturesInAnnotContainText (SeqAnnotPtr sap, ConvertFormPtr cfp)
1724 {
1725   SeqFeatPtr     sfp;
1726   GeneRefPtr     grp;
1727   ProtRefPtr     prp;
1728   RnaRefPtr      rrp;
1729   Boolean        found = FALSE;
1730   ValNodePtr     vnp;
1731   FieldSubfieldPtr f;
1732   
1733   if (sap == NULL || cfp == NULL) return FALSE;
1734   
1735   /* Search the requested item for the given string */
1736 
1737   while (sap != NULL && !found) {
1738     if (sap->type == 1) {
1739       sfp = (SeqFeatPtr) sap->data;
1740       while (sfp != NULL && !found) {
1741         if (sfp->data.choice == SEQFEAT_GENE && cfp->type == eFieldTypeGene) {
1742           grp = (GeneRefPtr) sfp->data.value.ptrvalue;
1743               found = SearchGeneRef (grp, sfp, cfp);
1744         } else if (sfp->data.choice == SEQFEAT_CDREGION && cfp->type == eFieldTypeCDS) {
1745               found = SearchCDSFeat (sfp, cfp);
1746         } else if (sfp->data.choice == SEQFEAT_PROT && cfp->type == eFieldTypeProtein) {
1747           prp = (ProtRefPtr) sfp->data.value.ptrvalue;
1748               found = SearchProtRef (prp, sfp, cfp);
1749         } else if (sfp->data.choice == SEQFEAT_RNA && cfp->type == eFieldTypeRNA) {
1750           rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
1751               found = SearchRnaRef (rrp, sfp, cfp);
1752         } else if (sfp->data.choice == SEQFEAT_IMP &&
1753                       cfp->type == eFieldTypeImport) {
1754               found = SearchImpFeat (sfp, cfp);
1755         } else if (cfp->type == eFieldTypeFeatureNote) {
1756           f = DialogToPointer (cfp->target_dlg);
1757           if (f != NULL) {
1758             for (vnp = f->subfield_list; vnp != NULL; vnp = vnp->next) {
1759               if (vnp->choice == sfp->idx.subtype 
1760                   && CheckForString (cfp->deleteStr, sfp->comment)) {
1761                 found = TRUE;
1762               }
1763             }
1764             f = FieldSubfieldFree (f);
1765           }
1766         }
1767         sfp = sfp->next;
1768       }
1769     }
1770     sap = sap->next;
1771   }
1772   return found;  
1773 }
1774 
1775 static Boolean DoFeaturesContainText_Callback 
1776 (BioseqPtr      bsp,
1777  ConvertFormPtr cfp)
1778 {
1779   
1780   SeqAnnotPtr    sap;
1781 
1782   /* Check parameters */
1783 
1784   if (bsp == NULL || cfp == NULL)
1785     return FALSE;
1786 
1787   /* Get the list of annotations */
1788 
1789   sap = bsp->annot;
1790 
1791   /* Search the requested item for the given string */
1792 
1793   return DoFeaturesInAnnotContainText (sap, cfp);
1794 }
1795 
1796 typedef struct objstringdata 
1797 {
1798   CharPtr match;
1799   Boolean found;        
1800 } ObjStringData, PNTR ObjStringPtr;
1801 
1802 static void LIBCALLBACK AsnWriteRemoveForDCallBack (AsnExpOptStructPtr pAEOS)
1803 
1804 {
1805   CharPtr        pchFind;
1806   CharPtr        pchSource;
1807   ObjStringPtr   osp;
1808 
1809   osp = (ObjStringPtr) pAEOS->data;
1810   if (ISA_STRINGTYPE (AsnFindBaseIsa (pAEOS->atp))) {
1811         pchSource = (CharPtr) pAEOS->dvp->ptrvalue;
1812         pchFind = osp->match;
1813         if (StringSearch (pchSource, pchFind) != NULL) {
1814           osp->found = TRUE;
1815         }
1816   }
1817 }
1818 
1819 static Boolean ObjectHasSubstring (ObjMgrTypePtr omtp, AsnIoPtr aip, Pointer ptr, ObjStringPtr osp)
1820 
1821 {
1822   osp->found = FALSE;
1823   (omtp->asnwrite) (ptr, aip, NULL);
1824   return osp->found;
1825 }
1826 
1827 static Uint1 GetPubStatus (PubdescPtr pdp)
1828 {
1829   ValNodePtr vnp;
1830   CitGenPtr  cgp;
1831   CitArtPtr  cap;
1832   CitJourPtr cjp;
1833   CitBookPtr cbp;
1834   CitSubPtr  csp;
1835   MedlineEntryPtr mlp;
1836   ImprintPtr ip = NULL;
1837   Uint1      status = 255; /* 255 is currently not a valid status */
1838   
1839   if (pdp == NULL) return status;
1840   
1841   for (vnp = pdp->pub; vnp != NULL && ip == NULL; vnp = vnp->next)
1842   {
1843         switch (vnp->choice)
1844         {
1845           case PUB_Gen:
1846         cgp = (CitGenPtr) vnp->data.ptrvalue;
1847             if (cgp != NULL && StringICmp (cgp->cit, "Unpublished"))
1848             {
1849                   return PUB_STATUS_UNPUBLISHED;
1850             }
1851             break;
1852           case PUB_Article:
1853           case PUB_Medline:
1854             if (vnp->choice == PUB_Article)
1855             {
1856               cap = (CitArtPtr) vnp->data.ptrvalue;
1857             }
1858             else
1859             {
1860               cap = NULL;
1861               mlp = (MedlineEntryPtr) vnp->data.ptrvalue;
1862               if (mlp != NULL)
1863               {
1864                 cap = mlp->cit;
1865               }
1866             }
1867             if (cap != NULL && cap->from == 1)
1868             {
1869               cjp = (CitJourPtr) cap->fromptr;
1870               if (cjp != NULL)
1871               {
1872                 ip = cjp->imp;
1873               }
1874             }
1875             break;
1876           case PUB_Man:
1877       case PUB_Book:
1878         cbp = (CitBookPtr) vnp->data.ptrvalue;
1879         if (cbp != NULL)
1880         {
1881           ip = cbp->imp;
1882         }
1883         break;
1884           case PUB_Sub:
1885             csp = (CitSubPtr) vnp->data.ptrvalue;
1886             if (csp != NULL)
1887             {
1888               ip = csp->imp;
1889             }
1890             break; 
1891         }
1892   }
1893   if (ip != NULL)
1894   {
1895         status = ip->prepub;
1896   }
1897   return status;  
1898 }
1899 
1900 static Boolean DoesPubStatusMatch (PubdescPtr pdp, ConvertFormPtr cfp)
1901 {
1902   Uint1 pub_status;
1903   
1904   if (pdp == NULL || cfp == NULL) return FALSE;
1905   if (cfp->subtype == 0) return TRUE;
1906   
1907   pub_status = GetPubStatus (pdp);
1908   
1909   if (cfp->subtype == PUBLICATION_PUBLISHED_FIELD 
1910       && pub_status == PUB_STATUS_PUBLISHED)
1911   {
1912         return TRUE;
1913   }
1914   else if (cfp->subtype == PUBLICATION_INPRESS_FIELD
1915       && pub_status == PUB_STATUS_IN_PRESS)
1916   {
1917         return TRUE;
1918   }
1919   else if (cfp->subtype == PUBLICATION_UNPUB_FIELD
1920       && pub_status == PUB_STATUS_UNPUBLISHED)
1921   {
1922         return TRUE;
1923   }
1924   else
1925   {
1926         return FALSE;
1927   }
1928 }
1929 
1930 static Boolean DoesSequenceHavePubWithText (BioseqPtr bsp, ConvertFormPtr cfp)
1931 {
1932   AsnExpOptPtr      aeop;
1933   AsnIoPtr          aip;
1934   ObjStringData     osd;
1935   SeqMgrDescContext dcontext;
1936   SeqDescrPtr       sdp;
1937   SeqMgrFeatContext fcontext;
1938   SeqFeatPtr        sfp;
1939   Boolean           rval = FALSE;
1940   ObjMgrPtr         omp;
1941   ObjMgrTypePtr     omtp;
1942   PubdescPtr        pdp;
1943 
1944   if (bsp == NULL || cfp == NULL) return FALSE;
1945   omp = ObjMgrGet ();
1946   if (omp == NULL) return FALSE;
1947   omtp = ObjMgrTypeFind (omp, OBJ_SEQDESC, NULL, NULL);
1948   if (omtp == NULL) return FALSE;
1949   
1950   aip = AsnIoNullOpen ();
1951   aeop = AsnExpOptNew (aip, NULL, NULL, AsnWriteRemoveForDCallBack);
1952   if (aeop != NULL) {
1953     aeop->user_data = (Pointer) &osd;
1954   }
1955   osd.match = cfp->deleteStr;
1956 
1957   /* look for publication descriptors */
1958   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_pub, &dcontext);
1959   while (sdp != NULL && !rval) {
1960     if (ObjectHasSubstring (omtp, aip, (Pointer) sdp, &osd)) {
1961       pdp = (PubdescPtr) sdp->data.ptrvalue;
1962       if (DoesPubStatusMatch (pdp, cfp))
1963       {
1964         rval = TRUE;
1965       }
1966     }
1967     sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_pub, &dcontext);
1968   }
1969   
1970   if (!rval)
1971   { 
1972     omtp = ObjMgrTypeFind (omp, OBJ_SEQFEAT, NULL, NULL);
1973     if (omtp != NULL) 
1974     {   
1975       /* look for publication features */
1976       sfp = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_PUB, &fcontext);
1977       while (sfp != NULL && !rval) 
1978       {
1979         if (ObjectHasSubstring (omtp, aip, (Pointer) sfp, &osd))
1980         {
1981           pdp = (PubdescPtr) sfp->data.value.ptrvalue;
1982           if (DoesPubStatusMatch (pdp, cfp))
1983           {
1984             rval = TRUE;
1985           }
1986         }
1987         sfp = SeqMgrGetNextFeature (bsp, sfp, 0, FEATDEF_PUB, &fcontext);
1988       }
1989     }
1990   }
1991   
1992   AsnIoClose (aip); 
1993   return rval;
1994 }
1995 
1996 static Boolean DoesNucProtSetHavePubWithText (BioseqSetPtr bssp, ConvertFormPtr cfp)
1997 {
1998   AsnExpOptPtr      aeop;
1999   AsnIoPtr          aip;
2000   ObjStringData     osd;
2001   SeqDescrPtr       sdp;
2002   Boolean           rval = FALSE;
2003   ObjMgrPtr         omp;
2004   ObjMgrTypePtr     omtp;
2005   PubdescPtr        pdp;
2006   
2007   if (bssp == NULL || cfp == NULL) return FALSE;  
2008   omp = ObjMgrGet ();
2009   if (omp == NULL) return FALSE;
2010   omtp = ObjMgrTypeFind (omp, OBJ_SEQDESC, NULL, NULL);
2011   if (omtp == NULL) return FALSE;
2012 
2013   aip = AsnIoNullOpen ();
2014   aeop = AsnExpOptNew (aip, NULL, NULL, AsnWriteRemoveForDCallBack);
2015   if (aeop != NULL) {
2016     aeop->user_data = (Pointer) &osd;
2017   }
2018   osd.match = cfp->deleteStr;
2019 
2020   /* look for publication descriptors */
2021   sdp = bssp->descr;
2022   while (sdp != NULL && !rval) {
2023     if (sdp->choice == Seq_descr_pub && ObjectHasSubstring (omtp, aip, (Pointer) sdp, &osd)) {
2024       pdp = (PubdescPtr) sdp->data.ptrvalue;
2025       if (DoesPubStatusMatch (pdp, cfp))
2026       {
2027         rval = TRUE;
2028       }
2029     }
2030     sdp = sdp->next;
2031   }
2032   
2033   AsnIoClose (aip); 
2034   return rval;
2035 }
2036 
2037 static Boolean DoesSimpleDescriptorForSequenceContainText (BioseqPtr bsp, CharPtr checkStr, Uint1 desc_choice)
2038 {
2039   SeqMgrDescContext dcontext;
2040   SeqDescrPtr       sdp;
2041   Boolean           found = FALSE;
2042 
2043   for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, desc_choice, &dcontext);
2044        sdp != NULL && !found;
2045        sdp = SeqMgrGetNextDescriptor (bsp, sdp, desc_choice, &dcontext))
2046   {
2047     found = CheckForString (checkStr, sdp->data.ptrvalue);
2048   }
2049   return found;
2050 }
2051 
2052 
2053 static Boolean LIBCALLBACK DoesSequenceContainText (BioseqPtr bsp, Pointer userdata)
2054 {
2055   BioSourcePtr biop;
2056   ConvertFormPtr cfp;
2057   Boolean      found = FALSE;
2058   SeqDescrPtr       sdp;
2059   SeqMgrDescContext descContext;
2060 
2061   cfp = (ConvertFormPtr) userdata;
2062   if (bsp == NULL || cfp == NULL) return FALSE;
2063 
2064   switch (cfp->type) {
2065     case eFieldTypeGene :
2066     case eFieldTypeCDS :
2067     case eFieldTypeProtein :
2068     case eFieldTypeRNA :
2069     case eFieldTypeImport :
2070     case eFieldTypeFeatureNote :
2071       found = DoFeaturesContainText_Callback (bsp, cfp);
2072       break;
2073     case eFieldTypeBioSource :
2074     case eFieldTypeOrgModSubSource :
2075       sdp = SeqMgrGetNextDescriptor (bsp, NULL, 0, &descContext);
2076       while (NULL != sdp && ! found) {
2077         if (Seq_descr_source == sdp->choice 
2078             && (biop = sdp->data.ptrvalue) != NULL) {
2079           if (cfp->type == eFieldTypeBioSource) {
2080             found = DoesBioSourceContainText (biop, cfp);
2081           } else if (cfp->type == eFieldTypeOrgModSubSource) {
2082             found = DoSubSourcesContainText (biop, cfp);
2083           }
2084         }
2085         sdp = SeqMgrGetNextDescriptor (bsp, sdp, 0, &descContext);
2086       }
2087       break;
2088     case eFieldTypeDefline :
2089       found = DoesSimpleDescriptorForSequenceContainText (bsp, cfp->deleteStr, Seq_descr_title);
2090       break;
2091     case eFieldTypeCommentDescriptor:
2092       found = DoesSimpleDescriptorForSequenceContainText (bsp, cfp->deleteStr, Seq_descr_comment);
2093       break;
2094         case eFieldTypePublication :
2095           found = DoesSequenceHavePubWithText (bsp, cfp);
2096           break;
2097     default:
2098       break;
2099   }
2100   return found;
2101 }
2102 
2103 static Boolean LIBCALLBACK  DoesNucProtSetContainText (BioseqSetPtr bssp, Pointer userdata)
2104 {
2105   SeqEntryPtr sep;
2106   BioseqPtr   bsp;
2107   ConvertFormPtr cfp;
2108 
2109   if (bssp == NULL) return FALSE;
2110   cfp = (ConvertFormPtr) userdata;
2111   if (cfp == NULL) return FALSE;
2112   if (cfp->type == eFieldTypePublication && DoesNucProtSetHavePubWithText (bssp, cfp))
2113   {
2114         return TRUE;
2115   }
2116   if (DoFeaturesInAnnotContainText (bssp->annot, cfp))
2117   {
2118         return TRUE;
2119   }
2120 
2121   for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
2122     if (IS_Bioseq (sep)) {
2123       bsp = (BioseqPtr) sep->data.ptrvalue;
2124       if (DoesSequenceContainText (bsp, (Pointer)cfp)) {
2125         return TRUE;
2126       }
2127     }
2128   }
2129   return FALSE;
2130 }
2131 
2132 static void SegregateItemsByText 
2133 (SeqEntryPtr                     seqlist,
2134  ConvertFormPtr                  cfp,
2135  BioseqSetPtr                    set1,
2136  BioseqSetPtr                    set2)
2137 {
2138   SegregateItemsRecursor (seqlist, set1, set2, 
2139                   DoesNucProtSetContainText,
2140                   DoesSequenceContainText, (Pointer)cfp);
2141 }
2142 
2143 typedef void (LIBCALLBACK *segregateFunction) (
2144   SeqEntryPtr  seqlist,
2145   Pointer      userdata,
2146   BioseqSetPtr set1,
2147   BioseqSetPtr set2
2148 );
2149 
2150 
2151 static void CreateSetsForSegregate (BioseqSetPtr bssp, BioseqSetPtr PNTR pNewSet1, BioseqSetPtr PNTR pNewSet2)
2152 {
2153   BioseqSetPtr parent_set;
2154   SeqEntryPtr  tmp1, tmp2, last_sep;
2155   BioseqSetPtr newset1, newset2;
2156   
2157   if (bssp == NULL || pNewSet1 == NULL || pNewSet2 == NULL) return;
2158   
2159   parent_set = (BioseqSetPtr)(bssp->idx.parentptr);
2160 
2161   if (parent_set == NULL || parent_set->seq_set == NULL) {
2162     /* this set has no parent, so make it the parent set, class GenBank,
2163      * and create two new sets using the original set class as members of this set
2164      */
2165     newset1 = BioseqSetNew ();
2166     if (newset1 == NULL) return;
2167     newset2 = BioseqSetNew ();
2168     if (newset2 == NULL) return;
2169     newset1->_class = bssp->_class;
2170     newset2->_class = bssp->_class;
2171     tmp1 = SeqEntryNew ();
2172     if (tmp1 == NULL) return;
2173     tmp1->choice = 2;
2174     tmp1->data.ptrvalue = (Pointer) newset1;
2175     tmp2 = SeqEntryNew ();
2176     if (tmp2 == NULL) return;
2177     tmp2->choice = 2;
2178     tmp2->data.ptrvalue = (Pointer) newset2;
2179     bssp->seq_set = tmp1;
2180     tmp1->next = tmp2;
2181     bssp->_class = BioseqseqSet_class_genbank;
2182     /* Propagate descriptors down */
2183     ValNodeLink (&(newset1->descr),
2184                  AsnIoMemCopy ((Pointer) bssp->descr,
2185                                (AsnReadFunc) SeqDescrAsnRead,
2186                                (AsnWriteFunc) SeqDescrAsnWrite));
2187     ValNodeLink (&(newset2->descr),
2188                  AsnIoMemCopy ((Pointer) bssp->descr,
2189                                (AsnReadFunc) SeqDescrAsnRead,
2190                                (AsnWriteFunc) SeqDescrAsnWrite));
2191     bssp->descr = SeqDescrFree (bssp->descr);
2192   } else {
2193     last_sep = parent_set->seq_set;
2194     newset1 = bssp;
2195     newset2 = BioseqSetNew ();
2196     if (newset2 == NULL) return;
2197     newset2->_class = newset1->_class;
2198     tmp1 = SeqEntryNew ();
2199     if (tmp1 == NULL) return;
2200     tmp1->choice = 2;
2201     tmp1->data.ptrvalue = (Pointer) newset2;
2202     while (last_sep != NULL && last_sep->next != NULL) {
2203       last_sep = last_sep->next;
2204     }
2205     if (last_sep == NULL) return;
2206     last_sep->next = tmp1;
2207     /* copy descriptors horizontally */
2208     ValNodeLink (&(newset2->descr),
2209                  AsnIoMemCopy ((Pointer) bssp->descr,
2210                                (AsnReadFunc) SeqDescrAsnRead,
2211                                (AsnWriteFunc) SeqDescrAsnWrite));
2212   }
2213   *pNewSet1 = newset1;
2214   *pNewSet2 = newset2;
2215 }  
2216   
2217 
2218 static void SegregateItemsGenericCallback
2219 (SeqEntryPtr       sep,
2220  BioseqSetPtr      bssp,
2221  Uint2             entityID,
2222  Pointer           userdata,
2223  segregateFunction seg_func)
2224 {
2225   ObjMgrDataPtr     omdptop;
2226   ObjMgrData        omdata;
2227   BioseqSetPtr      newset1;
2228   BioseqSetPtr      newset2;
2229   Uint2             parenttype;
2230   Pointer           parentptr;
2231   SeqEntryPtr       seqlist;
2232 
2233   if (sep == NULL || seg_func == NULL) return;
2234   /* Display the 'working' cursor */
2235 
2236   WatchCursor ();
2237   Update ();
2238 
2239 
2240   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
2241   GetSeqEntryParent (sep, &parentptr, &parenttype);
2242 
2243   seqlist = bssp->seq_set;
2244   bssp->seq_set = NULL;
2245 
2246   CreateSetsForSegregate (bssp, &newset1, &newset2);
2247 
2248   /* Do the search and move sequences */
2249   (*seg_func)(seqlist, userdata, newset1, newset2);
2250 
2251   /* Remove the window and update things */
2252   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
2253   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata); 
2254   ObjMgrSetDirtyFlag (entityID, TRUE);
2255   ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
2256 
2257   ArrowCursor ();
2258   Update ();
2259   
2260   /* Return successfully */
2261   return;
2262   
2263 }
2264  
2265 
2266 static Boolean OkToSegregate (OMProcControlPtr ompcp)
2267 {
2268   if (ompcp == NULL
2269       || ompcp->input_itemtype != OBJ_BIOSEQSET 
2270       || ompcp->input_data == NULL) {
2271     Message (MSG_ERROR, "You must select a set to segregate!");
2272     return FALSE;
2273   } else {
2274     return TRUE;
2275   }
2276 }
2277 
2278 
2279 /*=========================================================================*/
2280 /*                                                                         */
2281 /* SegregateByText_Callback () - Finds and deletes all items of a selected */
2282 /*                            type that contain a given text phrase.       */
2283 /*                                                                         */
2284 /*=========================================================================*/
2285 
2286 static void SegregateByText_Callback (ButtoN b)
2287 {
2288   ConvertFormPtr    cfp;
2289   SeqEntryPtr       sep;
2290   BioseqSetPtr      bssp;
2291   SeqEntryPtr       seqlist;
2292   BioseqSetPtr      newset1, newset2;
2293   ObjMgrDataPtr     omdptop;
2294   ObjMgrData        omdata;
2295   Uint2             parenttype;
2296   Pointer           parentptr;
2297   Boolean           leaveDlgUp = FALSE;
2298   FieldSubfieldPtr  f;
2299 
2300   /* Check the initial conditions and get the sequence */
2301   cfp = (ConvertFormPtr) GetObjectExtra (b);
2302   if (cfp == NULL || cfp->input_entityID == 0 || cfp->target_set == NULL) {
2303     Remove (cfp->form);
2304     return;
2305   }
2306 
2307   sep = GetTopSeqEntryForEntityID (cfp->input_entityID); 
2308   if (sep == NULL) {
2309     Remove (cfp->form);
2310     return;
2311   }
2312   
2313   if (GetStatus (cfp->leaveDlgUp))
2314   {
2315         leaveDlgUp = TRUE;
2316   }
2317 
2318   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
2319   GetSeqEntryParent (sep, &parentptr, &parenttype);
2320 
2321   bssp = cfp->target_set;
2322   seqlist = bssp->seq_set;
2323   bssp->seq_set = NULL;
2324 
2325   CreateSetsForSegregate (bssp, &newset1, &newset2);
2326 
2327   /* Get the string to search for */
2328 
2329   cfp->deleteStr = SaveStringFromTextNoStripSpaces (cfp->deleteText);
2330   if (StringHasNoText (cfp->deleteStr)){ 
2331     if (!leaveDlgUp)
2332     {
2333       Remove (cfp->form);
2334     }
2335     return;
2336   }
2337 
2338   /* Get the type of items to search */
2339   f = DialogToPointer (cfp->target_dlg);
2340   if (f == NULL || f->field < 0 || (f->subfield < 0 && f->subfield_list == NULL)) {
2341     f = FieldSubfieldFree (f);
2342     if (!leaveDlgUp)
2343     {
2344       Remove (cfp->form);
2345     }
2346     return;
2347   }
2348   
2349   cfp->type = f->field;
2350   cfp->subtype = f->subfield;
2351   f = FieldSubfieldFree (f);
2352 
2353   /* Display the 'working' cursor */
2354 
2355   WatchCursor ();
2356   Update ();
2357 
2358   /* Do the search and move sequences */
2359   SegregateItemsByText (seqlist, cfp, newset1, newset2);
2360 
2361   /* Remove the window and update things */
2362   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
2363   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata); 
2364   ObjMgrSetDirtyFlag (cfp->input_entityID, TRUE);
2365   ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID, 0, 0);
2366 
2367   ArrowCursor ();
2368   Update ();
2369   if (!leaveDlgUp)
2370   {
2371     Remove (cfp->form);
2372   }
2373 
2374   /* Return successfully */
2375   return;
2376 }
2377 
2378 
2379 
2380 
2381 /*-------------------------------------------------------------------------*/
2382 /*                                                                         */
2383 /* SetSegregateAcceptButton () -- Enable/Disable the Accept button depending  */
2384 /*                             on the condition of other window objects.   */
2385 /*                                                                         */
2386 /*-------------------------------------------------------------------------*/
2387 
2388 static void SetSegregateAcceptButton (Pointer data)
2389 
2390 {
2391   ConvertFormPtr  cfp;
2392   FieldSubfieldPtr f;
2393 
2394   cfp = (ConvertFormPtr) data;
2395   if (cfp == NULL)
2396     return;
2397 
2398   /* Disable if a target has not been selected */
2399   f = DialogToPointer (cfp->target_dlg);
2400   if (f == NULL || f->field < 0 || (f->subfield < 0 && f->subfield_list == NULL)) {
2401     SafeDisable (cfp->accept);
2402     f = FieldSubfieldFree (f);
2403     return;
2404   }
2405   f = FieldSubfieldFree (f);
2406 
2407   if (cfp->deleteText != NULL) {
2408     /* Disable if there is no delete string */ 
2409     if (TextHasNoText (cfp->deleteText)) {
2410       SafeDisable (cfp->accept);
2411       return;
2412     }
2413   }
2414 
2415   /* If we made it to here, then we passed all */
2416   /* test and can enable the accept button.    */
2417 
2418   SafeEnable (cfp->accept);
2419 }
2420 
2421 static void CleanupSegregatePage (GraphiC g, VoidPtr data)
2422 
2423 {
2424   ConvertFormPtr  cfp;
2425 
2426   cfp = (ConvertFormPtr) data;
2427   if (cfp != NULL) {
2428   }
2429   StdCleanupFormProc (g, data);
2430 }
2431 
2432 /*=========================================================================*/
2433 /*                                                                         */
2434 /* CreateSegregateByTextWindow () - Creates and then displays the window   */
2435 /*                        for getting segregate by text info from the user.*/
2436 /*                                                                         */
2437 /*=========================================================================*/
2438 
2439 extern Int2 LIBCALLBACK CreateSegregateByTextWindow (Pointer data)
2440 {
2441   Boolean            allowed[eFieldType_Max];
2442   GrouP              c;
2443   ConvertFormPtr     cfp;
2444   GrouP              g;
2445   GrouP              h;
2446   OMProcControlPtr   ompcp;
2447   GrouP              p;
2448   StdEditorProcsPtr  sepp;
2449   WindoW             w;
2450 
2451   /* Check parameters and get a pointer to the current data */
2452 
2453   ompcp = (OMProcControlPtr) data;
2454   if (!OkToSegregate(ompcp)) {
2455     return OM_MSG_RET_ERROR;
2456   }
2457 
2458   /* Create a new window, and a struct */
2459   /* to pass around the data in.       */
2460 
2461   cfp = ConvertFormNew ();
2462   if (cfp == NULL)
2463     return OM_MSG_RET_ERROR;
2464   cfp->target_set = (BioseqSetPtr)ompcp->input_data;
2465   cfp->set_accept_proc = SetSegregateAcceptButton;
2466 
2467   w = FixedWindow (-50, -33, -10, -10, "Segregate By Text String",
2468                    StdCloseWindowProc);
2469   SetObjectExtra (w, cfp, CleanupSegregatePage);
2470   cfp->form = (ForM) w;
2471 
2472   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2473   if (sepp != NULL) {
2474     SetActivate (w, sepp->activateForm);
2475     cfp->appmessage = sepp->handleMessages;
2476   }
2477 
2478   cfp->input_entityID = ompcp->input_entityID;
2479   cfp->input_itemID = ompcp->input_itemID;
2480   cfp->input_itemtype = ompcp->input_itemtype;
2481 
2482   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2483   if (sepp != NULL) {
2484     SetActivate (w, sepp->activateForm);
2485     cfp->appmessage = sepp->handleMessages;
2486   }
2487 
2488   /* Add the popup lists */
2489 
2490   h = HiddenGroup (w, -1, 0, NULL);
2491   SetGroupSpacing (h, 10, 10);
2492 
2493   g = HiddenGroup (h, 3, 0, NULL);
2494 
2495   StaticPrompt (g, "Segregate sequences with the string", 0, dialogTextHeight,
2496                 programFont, 'l');
2497   cfp->deleteText = DialogText (g, "", 10, ConvertFormTextCallback);
2498   SetObjectExtra (cfp->deleteText, cfp, NULL);
2499 
2500   p = HiddenGroup (h, 6, 0, NULL);
2501   StaticPrompt (p, "Find string in", 0, popupMenuHeight, programFont, 'l');
2502   MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
2503   allowed[eFieldTypeCommentDescriptor] = TRUE;
2504 
2505   cfp->target_dlg = CreateFieldSubfieldDlg (p, allowed, ChangeTargetFields, cfp);
2506 
2507   /* Add Accept and Cancel buttons */
2508 
2509   c = HiddenGroup (h, 4, 0, NULL);
2510   cfp->accept = DefaultButton (c, "Accept", SegregateByText_Callback);
2511   SetObjectExtra (cfp->accept, cfp, NULL);
2512   Disable (cfp->accept);
2513   PushButton (c, "Cancel", StdCancelButtonProc);
2514   cfp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
2515 
2516   /* Line things up nicely */
2517 
2518   AlignObjects (ALIGN_LEFT, (HANDLE) p, (HANDLE) c, (HANDLE) h, NULL);
2519 
2520   /* Display the window now */
2521 
2522   RealizeWindow (w);
2523   Show (w);
2524   Select (w);
2525   Select (cfp->accept);
2526   Update ();
2527   return OM_MSG_RET_OK;
2528 }
2529 
2530 
2531 typedef struct segregatefeatdata {
2532   FEATURE_FORM_BLOCK
2533 
2534   PopuP        type_popup;
2535   ValNodePtr   type_list;
2536   ButtoN       accept;
2537   
2538   BioseqSetPtr target_set;
2539   Uint2        segregate_type;
2540   Boolean      is_feat;
2541 } SegregateFeatData, PNTR SegregateFeatPtr;
2542 
2543 static Boolean LIBCALLBACK DoesSequenceContainFeatureType (BioseqPtr bsp, Pointer userdata)
2544 {
2545   SeqMgrFeatContext context;
2546   SeqFeatPtr        feat;
2547   SegregateFeatPtr  sfp;
2548   
2549   sfp = (SegregateFeatPtr) userdata;
2550   if (sfp == NULL || bsp == NULL) return FALSE;
2551   
2552   feat = NULL;
2553   while ((feat = SeqMgrGetNextFeature (bsp, feat, 0, 0, &context)) != NULL)
2554   {
2555         if (feat->idx.subtype == sfp->segregate_type)
2556         {
2557           return TRUE;
2558         }
2559   }
2560   return FALSE;
2561 }
2562 
2563 static Boolean LIBCALLBACK DoesNucProtSetContainFeatureType (BioseqSetPtr bssp, Pointer userdata)
2564 {
2565   SeqEntryPtr sep;
2566   BioseqPtr   bsp;
2567   SegregateFeatPtr  sfp;
2568   
2569   sfp = (SegregateFeatPtr) userdata;
2570   if (sfp == NULL || bssp == NULL) return FALSE;
2571 
2572   for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
2573     if (IS_Bioseq (sep)) {
2574       bsp = (BioseqPtr) sep->data.ptrvalue;
2575       if (DoesSequenceContainFeatureType (bsp, sfp)) {
2576         return TRUE;
2577       }
2578     }
2579   }
2580   return FALSE; 
2581 }
2582 
2583 static Boolean LIBCALLBACK DoesSequenceContainDescriptorType (BioseqPtr bsp, Pointer userdata)
2584 {
2585   SeqMgrDescContext context;
2586   SeqDescPtr        desc;
2587   SegregateFeatPtr  sfp;
2588   
2589   sfp = (SegregateFeatPtr) userdata;
2590   if (sfp == NULL || bsp == NULL) return FALSE;
2591   
2592   if((desc = SeqMgrGetNextDescriptor (bsp, NULL, sfp->segregate_type, &context)) != NULL)
2593   {
2594         return TRUE;
2595   }
2596   return FALSE;
2597 }
2598 
2599 typedef struct checkdescdata {
2600   Uint2   segregate_type;
2601   Boolean found;
2602 } CheckDescData, PNTR CheckDescPtr;
2603 
2604 static void DoesSetContainDescriptorType_Callback (SeqDescPtr sdp, Pointer userdata)
2605 {
2606   CheckDescPtr p;
2607   
2608   if (sdp == NULL || userdata == NULL) return;
2609   p = (CheckDescPtr) userdata;
2610   if (p->found) return;
2611   if (sdp->choice == p->segregate_type) p->found = TRUE;
2612 }
2613 
2614 static Boolean LIBCALLBACK DoesNucProtSetContainDescriptorType (BioseqSetPtr bssp, Pointer userdata)
2615 {
2616   CheckDescData d;
2617   SegregateFeatPtr  sfp;
2618   
2619   sfp = (SegregateFeatPtr) userdata;
2620   if (sfp == NULL || bssp == NULL) return FALSE;
2621 
2622   d.found = FALSE;
2623   d.segregate_type = sfp->segregate_type;
2624   VisitDescriptorsInSet (bssp, &d, DoesSetContainDescriptorType_Callback);
2625   return d.found;       
2626 }
2627 
2628 /*=========================================================================*/
2629 /*                                                                         */
2630 /* SegregateItemsByFeature () - Given a feature type, move bioseqs         */
2631 /*                        containing those features to a new popset.       */
2632 /*                                                                         */
2633 /*=========================================================================*/
2634 
2635 static void SegregateItemsByFeatureOrDescriptor 
2636 (SeqEntryPtr      seqlist,
2637  SegregateFeatPtr sfp,
2638  BioseqSetPtr     set1,
2639  BioseqSetPtr     set2)
2640 {
2641   
2642 
2643   if (sfp == NULL || set1 == NULL || set2 == NULL || seqlist == NULL)
2644     return;
2645   
2646   if (sfp->is_feat)
2647   {
2648         SegregateItemsRecursor (seqlist, set1, set2, 
2649                                        DoesNucProtSetContainFeatureType,
2650                                        DoesSequenceContainFeatureType,
2651                                        (Pointer) sfp);
2652   } 
2653   else 
2654   {
2655         SegregateItemsRecursor (seqlist, set1, set2, 
2656                                        DoesNucProtSetContainDescriptorType,
2657                                        DoesSequenceContainDescriptorType,
2658                                        (Pointer) sfp);
2659   }
2660   
2661 }
2662 
2663 
2664 /*=========================================================================*/
2665 /*                                                                         */
2666 /* SegregateByFeatureOrDescriptor_Callback () - Segregates sequences that  */
2667 /*                            contain a selected feature.                  */
2668 /*                                                                         */
2669 /*=========================================================================*/
2670 
2671 static void SegregateByFeatureOrDescriptor_Callback (ButtoN b)
2672 {
2673   SegregateFeatPtr  sfp;
2674   SeqEntryPtr       sep;
2675   UIEnum            val;
2676   BioseqSetPtr      bssp;
2677   SeqEntryPtr       seqlist;
2678   BioseqSetPtr      newset1, newset2;
2679   ObjMgrDataPtr     omdptop;
2680   ObjMgrData        omdata;
2681   Uint2             parenttype;
2682   Pointer           parentptr;
2683   ValNodePtr        vnp;
2684 
2685   /* Check the initial conditions and get the sequence */
2686   sfp = (SegregateFeatPtr) GetObjectExtra (b);
2687   if (sfp == NULL || sfp->input_entityID == 0 || sfp->target_set == NULL) {
2688     Remove (sfp->form);
2689     return;
2690   }
2691 
2692   sep = GetTopSeqEntryForEntityID (sfp->input_entityID); 
2693   if (sep == NULL) {
2694     Remove (sfp->form);
2695     return;
2696   }
2697 
2698   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
2699   GetSeqEntryParent (sep, &parentptr, &parenttype);
2700 
2701   bssp = sfp->target_set;
2702   seqlist = bssp->seq_set;
2703   bssp->seq_set = NULL;
2704 
2705   CreateSetsForSegregate (bssp, &newset1, &newset2);
2706 
2707   /* Get the feature to look for */
2708   val = GetValue (sfp->type_popup);
2709   for (vnp = sfp->type_list; vnp != NULL && val > 1; vnp = vnp->next, val--)
2710   {     
2711   }
2712   if (vnp == NULL || val != 1)
2713   {
2714     Remove (sfp->form);
2715     return;
2716   }
2717   sfp->segregate_type = vnp->choice;
2718   
2719   /* Display the 'working' cursor */
2720 
2721   WatchCursor ();
2722   Update ();
2723 
2724   /* Do the search and move sequences */
2725   SegregateItemsByFeatureOrDescriptor (seqlist, sfp, newset1, newset2);
2726 
2727   /* Remove the window and update things */
2728   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
2729   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata); 
2730   ObjMgrSetDirtyFlag (sfp->input_entityID, TRUE);
2731   ObjMgrSendMsg (OM_MSG_UPDATE, sfp->input_entityID, 0, 0);
2732 
2733   ArrowCursor ();
2734   Update ();
2735   Remove (sfp->form);
2736 
2737   /* Return successfully */
2738   return;
2739 }
2740 
2741 
2742 /*=========================================================================*/
2743 /*                                                                         */
2744 /* CreateSegregateByFeatureWindow () - Creates and then displays the window*/
2745 /*                        for getting segregate by text info from the user.*/
2746 /*                                                                         */
2747 /*=========================================================================*/
2748 
2749 static Int2 LIBCALLBACK CreateSegregateByFeatureOrDescriptorWindow (Pointer data, Boolean is_feat)
2750 {
2751   GrouP              c;
2752   SegregateFeatPtr   sfp;
2753   GrouP              g;
2754   GrouP              h;
2755   OMProcControlPtr   ompcp;
2756   StdEditorProcsPtr  sepp;
2757   WindoW             w;
2758   ValNodePtr         vnp;
2759 
2760   /* Check parameters and get a pointer to the current data */
2761 
2762   ompcp = (OMProcControlPtr) data;
2763   if (!OkToSegregate(ompcp)) {
2764     return OM_MSG_RET_ERROR;
2765   }
2766 
2767   /* Create a new window, and a struct */
2768   /* to pass around the data in.       */
2769 
2770   sfp = (SegregateFeatPtr) MemNew (sizeof (SegregateFeatData));
2771   if (sfp == NULL)
2772     return OM_MSG_RET_ERROR;
2773   sfp->is_feat = is_feat;
2774 
2775   if (sfp->is_feat)
2776   {
2777     w = FixedWindow (-50, -33, -10, -10, "Segregate By Feature",
2778                          StdCloseWindowProc);
2779   }
2780   else
2781   {
2782     w = FixedWindow (-50, -33, -10, -10, "Segregate By Descriptor",
2783                          StdCloseWindowProc);
2784   }
2785                    
2786   SetObjectExtra (w, sfp, StdCleanupFormProc);
2787   sfp->form = (ForM) w;
2788 
2789   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2790   if (sepp != NULL) {
2791     SetActivate (w, sepp->activateForm);
2792     sfp->appmessage = sepp->handleMessages;
2793   }
2794 
2795   sfp->input_entityID = ompcp->input_entityID;
2796   sfp->input_itemID = ompcp->input_itemID;
2797   sfp->input_itemtype = ompcp->input_itemtype;
2798   sfp->target_set = (BioseqSetPtr)ompcp->input_data;
2799 
2800   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
2801   if (sepp != NULL) {
2802     SetActivate (w, sepp->activateForm);
2803     sfp->appmessage = sepp->handleMessages;
2804   }
2805 
2806   /* Add the popup lists */
2807 
2808   h = HiddenGroup (w, -1, 0, NULL);
2809   SetGroupSpacing (h, 10, 10);
2810 
2811   g = HiddenGroup (h, 3, 0, NULL);
2812 
2813   if (sfp->is_feat)
2814   {
2815     StaticPrompt (g, "Segregate sequences with the feature", 0, dialogTextHeight,
2816                       programFont, 'l');
2817     sfp->type_list = BuildFeatureValNodeList (TRUE, NULL, 0, TRUE, FALSE);
2818   }
2819   else
2820   {
2821     StaticPrompt (g, "Segregate sequences with the descriptor", 0, dialogTextHeight,
2822                       programFont, 'l');
2823         sfp->type_list = BuildDescriptorValNodeList ();
2824   }
2825 
2826   sfp->type_popup = PopupList (g, TRUE, NULL);
2827   SetObjectExtra (sfp->type_popup, sfp, NULL);
2828   for (vnp = sfp->type_list; vnp != NULL; vnp = vnp->next)
2829   {
2830     PopupItem (sfp->type_popup, (CharPtr) vnp->data.ptrvalue);
2831   }
2832   SetValue (sfp->type_popup, 1);
2833 
2834   /* Add Accept and Cancel buttons */
2835 
2836   c = HiddenGroup (h, 4, 0, NULL);
2837   sfp->accept = DefaultButton (c, "Accept", SegregateByFeatureOrDescriptor_Callback);
2838   SetObjectExtra (sfp->accept, sfp, NULL);
2839   PushButton (c, "Cancel", StdCancelButtonProc);
2840 
2841   /* Line things up nicely */
2842 
2843   AlignObjects (ALIGN_LEFT, (HANDLE) g, (HANDLE) c, (HANDLE) h, NULL);
2844 
2845   /* Display the window now */
2846 
2847   RealizeWindow (w);
2848   Show (w);
2849   Select (w);
2850   Select (sfp->accept);
2851   Update ();
2852   return OM_MSG_RET_OK;
2853 }
2854 
2855 extern Int2 LIBCALLBACK CreateSegregateByFeatureWindow (Pointer data)
2856 {
2857   return CreateSegregateByFeatureOrDescriptorWindow (data, TRUE);
2858 }
2859 
2860 extern Int2 LIBCALLBACK CreateSegregateByDescriptorWindow (Pointer data)
2861 {
2862   return CreateSegregateByFeatureOrDescriptorWindow (data, FALSE);
2863 }
2864 
2865 typedef struct segregatemoltypedata
2866 {
2867   FEATURE_FORM_BLOCK
2868 
2869   PopuP        type_popup;
2870   ButtoN       use_mol_type;
2871   PopuP        class_popup;
2872   ButtoN       use_mol_class;
2873   ButtoN       accept;
2874   Uint1        moltype;
2875   Uint1        molclass;
2876   BioseqSetPtr target_set;
2877 } SegregateMolTypeData, PNTR SegregateMolTypePtr;
2878 
2879 static ENUM_ALIST(molinfo_biomol_alist)
2880   {"Genomic DNA or RNA",     1},
2881   {"Precursor RNA",          2},
2882   {"mRNA [cDNA]",            3},
2883   {"Ribosomal RNA",          4},
2884   {"Transfer RNA",           5},
2885   {"Peptide",                8},
2886   {"Other-Genetic",          9},
2887   {"Genomic-mRNA",          10},
2888   {"cRNA",                  11},
2889   {"Transcribed RNA",       13},
2890   {"Other",                255},
2891 END_ENUM_ALIST
2892 
2893 static ENUM_ALIST(mol_class_alist)
2894 {"DNA",             Seq_mol_dna},
2895 {"RNA",             Seq_mol_rna},
2896 {"Protein",         Seq_mol_aa},
2897 {"Nucleotide",      Seq_mol_na},
2898 {"Other",           Seq_mol_other},
2899 END_ENUM_ALIST
2900 
2901 static Boolean LIBCALLBACK DoesSequenceHaveMoleculeType (BioseqPtr bsp, Pointer userdata)
2902 {
2903   SegregateMolTypePtr  smp;
2904   ValNodePtr           sdp;
2905   MolInfoPtr           mip;
2906   
2907   smp = (SegregateMolTypePtr) userdata; 
2908   if (bsp == NULL || smp == NULL) return FALSE;
2909   
2910   if (GetStatus (smp->use_mol_class) && bsp->mol != smp->molclass)
2911   {
2912     return FALSE;
2913   }
2914 
2915   if (GetStatus (smp->use_mol_type))
2916   {
2917     sdp = bsp->descr;
2918     while (sdp != NULL)
2919     {
2920       if (sdp->choice == Seq_descr_molinfo && sdp->data.ptrvalue != NULL) 
2921       {
2922         mip = (MolInfoPtr) sdp->data.ptrvalue;
2923         if (mip->biomol == smp->moltype)
2924         {
2925           return TRUE;
2926         }
2927       }
2928       sdp = sdp->next;
2929     }
2930     return FALSE;
2931   }
2932   return TRUE;
2933 }
2934 
2935 typedef struct lookformoltype
2936 {
2937   Boolean found;
2938   Uint1   moltype;  
2939   Uint1   molclass;
2940 } LookForMolTypeData, PNTR LookForMolTypePtr;
2941 
2942 static void DoesNucProtSetHaveMoleculeTypeCallback (SeqDescPtr sdp, Pointer userdata)
2943 {
2944   LookForMolTypePtr l;
2945   MolInfoPtr           mip;
2946   
2947   if (sdp == NULL || userdata == NULL) return;
2948   l = (LookForMolTypePtr) userdata;
2949   
2950   if (sdp->choice == Seq_descr_molinfo && sdp->data.ptrvalue != NULL)
2951   {
2952         mip = (MolInfoPtr) sdp->data.ptrvalue;
2953         if (mip->biomol == l->moltype)
2954         {
2955           l->found = TRUE;
2956         }
2957   }
2958 }
2959 
2960 typedef struct lookformolclass
2961 {
2962   Boolean found;
2963   Uint1   molclass;
2964 } LookForMolClassData, PNTR LookForMolClassPtr;
2965 
2966 static void FindMolClassCallback (BioseqPtr bsp, Pointer userdata)
2967 {
2968   LookForMolClassPtr lcp;
2969   
2970   if (bsp == NULL || userdata == NULL) return;
2971   lcp = (LookForMolClassPtr) userdata;
2972   
2973   if (bsp->mol == lcp->molclass)
2974   {
2975     lcp->found = TRUE;
2976   }
2977 }
2978 
2979 static Boolean LIBCALLBACK DoesNucProtSetHaveMoleculeType (BioseqSetPtr bssp, Pointer userdata)
2980 {
2981   LookForMolTypeData   lm;
2982   LookForMolClassData  lc;
2983   SegregateMolTypePtr  smp;
2984 
2985   if (bssp == NULL || userdata == NULL) return FALSE;
2986   smp = (SegregateMolTypePtr) userdata;
2987   
2988   if (GetStatus (smp->use_mol_class))
2989   {
2990     lc.found = FALSE;
2991     lc.molclass = smp->molclass;
2992     VisitBioseqsInSet (bssp, &lc, FindMolClassCallback);
2993     if (!lc.found) return FALSE;
2994   }
2995   
2996   if (GetStatus (smp->use_mol_type))
2997   {
2998     lm.moltype = smp->moltype;
2999     lm.found = FALSE;
3000     VisitDescriptorsInSet (bssp, &lm, DoesNucProtSetHaveMoleculeTypeCallback);
3001     if (!lm.found) return FALSE;
3002   }
3003   return TRUE;
3004 }
3005 
3006 static void LIBCALLBACK SegregateByMoleculeType 
3007 (SeqEntryPtr  seqlist,
3008  Pointer      userdata,
3009  BioseqSetPtr set1,
3010  BioseqSetPtr set2)
3011 {
3012   SegregateItemsRecursor (seqlist, set1, set2, 
3013                           DoesNucProtSetHaveMoleculeType,
3014                           DoesSequenceHaveMoleculeType, userdata);
3015 }
3016 
3017 
3018 /*=========================================================================*/
3019 /*                                                                         */
3020 /* SegregateByMoleculeType_Callback () - Segregates sequences that  */
3021 /*                            have a selected molecule type.                  */
3022 /*                                                                         */
3023 /*=========================================================================*/
3024 
3025 static void SegregateByMoleculeType_Callback (ButtoN b)
3026 {
3027   SegregateMolTypePtr  smp;
3028   SeqEntryPtr          sep;
3029   UIEnum               val;
3030 
3031   /* Check the initial conditions and get the sequence */
3032   smp = (SegregateMolTypePtr) GetObjectExtra (b);
3033   if (smp == NULL || smp->input_entityID == 0 || smp->target_set == NULL) {
3034     Remove (smp->form);
3035     return;
3036   }
3037 
3038   sep = GetTopSeqEntryForEntityID (smp->input_entityID); 
3039   if (sep == NULL) {
3040     Remove (smp->form);
3041     return;
3042   }
3043   
3044   if (!GetEnumPopup (smp->type_popup, molinfo_biomol_alist, &val)) 
3045   {
3046     return;
3047   }
3048   smp->moltype = val;
3049   if (!GetEnumPopup (smp->class_popup, mol_class_alist, &val)) 
3050   {
3051     return;
3052   }
3053   smp->molclass = val;
3054 
3055   SegregateItemsGenericCallback (sep, smp->target_set, smp->input_entityID,
3056                                  (Pointer) smp, SegregateByMoleculeType);
3057 
3058   Remove (smp->form);
3059 
3060   /* Return successfully */
3061   return;
3062 }
3063 
3064 static void EnableMolInfoPopups (ButtoN b)
3065 {
3066   SegregateMolTypePtr smp;
3067   Boolean             ok_to_accept = FALSE;
3068   
3069   smp = (SegregateMolTypePtr) GetObjectExtra (b);
3070   if (smp == NULL) return;
3071   
3072   if (GetStatus (smp->use_mol_type))
3073   {
3074     Enable (smp->type_popup);
3075     ok_to_accept = TRUE;
3076   }
3077   else
3078   {
3079     Disable (smp->type_popup);
3080   }
3081   if (GetStatus (smp->use_mol_class))
3082   {
3083     Enable (smp->class_popup);
3084     ok_to_accept = TRUE;
3085   }
3086   else
3087   {
3088     Disable (smp->class_popup);
3089   }  
3090   if (ok_to_accept)
3091   {
3092     Enable (smp->accept);
3093   }
3094   else
3095   {
3096     Disable (smp->accept);
3097   }
3098 }
3099 
3100 /*=========================================================================*/
3101 /*                                                                         */
3102 /* CreateSegregateByFeatureWindow () - Creates and then displays the window*/
3103 /*                        for getting segregate by text info from the user.*/
3104 /*                                                                         */
3105 /*=========================================================================*/
3106 
3107 extern Int2 LIBCALLBACK CreateSegregateByMoleculeTypeWindow (Pointer data)
3108 {
3109   GrouP               c;
3110   SegregateMolTypePtr smp;
3111   GrouP               g, k;
3112   GrouP               h;
3113   OMProcControlPtr    ompcp;
3114   StdEditorProcsPtr   sepp;
3115   WindoW              w;
3116 
3117   /* Check parameters and get a pointer to the current data */
3118 
3119   ompcp = (OMProcControlPtr) data;
3120   if (!OkToSegregate(ompcp)) {
3121     return OM_MSG_RET_ERROR;
3122   }
3123 
3124   /* Create a new window, and a struct */
3125   /* to pass around the data in.       */
3126 
3127   smp = (SegregateMolTypePtr) MemNew (sizeof (SegregateMolTypeData));
3128   if (smp == NULL)
3129     return OM_MSG_RET_ERROR;
3130   
3131   w = FixedWindow (-50, -33, -10, -10, "Segregate By Molecule Type",
3132                        StdCloseWindowProc);
3133                    
3134   SetObjectExtra (w, smp, StdCleanupFormProc);
3135   smp->form = (ForM) w;
3136 
3137   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3138   if (sepp != NULL) {
3139     SetActivate (w, sepp->activateForm);
3140     smp->appmessage = sepp->handleMessages;
3141   }
3142 
3143   smp->input_entityID = ompcp->input_entityID;
3144   smp->input_itemID = ompcp->input_itemID;
3145   smp->input_itemtype = ompcp->input_itemtype;
3146   smp->target_set = (BioseqSetPtr)ompcp->input_data;
3147 
3148   /* Add the popup lists */
3149 
3150   h = HiddenGroup (w, -1, 0, NULL);
3151   SetGroupSpacing (h, 10, 10);
3152 
3153   g = HiddenGroup (h, 1, 0, NULL);
3154 
3155   StaticPrompt (g, "Segregate sequences with:", 0, dialogTextHeight,
3156                       programFont, 'l');
3157         k = HiddenGroup (g, 2, 0, NULL);
3158         smp->use_mol_type = CheckBox (k, "Molecule Type", EnableMolInfoPopups);
3159   SetObjectExtra (smp->use_mol_type, smp, NULL);
3160   smp->type_popup = PopupList (k, TRUE, NULL);
3161   InitEnumPopup (smp->type_popup, molinfo_biomol_alist, NULL);
3162   SetValue (smp->type_popup, 1);
3163   SetStatus (smp->use_mol_type, FALSE);
3164   Disable (smp->type_popup);
3165         k = HiddenGroup (g, 2, 0, NULL);
3166   smp->use_mol_class = CheckBox (k, "Molecule Class", EnableMolInfoPopups);
3167   SetObjectExtra (smp->use_mol_class, smp, NULL);
3168   smp->class_popup = PopupList (k, TRUE, NULL);
3169   InitEnumPopup (smp->class_popup, mol_class_alist, NULL);
3170   SetValue (smp->class_popup, 1);
3171   SetStatus (smp->use_mol_class, FALSE);
3172   Disable (smp->class_popup);
3173 
3174   /* Add Accept and Cancel buttons */
3175 
3176   c = HiddenGroup (h, 4, 0, NULL);
3177   smp->accept = DefaultButton (c, "Accept", SegregateByMoleculeType_Callback);
3178   SetObjectExtra (smp->accept, smp, NULL);
3179   Disable (smp->accept);
3180   PushButton (c, "Cancel", StdCancelButtonProc);
3181 
3182   /* Line things up nicely */
3183 
3184   AlignObjects (ALIGN_LEFT, (HANDLE) g, (HANDLE) c, (HANDLE) h, NULL);
3185 
3186   /* Display the window now */
3187 
3188   RealizeWindow (w);
3189   Show (w);
3190   Select (w);
3191   Select (smp->accept);
3192   Update ();
3193   return OM_MSG_RET_OK;
3194 }
3195 
3196 static Boolean LIBCALLBACK DoesSequenceHaveID (BioseqPtr bsp, Pointer userdata)
3197 {
3198   ConvertFormPtr cfp;
3199   Boolean      found = FALSE;
3200   ValNodePtr     vnp;
3201 
3202   cfp = (ConvertFormPtr) userdata;
3203   if (bsp == NULL || cfp == NULL) return FALSE;
3204 
3205   for (vnp = cfp->id_list; vnp != NULL && !found; vnp = vnp->next) {
3206     if (SeqIdIn (vnp->data.ptrvalue, bsp->id)) {
3207       found = TRUE;
3208     }
3209   }
3210   return found;
3211 }
3212 
3213 static Boolean LIBCALLBACK  DoesNucProtSetContainID (BioseqSetPtr bssp, Pointer userdata)
3214 {
3215   SeqEntryPtr sep;
3216   BioseqPtr   bsp;
3217   ConvertFormPtr cfp;
3218 
3219   if (bssp == NULL) return FALSE;
3220   cfp = (ConvertFormPtr) userdata;
3221   if (cfp == NULL) return FALSE;
3222 
3223   for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
3224     if (IS_Bioseq (sep)) {
3225       bsp = (BioseqPtr) sep->data.ptrvalue;
3226       if (DoesSequenceHaveID (bsp, (Pointer)cfp)) {
3227         return TRUE;
3228       }
3229     }
3230   }
3231   return FALSE;
3232 }
3233 
3234 static void SegregateItemsById 
3235 (SeqEntryPtr                     seqlist,
3236  ConvertFormPtr                  cfp,
3237  BioseqSetPtr                    set1,
3238  BioseqSetPtr                    set2)
3239 {
3240   SegregateItemsRecursor (seqlist, set1, set2, 
3241                   DoesNucProtSetContainID,
3242                   DoesSequenceHaveID, (Pointer)cfp);
3243 }
3244 
3245 static void SetSegregateByIDAcceptButton (Pointer data)
3246 
3247 {
3248   ConvertFormPtr  cfp;
3249   CharPtr         id_str;
3250 
3251   cfp = (ConvertFormPtr) data;
3252   if (cfp == NULL)
3253     return;
3254 
3255   id_str = SaveStringFromText (cfp->deleteText);
3256   if (StringHasNoText (id_str)) {
3257     SafeDisable (cfp->accept);
3258   } else {
3259     SafeEnable (cfp->accept);
3260   }
3261 }
3262 
3263 /*=========================================================================*/
3264 /*                                                                         */
3265 /* SegregateByID_Callback () - Finds and deletes all items of a selected */
3266 /*                            type that contain a given text phrase.       */
3267 /*                                                                         */
3268 /*=========================================================================*/
3269 
3270 static void SegregateById_Callback (ButtoN b)
3271 {
3272   ConvertFormPtr    cfp;
3273   SeqEntryPtr       sep;
3274   BioseqSetPtr      bssp;
3275   SeqEntryPtr       seqlist;
3276   BioseqSetPtr      newset1, newset2;
3277   ObjMgrDataPtr     omdptop;
3278   ObjMgrData        omdata;
3279   Uint2             parenttype;
3280   Pointer           parentptr;
3281   Boolean           leaveDlgUp = FALSE;
3282   CharPtr           id_str;
3283 
3284   /* Check the initial conditions and get the sequence */
3285   cfp = (ConvertFormPtr) GetObjectExtra (b);
3286   if (cfp == NULL || cfp->input_entityID == 0 || cfp->target_set == NULL) {
3287     Remove (cfp->form);
3288     return;
3289   }
3290 
3291   sep = GetTopSeqEntryForEntityID (cfp->input_entityID); 
3292   if (sep == NULL) {
3293     Remove (cfp->form);
3294     return;
3295   }
3296   
3297   if (GetStatus (cfp->leaveDlgUp))
3298   {
3299         leaveDlgUp = TRUE;
3300   }
3301 
3302   /* Get the string to search for */
3303   id_str = SaveStringFromText(cfp->deleteText);
3304   if (StringHasNoText (id_str)){ 
3305     if (!leaveDlgUp)
3306     {
3307       Remove (cfp->form);
3308     }
3309     id_str = MemFree (id_str);
3310     return;
3311   }
3312   
3313   cfp->id_list = ParseAccessionNumberListFromString (id_str, SeqMgrGetSeqEntryForData (cfp->target_set));
3314   id_str = MemFree (id_str);
3315   if (cfp->id_list == NULL) {
3316     Message (MSG_ERROR, "No IDs specified!");
3317     return;
3318   } 
3319 
3320   SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
3321   GetSeqEntryParent (sep, &parentptr, &parenttype);
3322 
3323   bssp = cfp->target_set;
3324   seqlist = bssp->seq_set;
3325   bssp->seq_set = NULL;
3326 
3327   CreateSetsForSegregate (bssp, &newset1, &newset2);
3328 
3329   /* Display the 'working' cursor */
3330 
3331   WatchCursor ();
3332   Update ();
3333 
3334   /* Do the search and move sequences */
3335   SegregateItemsById (seqlist, cfp, newset1, newset2);
3336 
3337   cfp->id_list = FreeSeqIdList (cfp->id_list);
3338   /* Remove the window and update things */
3339   SeqMgrLinkSeqEntry (sep, parenttype, parentptr);
3340   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata); 
3341   ObjMgrSetDirtyFlag (cfp->input_entityID, TRUE);
3342   ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID, 0, 0);
3343 
3344   ArrowCursor ();
3345   Update ();
3346   if (!leaveDlgUp)
3347   {
3348     Remove (cfp->form);
3349   }
3350 
3351   /* Return successfully */
3352   return;
3353 }
3354 
3355 /*=========================================================================*/
3356 /*                                                                         */
3357 /* CreateSegregateByIdWindow () - Creates and then displays the window   */
3358 /*                        for getting segregate by ID info from the user.*/
3359 /*                                                                         */
3360 /*=========================================================================*/
3361 
3362 extern Int2 LIBCALLBACK CreateSegregateByIdWindow (Pointer data)
3363 {
3364   GrouP              c;
3365   ConvertFormPtr     cfp;
3366   GrouP              g;
3367   GrouP              h;
3368   OMProcControlPtr   ompcp;
3369   StdEditorProcsPtr  sepp;
3370   WindoW             w;
3371 
3372   /* Check parameters and get a pointer to the current data */
3373 
3374   ompcp = (OMProcControlPtr) data;
3375   if (!OkToSegregate(ompcp)) {
3376     return OM_MSG_RET_ERROR;
3377   }
3378 
3379   /* Create a new window, and a struct */
3380   /* to pass around the data in.       */
3381 
3382   cfp = ConvertFormNew ();
3383   if (cfp == NULL)
3384     return OM_MSG_RET_ERROR;
3385   cfp->target_set = (BioseqSetPtr)ompcp->input_data;
3386   cfp->set_accept_proc = SetSegregateByIDAcceptButton;
3387 
3388   w = FixedWindow (-50, -33, -10, -10, "Segregate By ID",
3389                    StdCloseWindowProc);
3390   SetObjectExtra (w, cfp, CleanupSegregatePage);
3391   cfp->form = (ForM) w;
3392 
3393   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3394   if (sepp != NULL) {
3395     SetActivate (w, sepp->activateForm);
3396     cfp->appmessage = sepp->handleMessages;
3397   }
3398 
3399   cfp->input_entityID = ompcp->input_entityID;
3400   cfp->input_itemID = ompcp->input_itemID;
3401   cfp->input_itemtype = ompcp->input_itemtype;
3402 
3403   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3404   if (sepp != NULL) {
3405     SetActivate (w, sepp->activateForm);
3406     cfp->appmessage = sepp->handleMessages;
3407   }
3408 
3409   /* Add the popup lists */
3410 
3411   h = HiddenGroup (w, -1, 0, NULL);
3412   SetGroupSpacing (h, 10, 10);
3413 
3414   g = HiddenGroup (h, 3, 0, NULL);
3415 
3416   StaticPrompt (g, "Segregate sequences with the following IDs", 0, dialogTextHeight,
3417                 programFont, 'l');
3418   cfp->deleteText = DialogText (g, "", 10, ConvertFormTextCallback);
3419   SetObjectExtra (cfp->deleteText, cfp, NULL);
3420 
3421   /* Add Accept and Cancel buttons */
3422 
3423   c = HiddenGroup (h, 4, 0, NULL);
3424   cfp->accept = DefaultButton (c, "Accept", SegregateById_Callback);
3425   SetObjectExtra (cfp->accept, cfp, NULL);
3426   Disable (cfp->accept);
3427   PushButton (c, "Cancel", StdCancelButtonProc);
3428   cfp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
3429 
3430   /* Line things up nicely */
3431 
3432   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
3433 
3434   /* Display the window now */
3435 
3436   RealizeWindow (w);
3437   Show (w);
3438   Select (w);
3439   Select (cfp->accept);
3440   Update ();
3441   return OM_MSG_RET_OK;
3442 }
3443 
3444 
3445 static void SearchAndExciseTextInside (CharPtr PNTR strptr, ConvertFormPtr cfp)
3446 
3447 {
3448   CharPtr  lft = NULL;
3449   CharPtr  rgt = NULL;
3450   CharPtr  string;
3451   CharPtr  next_delete = NULL;
3452   Int4     strLen;
3453 
3454   if (strptr == NULL || cfp == NULL || cfp->textportion == NULL) return;
3455   string = *strptr;
3456   if (string == NULL) return;
3457 
3458   FindTextPortionXInString (string, cfp->textportion, &lft, &strLen);
3459   if (lft == NULL) return;
3460   rgt = lft + strLen;
3461   next_delete = lft;
3462   if (lft < rgt) {  /* No text to delete */
3463     while (*rgt != 0) {
3464       *lft = *rgt;
3465       lft++;
3466       rgt++;
3467     }
3468     *lft = '\0';
3469   }
3470   if (cfp->repeat_remove && next_delete != NULL && *next_delete != 0) {
3471     SearchAndExciseTextInside (&next_delete, cfp);
3472   }
3473 }
3474 
3475 
3476 /*---------------------------------------------------------------------*/
3477 /*                                                                     */
3478 /* RemOutTxt_SearchAndExcise () -- Removes all text from a string that */
3479 /*                                 does not match a specified substring*/
3480 /*                                                                     */
3481 /*---------------------------------------------------------------------*/
3482 
3483 static void SearchAndExciseTextOutside (CharPtr sourceStr, ConvertFormPtr cfp)
3484 {
3485   CharPtr  leftEnd = NULL;
3486   CharPtr  rightEnd = NULL;
3487   Int4     strLen;
3488   Int4     i;
3489 
3490   /* Check parameters */
3491 
3492   if (cfp == NULL || cfp->textportion == NULL || sourceStr == NULL)
3493   {
3494     return;
3495   }
3496 
3497   FindTextPortionXInString (sourceStr, cfp->textportion, &leftEnd, &strLen);
3498 
3499   if (leftEnd != NULL) 
3500   {
3501     rightEnd = leftEnd + strLen;
3502   }
3503 
3504   if (NULL == leftEnd)  /* String not found */
3505   {
3506     if (DO_NOTHING == cfp->ifNotFound)
3507     {
3508         return;
3509     }
3510     else
3511     {
3512       sourceStr [0] = '\0';
3513       return;
3514     }
3515   }
3516   else
3517   {
3518     /* End the original string at rightEnd and  */
3519     /* then move everything starting at leftEnd */
3520     /* to the beginning of the original.        */
3521 
3522     rightEnd[0] = '\0';
3523     if (leftEnd == sourceStr)
3524       return;
3525 
3526     strLen = StringLen (leftEnd);
3527 
3528     for (i = 0; i <= strLen; i++)
3529       sourceStr[i] = leftEnd[i];
3530 
3531     sourceStr[i] = '\0';
3532   }
3533 }
3534 
3535 
3536 static void SearchAndExciseText (CharPtr str, ConvertFormPtr cfp)
3537 {
3538   if (str == NULL || cfp == NULL) return;
3539   if (cfp->remove_inside) 
3540   {
3541     SearchAndExciseTextInside (&str, cfp);
3542   } 
3543   else
3544   {
3545     SearchAndExciseTextOutside (str, cfp);
3546   }
3547 }
3548 
3549 
3550 static void RemoveAFeatureText (SeqFeatPtr sfp, Pointer mydata)
3551 {
3552   ConvertFormPtr  cfp;
3553   GBQualPtr       gbqp;
3554   GeneRefPtr      grp;
3555   ProtRefPtr      prp;
3556   RnaRefPtr       rrp;
3557   CharPtr         str;
3558   ValNodePtr      vnp;
3559 
3560   if (sfp == NULL) return;
3561   cfp = (ConvertFormPtr) mydata;
3562   if (cfp == NULL) return;
3563 
3564   if (sfp->data.choice == SEQFEAT_GENE && cfp->type == eFieldTypeGene) {
3565     grp = (GeneRefPtr) sfp->data.value.ptrvalue;
3566     if (grp != NULL) {
3567       switch (cfp->subtype) {
3568         case 1 :
3569           SearchAndExciseText (grp->locus, cfp);
3570           break;
3571         case 2 :
3572           SearchAndExciseText (grp->desc, cfp);
3573           break;
3574         case 3 :
3575           SearchAndExciseText (grp->allele, cfp);
3576           break;
3577         case 4 :
3578           SearchAndExciseText (grp->maploc, cfp);
3579           break;
3580         case 5 :
3581           SearchAndExciseText (grp->locus_tag, cfp);
3582           break;
3583         case 6 :
3584           for (vnp = grp->syn; vnp != NULL; vnp = vnp->next) {
3585             str = (CharPtr) vnp->data.ptrvalue;
3586             SearchAndExciseText (str, cfp);
3587           }
3588           break;
3589         case 7 :
3590           SearchAndExciseText (sfp->comment, cfp);
3591           break;
3592         default :
3593           break;
3594       }
3595     }
3596   } else if (sfp->data.choice == SEQFEAT_CDREGION && cfp->type == eFieldTypeCDS) {
3597     switch (cfp->subtype) {
3598       case CDS_COMMENT :
3599         SearchAndExciseText (sfp->comment, cfp);
3600         break;
3601       case CDS_GENE_XREF :
3602         break;
3603       default :
3604         break;
3605     }
3606   } else if (sfp->data.choice == SEQFEAT_PROT && cfp->type == eFieldTypeProtein) {
3607     prp = (ProtRefPtr) sfp->data.value.ptrvalue;
3608     if (prp != NULL) {
3609       switch (cfp->subtype) {
3610         case 1 :
3611           for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
3612             str = (CharPtr) vnp->data.ptrvalue;
3613             SearchAndExciseText (str, cfp);
3614           }
3615           break;
3616         case 2 :
3617           SearchAndExciseText (prp->desc, cfp);
3618           break;
3619         case 3 :
3620           for (vnp = prp->ec; vnp != NULL; vnp = vnp->next) {
3621             str = (CharPtr) vnp->data.ptrvalue;
3622             SearchAndExciseText (str, cfp);
3623           }
3624           break;
3625         case 4 :
3626           for (vnp = prp->activity; vnp != NULL; vnp = vnp->next) {
3627             str = (CharPtr) vnp->data.ptrvalue;
3628             SearchAndExciseText (str, cfp);
3629           }
3630           break;
3631         case 5 :
3632           SearchAndExciseText (sfp->comment, cfp);
3633           break;
3634         default :
3635           break;
3636       }
3637     }
3638   } else if (sfp->data.choice == SEQFEAT_RNA && cfp->type == eFieldTypeRNA) {
3639     rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
3640     if (rrp != NULL) {
3641       switch (cfp->subtype) {
3642         case 1 :
3643           if (rrp->ext.choice == 0 || rrp->ext.choice == 1) {
3644             rrp->ext.choice = 1;
3645             str = (CharPtr) rrp->ext.value.ptrvalue;
3646             SearchAndExciseText (str, cfp);
3647           }
3648           break;
3649         case 2 :
3650           SearchAndExciseText (sfp->comment, cfp);
3651           break;
3652         case 3 :
3653         default :
3654           break;
3655       }
3656     }
3657   } else if (sfp->data.choice == SEQFEAT_IMP && cfp->type == eFieldTypeImport) {
3658     switch (cfp->subtype) {
3659       case IMPORT_GBQUAL_FIELD :
3660         gbqp = sfp->qual;
3661         while (NULL != gbqp)
3662         {
3663           if (NULL != gbqp->val)
3664             SearchAndExciseText (gbqp->val, cfp);
3665           gbqp = gbqp->next;
3666         }
3667         break;
3668       case IMPORT_COMMENT_FIELD :
3669         SearchAndExciseText (sfp->comment, cfp);
3670         break;
3671       default :
3672         break;
3673     }
3674         }
3675 }
3676 
3677 
3678 static void RemoveOrgModText (BioSourcePtr biop, ConvertFormPtr cfp)
3679 {
3680   OrgModPtr mod, prev_mod = NULL, next_mod;
3681 
3682   if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL || cfp == NULL) return;
3683 
3684   mod = biop->org->orgname->mod;
3685   while (mod != NULL) {
3686     next_mod = mod->next;
3687     if (mod->subtype == cfp->subtype) {
3688             SearchAndExciseText (mod->subname, cfp);
3689       if (StringHasNoText (mod->subname) && !IsNonTextModifier (GetOrgModQualName (mod->subtype))) {
3690         if (prev_mod == NULL) {
3691           biop->org->orgname->mod = mod->next;
3692         } else {
3693           prev_mod->next = mod->next;
3694         }
3695         mod->next = NULL;
3696         mod = OrgModFree (mod);
3697       } else {
3698         prev_mod = mod;
3699       }
3700     } else {
3701       prev_mod = mod;
3702     }
3703     mod = mod->next;
3704   }
3705 }
3706 
3707 
3708 static void RemoveSubSourceText (BioSourcePtr biop, ConvertFormPtr cfp)
3709 {
3710   SubSourcePtr ssp, next_ssp, prev_ssp = NULL;
3711 
3712   if (biop == NULL || cfp == NULL) return;
3713 
3714   ssp = biop->subtype;
3715   while (ssp != NULL) {
3716     next_ssp = ssp->next;
3717     if (ssp->subtype == (cfp->subtype - 1000)) {
3718             SearchAndExciseText (ssp->name, cfp);
3719       if (StringHasNoText (ssp->name) && !IsNonTextModifier (GetSubsourceQualName (ssp->subtype))) {
3720         if (prev_ssp == NULL) {
3721           biop->subtype = ssp->next;
3722         } else {
3723           prev_ssp->next = ssp->next;
3724         }
3725         ssp->next = NULL;
3726         ssp = SubSourceFree (ssp);
3727       } else {
3728         prev_ssp = ssp;
3729       }
3730     } else {
3731       prev_ssp = ssp;
3732     }
3733           ssp = next_ssp;
3734   }
3735 }
3736 
3737 static void RemoveASourceText (BioSourcePtr biop, Pointer data)
3738 {
3739   ConvertFormPtr cfp;
3740   OrgRefPtr      orp;
3741   CharPtr        tmp_str;
3742 
3743   cfp = (ConvertFormPtr) data;
3744   if (biop == NULL || cfp == NULL) return;
3745   switch (cfp->type) {
3746     case eFieldTypeBioSource :
3747       orp = biop->org;
3748       if (orp == NULL) return;
3749       switch (cfp->subtype) {
3750         case ORGREF_SCI_NAME_FIELD :
3751           tmp_str = StringSave (orp->taxname);
3752           SearchAndExciseText (tmp_str, cfp);
3753           if (StringCmp (tmp_str, orp->taxname) == 0) {
3754             /* no change, no need to remove taxref */
3755             tmp_str = MemFree (tmp_str);
3756           } else {
3757             SetTaxNameAndRemoveTaxRef (orp, tmp_str);
3758           }
3759           break;
3760         case ORGREF_COMMON_NAME_FIELD :
3761           SearchAndExciseText (orp->common, cfp);
3762           break;
3763         case ORGREF_LINEAGE_FIELD :
3764           if (orp->orgname != NULL) {
3765             SearchAndExciseText (orp->orgname->lineage, cfp);
3766           }
3767           break;
3768         case ORGREF_DIVISION_FIELD :
3769           if (orp->orgname != NULL) {
3770             SearchAndExciseText (orp->orgname->div, cfp);
3771           }
3772           break;
3773         default:
3774           break;
3775       }
3776       break;
3777     case eFieldTypeOrgModSubSource :
3778       if (cfp->subtype < 1000) {  /* Orgmod Note */
3779         RemoveOrgModText (biop, cfp);
3780       } else {  /* subsource note */
3781         RemoveSubSourceText (biop, cfp);
3782       }
3783       break;
3784     default:
3785       break;
3786   }
3787 }
3788 
3789 
3790 static void RemoveDescriptorTextCallback (SeqDescrPtr sdp, Pointer userdata)
3791 {
3792   ConvertFormPtr    cfp;
3793   CharPtr           title;
3794   ObjValNodePtr     ovp;
3795 
3796   cfp = (ConvertFormPtr) userdata;
3797 
3798   if (sdp == NULL || cfp == NULL) return;
3799 
3800   if (cfp->type == eFieldTypeDefline) {
3801     if (sdp->choice != Seq_descr_title) {
3802       return;
3803     }
3804   } else if (cfp->type == eFieldTypeCommentDescriptor) {
3805     if (sdp->choice != Seq_descr_comment) {
3806       return;
3807     }
3808   } else {
3809     return;
3810   }
3811 
3812   title = (CharPtr) sdp->data.ptrvalue;
3813   SearchAndExciseText (title, cfp);
3814   
3815   if (StringHasNoText (title) && (sdp->extended > 0)) {
3816     ovp = (ObjValNodePtr) sdp;
3817     ovp->idx.deleteme = TRUE;
3818     cfp->isDirty = TRUE;
3819   }
3820 }
3821 
3822   
3823 static void DoRemoveText (ConvertFormPtr cfp)
3824 
3825 {
3826   SeqEntryPtr     sep;
3827   FieldSubfieldPtr f;
3828 
3829   /* Get the current sequence and associated data */
3830 
3831   if (cfp == NULL || cfp->input_entityID == 0)
3832     return;
3833 
3834   sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
3835   if (sep == NULL)
3836     return;
3837 
3838   /* Get the feature and subfeature types */
3839   f = DialogToPointer (cfp->target_dlg);
3840   if (f == NULL || f->field < 0 || (f->subfield < 0 && f->subfield_list == NULL)) {
3841     f = FieldSubfieldFree (f);
3842     return;
3843   }
3844 
3845   cfp->type = f->field;
3846   cfp->subtype = f->subfield;
3847 
3848   f = FieldSubfieldFree (f);
3849 
3850   /* Hide the window and set the 'working' cursor */
3851 
3852   Hide (cfp->form);
3853   WatchCursor ();
3854   Update ();
3855 
3856 
3857   /* get information about text to remove */
3858   cfp->textportion = (TextPortionXPtr) DialogToPointer (cfp->textportion_dlg);
3859   
3860   if (GetValue (cfp->repeat_remove_grp) == 2) {
3861     cfp->repeat_remove = TRUE;
3862   } else {
3863     cfp->repeat_remove = FALSE;
3864   }
3865 
3866   /* Do actual work of removing text */
3867   cfp->isDirty = FALSE;
3868   if (cfp->type == eFieldTypeDefline || cfp->type == eFieldTypeCommentDescriptor) {
3869     VisitDescriptorsInSep (sep, cfp, RemoveDescriptorTextCallback);
3870   }
3871   else if (cfp->type == eFieldTypeBioSource || cfp->type == eFieldTypeOrgModSubSource) {
3872     VisitBioSourcesInSep (sep, cfp, RemoveASourceText);
3873   }
3874   else {
3875     VisitFeaturesInSep (sep, cfp, RemoveAFeatureText);
3876   }
3877   
3878   /* Clean up and exit */
3879 
3880   cfp->textportion = TextPortionXFree (cfp->textportion);
3881 
3882   if (cfp->isDirty) {
3883     DeleteMarkedObjects (cfp->input_entityID, 0, NULL);
3884   }
3885 
3886   ObjMgrSetDirtyFlag (cfp->input_entityID, TRUE);
3887   ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID, 0, 0);
3888   if (GetStatus (cfp->leaveDlgUp))
3889   {
3890         Show (cfp->form);
3891   }
3892   else
3893   {
3894     Remove (cfp->form);         
3895   }
3896   ArrowCursor ();
3897   Update ();
3898 }
3899 
3900 static void ConvertMessageProc (ForM f, Int2 mssg)
3901 
3902 {
3903   StdEditorProcsPtr  sepp;
3904 
3905   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3906   if (sepp != NULL) {
3907     if (sepp->handleMessages != NULL) {
3908       sepp->handleMessages (f, mssg);
3909     }
3910   }
3911 }
3912 
3913 
3914 /* gather information specific ro remove inside text, then call common removetext function */
3915 static void DoRemoveInsideText (ButtoN b)
3916 {
3917   ConvertFormPtr cfp;
3918 
3919   cfp = (ConvertFormPtr) GetObjectExtra (b);
3920   if (cfp == NULL) return;
3921 
3922   if (GetValue (cfp->repeat_remove_grp) == 2) {
3923     cfp->repeat_remove = TRUE;
3924   } else {
3925     cfp->repeat_remove = FALSE;
3926   }
3927 
3928   DoRemoveText (cfp);
3929 }
3930 
3931 
3932 /* gather information specific ro remove inside text, then call common removetext function */
3933 static void DoRemoveOutsideText (ButtoN b)
3934 {
3935   ConvertFormPtr cfp;
3936 
3937   cfp = (ConvertFormPtr) GetObjectExtra (b);
3938   if (cfp == NULL) return;
3939 
3940   if (GetValue (cfp->ifNotFoundGroup) == DO_NOTHING)
3941     cfp->ifNotFound = DO_NOTHING;
3942   else
3943     cfp->ifNotFound = REMOVE_ALL_TEXT;
3944 
3945 
3946   DoRemoveText (cfp);
3947 }
3948 
3949 
3950 /*-------------------------------------------------------------------------*/
3951 /*                                                                         */
3952 /* SetRemoveTextAcceptButton () -- Enable/Disable the Accept button depending */
3953 /*                              on the condition of other window objects.  */
3954 /*                                                                         */
3955 /*-------------------------------------------------------------------------*/
3956 
3957 static void SetRemoveTextAcceptButton (Pointer data)
3958 
3959 {
3960   ConvertFormPtr   cfp;
3961   FieldSubfieldPtr f;
3962   Boolean          ok_to_accept = FALSE;
3963   TextPortionXPtr   tp;
3964 
3965   cfp = (ConvertFormPtr) data;
3966   if (cfp == NULL) return;
3967 
3968   f = DialogToPointer (cfp->target_dlg);
3969   if (f != NULL && f->field >= 0 && (f->subfield >= 0 || f->subfield_list != NULL)) {
3970     if (f->field == eFieldTypeFeatureNote) {
3971       if (f->subfield_list != NULL) {
3972         ok_to_accept = TRUE;
3973       }
3974     } else { 
3975       ok_to_accept = TRUE;
3976     }
3977   }
3978   f = FieldSubfieldFree (f);
3979   if (ok_to_accept) {
3980     tp = (TextPortionXPtr) DialogToPointer (cfp->textportion_dlg);
3981     if (tp == NULL || (StringHasNoText (tp->start_text) && StringHasNoText (tp->end_text))) {
3982       ok_to_accept = FALSE;        
3983     }
3984     tp = TextPortionXFree (tp);
3985   }
3986   if (ok_to_accept) {
3987     SafeEnable (cfp->accept);
3988   } else {
3989     SafeDisable (cfp->accept);
3990   }
3991   f = FieldSubfieldFree (f);
3992 }
3993 
3994 
3995 static void ClearRemoveOutsideText (ButtoN b)
3996 {
3997   ConvertFormPtr cfp;
3998 
3999   cfp = (ConvertFormPtr) GetObjectExtra (b);
4000   if (cfp == NULL) return;
4001 
4002   PointerToDialog (cfp->target_dlg, NULL);
4003   PointerToDialog (cfp->textportion_dlg, NULL);
4004 
4005   SetRemoveTextAcceptButton (cfp);
4006 }
4007 
4008 
4009 /*---------------------------------------------------------------------*/
4010 /*                                                                     */
4011 /* RemoveTextOutsideString ()                                          */
4012 /*                                                                     */
4013 /*---------------------------------------------------------------------*/
4014 
4015 extern void RemoveTextOutsideString (IteM i)
4016 {
4017   Boolean            allowed[eFieldType_Max];
4018   BaseFormPtr        bfp;
4019   GrouP              buttonGroup;
4020   ConvertFormPtr     cfp;
4021   GrouP              mainGroup;
4022   SeqEntryPtr        sep;
4023   StdEditorProcsPtr  sepp;
4024   WindoW             w;
4025   PrompT             p, p2;
4026   ButtoN             b;
4027 
4028   /* Get current sequence */
4029 
4030 #ifdef WIN_MAC
4031   bfp = currentFormDataPtr;
4032 #else
4033   bfp = GetObjectExtra (i);
4034 #endif
4035   if (bfp == NULL)
4036     return;
4037 
4038   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4039   if (sep == NULL)
4040     return;
4041 
4042   /* Create a form for passing user data on to callbacks */
4043 
4044   cfp = ConvertFormNew ();
4045   if (cfp == NULL)
4046     return;
4047 
4048   /* Create a window for getting user input */
4049 
4050   w = FixedWindow (-50, -33, -10, -10, "Remove Text Outside String",
4051                    StdCloseWindowProc);
4052   SetObjectExtra (w, cfp, StdCleanupFormProc);
4053   cfp->form = (ForM) w;
4054   cfp->formmessage = ConvertMessageProc;
4055 
4056   /* Attach some basic data and callbacks to the data form */
4057 
4058   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
4059   if (sepp != NULL) {
4060     SetActivate (w, sepp->activateForm);
4061     cfp->appmessage = sepp->handleMessages;
4062   }
4063 
4064   cfp->input_entityID = bfp->input_entityID;
4065   cfp->input_itemID   = bfp->input_itemID;
4066   cfp->input_itemtype = bfp->input_itemtype;
4067 
4068   cfp->set_accept_proc = SetRemoveTextAcceptButton ;
4069   cfp->remove_inside = FALSE;
4070 
4071   /* Main object group for holding all the others */
4072 
4073   mainGroup = HiddenGroup (w, -1, 0, NULL);
4074   SetGroupSpacing (mainGroup, 10, 10);
4075 
4076   /* Set up Text group and headers */
4077 
4078   p = StaticPrompt (mainGroup, "Remove Text", 0, 0, programFont, 'l');
4079 
4080   cfp->textportion_dlg = TextPortionXDialogEx (mainGroup, FALSE, SetRemoveTextAcceptButton, cfp);
4081 
4082   /* The "If not found" group */
4083 
4084   cfp->ifNotFoundGroup = HiddenGroup (mainGroup, 0, 3, NULL);
4085   StaticPrompt (cfp->ifNotFoundGroup, "If field doesn't contain searched" 
4086                 " for text:", 0, 0, programFont, 'l');
4087 
4088   RadioButton (cfp->ifNotFoundGroup, "     Do nothing to field");
4089   RadioButton (cfp->ifNotFoundGroup, "     Remove entire field text");
4090   SetValue (cfp->ifNotFoundGroup, DO_NOTHING);
4091 
4092   p2 = StaticPrompt (mainGroup, "Perform excision in", 0, popupMenuHeight, programFont, 'l');
4093 
4094   /* selecting the target field */
4095   MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
4096   allowed[eFieldTypeFeatureNote] = FALSE;
4097   allowed[eFieldTypePublication] = FALSE;
4098   cfp->target_dlg = CreateFieldSubfieldDlg (mainGroup, allowed, ChangeTargetFields, cfp);
4099 
4100   /* clear button */
4101   b = PushButton (mainGroup, "Clear", ClearRemoveOutsideText);
4102   SetObjectExtra (b, cfp, NULL);
4103 
4104   /* Accept and Cancel buttons */
4105 
4106   buttonGroup = HiddenGroup (mainGroup, 4, 0, NULL);
4107   cfp->accept = DefaultButton (buttonGroup, "Accept", DoRemoveOutsideText);
4108   SetObjectExtra (cfp->accept, cfp, NULL);
4109   Disable (cfp->accept);
4110   PushButton (buttonGroup, "Cancel", StdCancelButtonProc);
4111   cfp->leaveDlgUp = CheckBox (buttonGroup, "Leave Dialog Up", NULL);
4112 
4113   /* Line things up and display the window */
4114 
4115   AlignObjects (ALIGN_CENTER,
4116                 (HANDLE) p,
4117                 (HANDLE) cfp->textportion_dlg,
4118                 (HANDLE) cfp->ifNotFoundGroup,
4119                 (HANDLE) p2,
4120                             (HANDLE) cfp->target_dlg,
4121                 (HANDLE) b,
4122                             (HANDLE) buttonGroup,
4123                             NULL);
4124 
4125   RealizeWindow (w);
4126   Show (w);
4127   Select (w);
4128   Update ();
4129 }
4130 
4131 extern void RemoveTextInsideString (IteM i)
4132 {
4133   BaseFormPtr        bfp;
4134   GrouP              c;
4135   ConvertFormPtr     cfp;
4136   GrouP              h;
4137   PrompT             ppt, ppt2;
4138   SeqEntryPtr        sep;
4139   StdEditorProcsPtr  sepp;
4140   WindoW             w;
4141   Boolean            allowed[eFieldType_Max];
4142 
4143 #ifdef WIN_MAC
4144   bfp = currentFormDataPtr;
4145 #else
4146   bfp = GetObjectExtra (i);
4147 #endif
4148   if (bfp == NULL) return;
4149   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4150   if (sep == NULL) return;
4151   cfp = ConvertFormNew ();
4152   if (cfp == NULL) return;
4153 
4154   cfp->set_accept_proc = SetRemoveTextAcceptButton;
4155   cfp->remove_inside = TRUE;
4156 
4157   w = FixedWindow (-50, -33, -10, -10, "Remove Text Inside String", StdCloseWindowProc);
4158   SetObjectExtra (w, cfp, StdCleanupFormProc);
4159   cfp->form = (ForM) w;
4160   cfp->formmessage = ConvertMessageProc;
4161 
4162   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
4163   if (sepp != NULL) {
4164     SetActivate (w, sepp->activateForm);
4165     cfp->appmessage = sepp->handleMessages;
4166   }
4167 
4168   cfp->input_entityID = bfp->input_entityID;
4169   cfp->input_itemID = bfp->input_itemID;
4170   cfp->input_itemtype = bfp->input_itemtype;
4171 
4172   h = HiddenGroup (w, -1, 0, NULL);
4173   SetGroupSpacing (h, 10, 10);
4174 
4175   ppt = StaticPrompt (h, "Remove Text", 0, popupMenuHeight, programFont, 'c');
4176   cfp->textportion_dlg = TextPortionXDialogEx (h, TRUE, SetRemoveTextAcceptButton, cfp);
4177   
4178   cfp->repeat_remove_grp = HiddenGroup (h, 2, 0, NULL);
4179   RadioButton (cfp->repeat_remove_grp, "Remove first instance in each string");
4180   RadioButton (cfp->repeat_remove_grp, "Remove all instances");
4181   SetValue (cfp->repeat_remove_grp, 1);
4182 
4183   ppt2 = StaticPrompt (h, "Perform excision in", 0, popupMenuHeight, programFont, 'c');
4184   
4185   MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
4186   allowed[eFieldTypeCommentDescriptor] = TRUE;
4187   allowed[eFieldTypeFeatureNote] = FALSE;
4188   allowed[eFieldTypePublication] = FALSE;
4189   cfp->target_dlg = CreateFieldSubfieldDlg (h, allowed, ChangeTargetFields, cfp);
4190 
4191   c = HiddenGroup (h, 4, 0, NULL);
4192   cfp->accept = DefaultButton (c, "Accept", DoRemoveInsideText);
4193   SetObjectExtra (cfp->accept, cfp, NULL);
4194   Disable (cfp->accept);
4195   PushButton (c, "Cancel", StdCancelButtonProc);
4196   cfp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
4197 
4198 
4199   AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) cfp->textportion_dlg, (HANDLE) cfp->repeat_remove_grp, (HANDLE) ppt2, (HANDLE) cfp->target_dlg, (HANDLE) c, NULL);
4200   RealizeWindow (w);
4201   Show (w);
4202   Select (w);
4203   Select (cfp->textportion_dlg);
4204   Update ();
4205 }
4206 
4207 /* AAForCodon is extern in seqport.c */
4208 /* NLM_EXTERN Uint1 AAForCodon (Uint1Ptr codon, CharPtr codes); */
4209 
4210 /*
4211 static Boolean CorrectStartCodonCallback (GatherContextPtr gcp)
4212 
4213 {
4214   Uint1           aa;
4215   Boolean         bad_base;
4216   CodeBreakPtr    cbp;
4217   Uint1           codon [3];
4218   CharPtr         codes;
4219   CdRegionPtr     crp;
4220   GeneticCodePtr  gc;
4221   Int2            i;
4222   Uint1           residue;
4223   SeqEntryPtr     sep;
4224   SeqFeatPtr      sfp;
4225   SeqLocPtr       slp;
4226   SeqPntPtr       spntp;
4227   SeqPortPtr      spp;
4228   ValNodePtr      vnp;
4229 
4230   if (gcp == NULL) return TRUE;
4231   sep = (SeqEntryPtr) gcp->userdata;
4232   if (sep == NULL ) return TRUE;
4233   if (gcp->thistype != OBJ_SEQFEAT) return TRUE;
4234   sfp = (SeqFeatPtr) gcp->thisitem;
4235   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return TRUE;
4236   crp = (CdRegionPtr) sfp->data.value.ptrvalue;
4237   if (crp == NULL) return TRUE;
4238 
4239   if (crp->code_break != NULL) return TRUE;
4240 
4241         gc = NULL;
4242         if (crp->genetic_code != NULL)
4243         {
4244                 vnp = (ValNodePtr)(crp->genetic_code->data.ptrvalue);
4245                 while ((vnp != NULL) && (gcp == NULL))
4246                 {
4247                         switch (vnp->choice)
4248                         {
4249                         case 1:
4250                                 gc = GeneticCodeFind(0, (CharPtr)vnp->data.ptrvalue);
4251                                 break;
4252                         case 2:
4253                                 gc = GeneticCodeFind(vnp->data.intvalue, NULL);
4254                                 break;
4255                         case 3:
4256                         case 6:
4257                         case 4:
4258                         case 5:
4259                         case 7:
4260                         case 8:
4261                         default:
4262                                 break;
4263                         }
4264                         vnp = vnp->next;
4265                 }
4266         }
4267         if (gc == NULL)
4268                 gc = GeneticCodeFind(1, NULL);
4269         if (gc == NULL) return TRUE;
4270 
4271         codes = NULL;
4272         for (vnp = (ValNodePtr)gc->data.ptrvalue; vnp != NULL; vnp = vnp->next)
4273         {
4274                 if (vnp->choice == 3)
4275                         codes = (CharPtr)vnp->data.ptrvalue;
4276         }
4277         if (codes == NULL) return TRUE;
4278 
4279   if (crp->frame == 2 || crp->frame == 3) return TRUE;
4280 
4281   spp = SeqPortNewByLoc (sfp->location, Seq_code_ncbi4na);
4282   if (spp == NULL) return TRUE;
4283   bad_base = FALSE;
4284   for (i = 0; i < 3; i++) {
4285     residue = SeqPortGetResidue (spp);
4286     if (residue == SEQPORT_EOF)
4287       break;
4288     if (residue == INVALID_RESIDUE)
4289       bad_base = TRUE;
4290     codon[i] = residue;
4291   }
4292   SeqPortFree (spp);
4293   if (i != 3 || bad_base) return TRUE;
4294   aa = AAForCodon (codon, codes);
4295 
4296   spp = SeqPortNewByLoc (sfp->product, Seq_code_ncbieaa);
4297   if (spp == NULL) return TRUE;
4298   residue = SeqPortGetResidue (spp);
4299   SeqPortFree (spp);
4300   if (residue == SEQPORT_EOF || residue == INVALID_RESIDUE) return TRUE;
4301 
4302   if (residue != aa) {
4303     cbp = CodeBreakNew ();
4304     if (cbp != NULL) {
4305       spntp = SeqPntNew ();
4306       slp = ValNodeNew (NULL);
4307       slp->choice = SEQLOC_PNT;
4308       slp->data.ptrvalue = (Pointer) spntp;
4309       spntp->point = (Int4) 0;
4310       spntp->id = SeqIdStripLocus (SeqIdDup (SeqLocId (sfp->product)));
4311       cbp->loc = slp;
4312       slp = aaLoc_to_dnaLoc (sfp, cbp->loc);
4313       cbp->loc = SeqLocFree (cbp->loc);
4314       cbp->loc = slp;
4315       cbp->aa.value.intvalue = aa;
4316       cbp->aa.choice = 1;
4317       cbp->next = crp->code_break;
4318       crp->code_break = cbp;
4319     }
4320   }
4321 
4322   return TRUE;
4323 }
4324 
4325 static void CorrectStartCodon (SeqEntryPtr sep, Uint2 entityID)
4326 
4327 {
4328   BioseqSetPtr  bssp;
4329   GatherScope   gs;
4330 
4331   if (sep == NULL) return;
4332   if (IS_Bioseq_set (sep)) {
4333     bssp = (BioseqSetPtr) sep->data.ptrvalue;
4334     if (bssp != NULL && (bssp->_class == 7 || bssp->_class == 13 ||
4335                          bssp->_class == 14 || bssp->_class == 15)) {
4336       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
4337         CorrectStartCodon (sep, entityID);
4338       }
4339       return;
4340     }
4341   }
4342   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
4343   gs.seglevels = 1;
4344   gs.get_feats_location = FALSE;
4345   MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
4346   gs.ignore[OBJ_BIOSEQ] = FALSE;
4347   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
4348   gs.ignore[OBJ_SEQFEAT] = FALSE;
4349   gs.ignore[OBJ_SEQANNOT] = FALSE;
4350   gs.scope = sep;
4351   GatherEntity (entityID, (Pointer) sep, CorrectStartCodonCallback, &gs);
4352 }
4353 
4354 extern void CorrectCDSStartCodon (IteM i);
4355 extern void CorrectCDSStartCodon (IteM i)
4356 
4357 {
4358   BaseFormPtr  bfp;
4359   SeqEntryPtr  sep;
4360 
4361 #ifdef WIN_MAC
4362   bfp = currentFormDataPtr;
4363 #else
4364   bfp = GetObjectExtra (i);
4365 #endif
4366   if (bfp == NULL) return;
4367   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4368   if (sep == NULL) return;
4369   CorrectStartCodon (sep, bfp->input_entityID);
4370   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
4371   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
4372 }
4373 */
4374 
4375 
4376 typedef struct applyformdata {
4377   FEATURE_FORM_BLOCK
4378 
4379   Int2           type;
4380   Int2           errcount;
4381   ValNodePtr     ambigList;
4382   Boolean        noLeft;
4383   Boolean        noRight;
4384   ButtoN         applyToParts;
4385   ButtoN         partial5;
4386   ButtoN         partial3;
4387   TexT           onlyThisPart;
4388   GrouP          all_or_some_grp;
4389   TexT           accession_list_txt;
4390   
4391   DialoG         feature_details_dlg;
4392   
4393   BatchApplyFeatureDetailsPtr feature_details_data;
4394   
4395   GrouP          strand_group;
4396   GrouP          use_whole_interval;
4397   TexT           left_end;
4398   TexT           right_end;
4399   ButtoN         add_to_seq_with_like_feature;
4400   ButtoN         also_add_mRNA_btn;
4401   ButtoN         accept;
4402   ButtoN         leaveDlgUp;
4403   
4404   GetSamplePtr   gsp;
4405   ExistingTextPtr etp;
4406 } ApplyFormData, PNTR ApplyFormPtr;
4407 
4408 typedef struct alreadyhas {
4409   Boolean        rsult;
4410   Uint1          featchoice;
4411   Uint1          descchoice;
4412   Uint1          rnatype;
4413 } AlreadyHas, PNTR AlreadyHasPtr;
4414 
4415 static Boolean SeeIfAlreadyHasGatherFunc (GatherContextPtr gcp)
4416 
4417 {
4418   AlreadyHasPtr  ahp;
4419   RnaRefPtr      rrp;
4420   ValNodePtr     sdp;
4421   SeqFeatPtr     sfp;
4422 
4423   if (gcp == NULL) return TRUE;
4424 
4425   ahp = (AlreadyHasPtr) gcp->userdata;
4426   if (ahp == NULL ) return TRUE;
4427 
4428   if (gcp->thistype == OBJ_SEQFEAT && ahp->featchoice != 0) {
4429     sfp = (SeqFeatPtr) gcp->thisitem;
4430     if (sfp != NULL && sfp->data.choice == ahp->featchoice && sfp->data.value.ptrvalue != NULL) {
4431       if (sfp->data.choice == SEQFEAT_RNA) {
4432         rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
4433         if (rrp->type != ahp->rnatype) return TRUE;
4434       }
4435       ahp->rsult = TRUE;
4436       return FALSE;
4437     }
4438   } else if (gcp->thistype == OBJ_SEQDESC && ahp->descchoice != 0) {
4439     sdp = (ValNodePtr) gcp->thisitem;
4440     if (sdp != NULL && sdp->choice == ahp->descchoice && sdp->data.ptrvalue != NULL) {
4441       ahp->rsult = TRUE;
4442       return FALSE;
4443     }
4444   }
4445   return TRUE;
4446 }
4447 
4448 static Boolean AlreadyHasFeatOrDesc (SeqEntryPtr sep, Uint1 featchoice, Uint1 descchoice, Uint1 rnatype)
4449 
4450 {
4451   AlreadyHas   ah;
4452   BioseqPtr    bsp;
4453   GatherScope  gs;
4454   SeqEntryPtr  nsep;
4455   SeqIdPtr     sip;
4456   SeqLocPtr    slp;
4457 
4458   ah.rsult = FALSE;
4459   ah.featchoice = featchoice;
4460   ah.descchoice = descchoice;
4461   ah.rnatype = rnatype;
4462   if (sep == NULL) return FALSE;
4463   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
4464   gs.seglevels = 1;
4465   gs.get_feats_location = TRUE;
4466   MemSet ((Pointer) (gs.ignore), (int)(TRUE), (size_t) (OBJ_MAX * sizeof(Boolean)));
4467   gs.ignore[OBJ_BIOSEQ] = FALSE;
4468   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
4469   gs.ignore[OBJ_SEQFEAT] = FALSE;
4470   gs.ignore[OBJ_SEQDESC] = FALSE;
4471   gs.ignore[OBJ_SEQANNOT] = FALSE;
4472   gs.scope = sep;
4473   if (descchoice != 0) {
4474     nsep = FindNucSeqEntry (sep);
4475     if (nsep != NULL && IS_Bioseq (nsep)) {
4476       bsp = (BioseqPtr) nsep->data.ptrvalue;
4477       if (bsp != NULL) {
4478         slp = ValNodeNew (NULL);
4479         slp->choice = SEQLOC_WHOLE;
4480         sip = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
4481         slp->data.ptrvalue = sip;
4482         gs.target = slp;
4483       }
4484     }
4485   }
4486   GatherSeqEntry (sep, (Pointer) (&ah), SeeIfAlreadyHasGatherFunc, &gs);
4487   gs.target = SeqLocFree (gs.target);
4488   return ah.rsult;
4489 }
4490 
4491 static void setSeqFeatStrand(SeqFeatPtr sfp, Uint1 strand)
4492 {
4493   SeqIntPtr          sqip;
4494 
4495   if (sfp == NULL) return;
4496   if (sfp->location == NULL) return;
4497   if (sfp->location->choice != SEQLOC_INT) return;
4498   sqip = (SeqIntPtr) sfp->location->data.ptrvalue;
4499   if (sqip != NULL)
4500   {
4501     sqip->strand = Seq_strand_minus;
4502   }
4503 }
4504 
4505 /* must be called after partials and strand are set*/
4506 static void AdjustSeqLocForApply (SeqFeatPtr sfp, ApplyFormPtr afp)
4507 {
4508   BioseqPtr bsp;
4509   SeqLocPtr slp;
4510   SeqIntPtr sip;
4511   CharPtr   num_str;
4512   Int4      from;
4513   Int4      to;
4514   Int4      tmp;
4515   Boolean   partial3, partial5;
4516   Boolean   is_caret = FALSE;
4517   Uint1     strand;
4518   
4519   if (sfp == NULL || afp == NULL) return;
4520   
4521   bsp = BioseqFindFromSeqLoc (sfp->location);
4522   if (bsp == NULL) return;
4523   
4524   num_str = SaveStringFromText (afp->left_end);
4525   if (num_str == NULL) return;
4526   from = atoi (num_str);
4527   tmp = StringLen (num_str);
4528   if (tmp > 1 && num_str[tmp - 1] == '^')
4529   {
4530     is_caret = TRUE;
4531   } 
4532   num_str = MemFree (num_str);
4533   num_str = SaveStringFromText (afp->right_end);
4534   if (num_str == NULL) return;
4535   to = atoi (num_str);
4536   num_str = MemFree (num_str);
4537   if (from > to)
4538   {
4539         tmp = from;
4540         from = to;
4541         to = tmp;
4542   }
4543   if (from < 1)
4544   {
4545         from = 1;
4546   }
4547   if (to < 1)
4548   {
4549     if (to == 0 && is_caret) {
4550       to = from + 1;
4551     } else {
4552           to = 1;
4553         }
4554   }
4555   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
4556   strand = SeqLocStrand (sfp->location);
4557   if (to > bsp->length)
4558   {
4559         to = bsp->length;
4560         partial3 = TRUE;
4561   }
4562 
4563   if (is_caret && to != from + 1) {
4564     is_caret = FALSE;
4565   }
4566 
4567   slp = NULL;
4568   if (is_caret) {
4569     AddSeqLocPoint (&slp, SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0))),
4570                     from, FALSE, TRUE, strand);
4571   } else {
4572     slp = ValNodeNew (NULL);
4573     if (slp != NULL) {
4574       sip = SeqIntNew ();
4575       if (sip != NULL) {
4576         sip->from = from - 1;
4577         sip->to = to - 1;
4578         sip->strand = strand;
4579         sip->id = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0)));
4580         slp->choice = SEQLOC_INT;
4581         slp->data.ptrvalue = (Pointer) sip;
4582         SetSeqLocPartial (slp, partial5, partial3);
4583       }
4584     }
4585   }
4586   
4587   sfp->location = SeqLocFree (sfp->location);
4588   sfp->location = slp;
4589   
4590   if (partial5 || partial3)
4591   {
4592         sfp->partial = TRUE;
4593   }
4594   
4595 }
4596 
4597 static void SetApplyFeatureLocation (SeqFeatPtr sfp, ApplyFormPtr afp)
4598 {
4599   if (sfp == NULL || afp == NULL)
4600   {
4601     return;
4602   }
4603   
4604   if (GetValue (afp->strand_group) == 2) 
4605   {
4606     /* reverse strand direction - strand direction is plus by default */
4607     setSeqFeatStrand (sfp, Seq_strand_minus);
4608   }
4609 
4610   SetSeqLocPartial (sfp->location, afp->noLeft, afp->noRight);
4611 
4612   if (afp->use_whole_interval != NULL
4613       && GetValue (afp->use_whole_interval) != 1)
4614   {
4615     /* adjust location to match coordinates from user */
4616     AdjustSeqLocForApply (sfp, afp);
4617   }      
4618     
4619   sfp->partial = (afp->noLeft || afp->noRight);
4620 }
4621 
4622 static void AddGeneXrefToFeat (SeqFeatPtr sfp, CharPtr str)
4623 {
4624   SeqFeatXrefPtr    xref;
4625   GeneRefPtr        grp;
4626   
4627   if (sfp == NULL || StringHasNoText (str)) return;
4628   
4629   /* add gene xref to feature */
4630   xref = SeqFeatXrefNew ();
4631   if (xref != NULL)
4632   {
4633     grp = CreateNewGeneRef (str, NULL, NULL, FALSE);
4634     if (grp != NULL) 
4635     {
4636       xref->data.choice = SEQFEAT_GENE;
4637       xref->data.value.ptrvalue = grp;
4638       xref->next = sfp->xref;
4639       sfp->xref = xref;
4640     }
4641   }
4642 }
4643 
4644 static SeqFeatPtr ApplyGene (CharPtr str, ApplyFormPtr afp, SeqEntryPtr gene_sep, SeqFeatPtr sfp)
4645 {
4646   GeneRefPtr        grp;
4647   SeqFeatPtr        gene_sfp;
4648   SeqFeatXrefPtr    xref;
4649   SeqMgrFeatContext fcontext;
4650   BioseqPtr         bsp = NULL;
4651   SeqFeatPtr        other_feat;
4652   SeqFeatPtr        overlap_gene;
4653   Boolean           added_xrefs = FALSE;
4654   SeqFeatPtr        misc_feat = NULL;
4655   SeqLocPtr         overlap_loc;
4656   CharPtr           gene_desc = NULL;
4657 
4658   if (afp == NULL || gene_sep == NULL 
4659           || (StringHasNoText (str) 
4660               && (afp->feature_details_data == NULL 
4661                       || StringHasNoText (afp->feature_details_data->geneDesc))))
4662   {
4663     return NULL;
4664   }
4665 
4666   if (afp != NULL && afp->feature_details_data != NULL)
4667   {
4668     gene_desc = afp->feature_details_data->geneDesc;
4669   }
4670 
4671   /* we need a location to use when we're checking for feature-stealing genes */
4672   if (sfp != NULL)
4673   {
4674     overlap_loc = sfp->location;
4675   }
4676   else
4677   {
4678     misc_feat = CreateNewFeature (gene_sep, NULL, SEQFEAT_COMMENT, NULL);
4679     if (NULL == misc_feat)
4680     return NULL;
4681     
4682     SetApplyFeatureLocation (misc_feat, afp);
4683 
4684     overlap_loc = misc_feat->location;
4685   }
4686   
4687   /* first, add gene xrefs to all features on bioseq that are contained in the location */
4688   /* maintain list of features that had xrefs before, should not remove them later */
4689   if (IS_Bioseq (gene_sep))
4690   {
4691     bsp = (BioseqPtr) gene_sep->data.ptrvalue;
4692   }
4693   else if (sfp != NULL)
4694   {
4695     bsp = BioseqFindFromSeqLoc (sfp->location);
4696   }
4697   if (bsp != NULL)
4698   {
4699     other_feat = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
4700     while (other_feat != NULL)
4701     {
4702       if (other_feat != sfp && other_feat->data.choice != SEQFEAT_GENE)
4703       {
4704         for (xref = other_feat->xref;
4705              xref != NULL && xref->data.choice != SEQFEAT_GENE;
4706              xref = xref->next)
4707         {}
4708         if (xref == NULL
4709             && SeqLocCompare (other_feat->location, overlap_loc) == SLC_A_EQ_B)
4710         {
4711           overlap_gene = SeqMgrGetOverlappingGene (other_feat->location, &fcontext);
4712           if (overlap_gene != NULL)
4713           {
4714             AddGeneXrefToFeat (other_feat, fcontext.label);
4715             added_xrefs = TRUE;
4716           }
4717         }
4718       }
4719       other_feat = SeqMgrGetNextFeature (bsp, other_feat, 0, 0, &fcontext);
4720     }   
4721   }
4722   
4723   if (misc_feat != NULL)
4724   {
4725     misc_feat->idx.deleteme = TRUE;
4726     DeleteMarkedObjects (0, OBJ_SEQENTRY, gene_sep);
4727   }
4728   
4729   grp = CreateNewGeneRef (str, NULL, gene_desc, FALSE);
4730   if (NULL == grp)
4731     return NULL;
4732 
4733   gene_sfp = CreateNewFeature (gene_sep, NULL, SEQFEAT_GENE, NULL);
4734   if (NULL == gene_sfp)
4735     return NULL;
4736 
4737   gene_sfp->data.value.ptrvalue = (Pointer) grp;
4738   
4739   SetApplyFeatureLocation (gene_sfp, afp);
4740 
4741   if (added_xrefs && sfp != NULL)
4742   {
4743     /* add gene xref to feature */
4744     AddGeneXrefToFeat (sfp, str);
4745   }
4746   
4747   return gene_sfp;
4748 }
4749 
4750 
4751 typedef struct adjustfeatforgapdialog {
4752   DIALOG_MESSAGE_BLOCK
4753   DialoG feature_select;
4754   ButtoN unknown_gaps;
4755   ButtoN known_gaps;
4756   GrouP  partial_grp;
4757   ButtoN trim_ends;
4758   ButtoN split_internal;
4759 
4760   Nlm_ChangeNotifyProc     change_notify;
4761   Pointer                  change_userdata;
4762 } AdjustFeatForGapDialogData, PNTR AdjustFeatForGapDialogPtr;
4763 
4764 
4765 static void AdjustFeaturesForGapToDialog (DialoG d, Pointer udata)
4766 {
4767   AdjustFeatForGapDialogPtr dlg;
4768   AdjustFeatForGapPtr       data;
4769 
4770   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (d);
4771   data = (AdjustFeatForGapPtr) udata;
4772 
4773   if (dlg == NULL) return;
4774  
4775   if (data == NULL) {
4776     PointerToDialog (dlg->feature_select, NULL);
4777     SetStatus (dlg->unknown_gaps, FALSE);
4778     SetStatus (dlg->known_gaps, FALSE);
4779     SetStatus (dlg->trim_ends, FALSE);
4780     SetStatus (dlg->split_internal, FALSE);
4781     SetValue (dlg->partial_grp, 2);
4782   } else {
4783     PointerToDialog (dlg->feature_select, data->feature_list);
4784     SetStatus (dlg->unknown_gaps, data->unknown_gaps);
4785     SetStatus (dlg->known_gaps, data->known_gaps);
4786     SetStatus (dlg->split_internal, data->split_internal);
4787     SetStatus (dlg->trim_ends, data->trim_ends);
4788 
4789     if (data->make_partial && data->partial_for_pseudo) {
4790       SetValue (dlg->partial_grp, 1);
4791     } else if (data->make_partial && !data->partial_for_pseudo) {
4792       SetValue (dlg->partial_grp, 2);
4793     } else {
4794       SetValue (dlg->partial_grp, 3);
4795     }
4796   }    
4797 }
4798 
4799 
4800 static Pointer AdjustFeaturesForGapToPointer (DialoG d)
4801 {
4802   AdjustFeatForGapDialogPtr dlg;
4803   AdjustFeatForGapPtr       data;
4804   Int4                      grp_val;
4805 
4806   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (d);
4807 
4808   if (dlg == NULL) return NULL;
4809 
4810   data = (AdjustFeatForGapPtr) MemNew (sizeof (AdjustFeatForGapData));
4811 
4812   /* get list of feature types to ask on */
4813   data->feature_list = (ValNodePtr) DialogToPointer (dlg->feature_select);
4814   data->features_in_gap = NULL;
4815 
4816   data->unknown_gaps = GetStatus (dlg->unknown_gaps);
4817   data->known_gaps = GetStatus (dlg->known_gaps);
4818 
4819   grp_val = GetValue (dlg->partial_grp);
4820   switch (grp_val) {
4821     case 1:
4822       data->make_partial = TRUE;
4823       data->partial_for_pseudo = TRUE;
4824       break;
4825     case 2:
4826       data->make_partial = TRUE;
4827       data->partial_for_pseudo = FALSE;
4828       break;
4829     case 3:
4830       data->make_partial = FALSE;
4831       data->partial_for_pseudo = FALSE;
4832       break;
4833   }
4834   
4835   data->split_internal = GetStatus (dlg->split_internal);
4836   data->trim_ends = GetStatus (dlg->trim_ends);
4837 
4838   return (Pointer) data;
4839 }
4840 
4841 
4842 static ValNodePtr TestAdjustForGapsDialog (DialoG d)
4843 {
4844   AdjustFeatForGapDialogPtr dlg;
4845   AdjustFeatForGapPtr       data;
4846   ValNodePtr                err_list = NULL;
4847   
4848   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (d);
4849   if (dlg == NULL)
4850   {
4851     ValNodeAddPointer (&err_list, 0, "No dialog");
4852     return err_list;
4853   }
4854 
4855   data = (AdjustFeatForGapPtr) DialogToPointer (d);
4856   if (data == NULL) 
4857   {
4858     ValNodeAddPointer (&err_list, 0, "No data");
4859     return err_list;
4860   }
4861     
4862   if (data->feature_list == NULL) 
4863   {
4864     ValNodeAddPointer (&err_list, 0, "No features");
4865   }
4866 
4867   if (!data->unknown_gaps && !data->known_gaps)
4868   {
4869     ValNodeAddPointer (&err_list, 0, "No gaps");
4870   }
4871 
4872   if (!data->split_internal && !data->trim_ends)
4873   {
4874     ValNodeAddPointer (&err_list, 0, "No action");
4875   }
4876 
4877   data = AdjustFeatForGapFree (data);
4878 
4879   return err_list;    
4880 }
4881 
4882 
4883 static void AdjustFeaturesForGapsChangeNotifyButton (ButtoN b)
4884 {
4885   AdjustFeatForGapDialogPtr dlg;
4886 
4887   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (b);
4888   if (dlg != NULL && dlg->change_notify != NULL) {
4889     (dlg->change_notify) (dlg->change_userdata);
4890   }
4891 }
4892 
4893 
4894 static void AdjustFeaturesForGapsChangeNotifyGroup (GrouP g)
4895 {
4896   AdjustFeatForGapDialogPtr dlg;
4897 
4898   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (g);
4899   if (dlg != NULL && dlg->change_notify != NULL) {
4900     (dlg->change_notify) (dlg->change_userdata);
4901   }
4902 }
4903 
4904 
4905 static DialoG AdjustFeaturesForGapDialog (GrouP h, Uint2 entityID, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
4906 {
4907   AdjustFeatForGapDialogPtr dlg;
4908   GrouP                     p, g, g2;
4909   SeqEntryPtr               sep;
4910 
4911   dlg = (AdjustFeatForGapDialogPtr) MemNew (sizeof (AdjustFeatForGapDialogData));
4912   if (dlg == NULL) return NULL;
4913 
4914   p = HiddenGroup (h, -1, 0, NULL);
4915   SetObjectExtra (p, dlg, StdCleanupExtraProc);
4916   SetGroupSpacing (p, 10, 10);
4917 
4918   dlg->dialog = (DialoG) p;
4919   dlg->todialog = AdjustFeaturesForGapToDialog;
4920   dlg->fromdialog = AdjustFeaturesForGapToPointer;
4921   dlg->dialogmessage = NULL;
4922   dlg->testdialog = TestAdjustForGapsDialog;
4923   dlg->change_notify = change_notify;
4924   dlg->change_userdata = change_userdata;
4925   
4926   sep = GetTopSeqEntryForEntityID (entityID);
4927   dlg->feature_select = FeatureSelectionDialogEx (p, TRUE, sep,
4928                                                   change_notify, 
4929                                                   change_userdata);
4930 
4931   g = HiddenGroup (p, 2, 0, NULL);
4932   dlg->unknown_gaps = CheckBox (g, "Unknown length gaps", AdjustFeaturesForGapsChangeNotifyButton);
4933   SetObjectExtra (dlg->unknown_gaps, dlg, NULL);
4934   dlg->known_gaps = CheckBox (g, "Known length gaps", AdjustFeaturesForGapsChangeNotifyButton);
4935   SetObjectExtra (dlg->known_gaps, dlg, NULL);
4936 
4937   dlg->partial_grp = NormalGroup (p, 3, 0, "Make truncated ends partial", programFont, AdjustFeaturesForGapsChangeNotifyGroup);
4938   SetObjectExtra (dlg->partial_grp, dlg, NULL);
4939   RadioButton (dlg->partial_grp, "Always");
4940   RadioButton (dlg->partial_grp, "Unless pseudo");
4941   RadioButton (dlg->partial_grp, "Never");
4942   SetValue (dlg->partial_grp, 2);
4943 
4944   g2 = HiddenGroup (p, 2, 0, NULL);
4945   dlg->trim_ends = CheckBox (g2, "Trim ends in gaps", AdjustFeaturesForGapsChangeNotifyButton);
4946   SetObjectExtra (dlg->trim_ends, dlg, NULL);
4947   dlg->split_internal = CheckBox (g2, "Split for internal gaps", AdjustFeaturesForGapsChangeNotifyButton);
4948   SetObjectExtra (dlg->split_internal, dlg, NULL);
4949 
4950   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_select, (HANDLE) g, (HANDLE) dlg->partial_grp, (HANDLE) g2, NULL);
4951   return (DialoG) p;
4952 }
4953 
4954 typedef struct adjustfeatforgapform {
4955   FORM_MESSAGE_BLOCK
4956 
4957   DialoG dlg;
4958   DialoG clickable_list;
4959   ButtoN accept_btn;
4960   
4961   ValNodePtr feat_list;
4962 } AdjustFeatforGapFormData, PNTR AdjustFeatForGapFormPtr;
4963 
4964 
4965 typedef struct featforadjust {
4966   AdjustFeatForGapPtr afgp;
4967   ValNodePtr          features_to_adjust;
4968   ValNodePtr          features_contain_gap;
4969   ValNodePtr          features_in_gap;  
4970 } FeatForAdjustData, PNTR FeatForAdjustPtr;
4971 
4972 
4973 static void FindFeaturesToBeAdjustedForGapsCallback (SeqFeatPtr sfp, Pointer data)
4974 {
4975   FeatForAdjustPtr faap;
4976   BioseqPtr   gapped_bioseq;
4977   Boolean     terminal_gaps = FALSE;
4978   Boolean     entirely_in_gap = FALSE;
4979   Boolean     internal_gaps = FALSE;
4980 
4981   if (sfp == NULL || data == NULL) return;
4982 
4983   faap = (FeatForAdjustPtr) data;
4984   if (faap->afgp == NULL) return;
4985 
4986   if (!FeatureOkForFeatureList(sfp, faap->afgp->feature_list)) return;
4987 
4988   gapped_bioseq = BioseqFind (SeqLocId (sfp->location));
4989 
4990   LocationContainsGaps (sfp->location, gapped_bioseq, faap->afgp->unknown_gaps, faap->afgp->known_gaps, &terminal_gaps, &internal_gaps, &entirely_in_gap);
4991   if (entirely_in_gap)
4992   {
4993     ValNodeAddPointer (&(faap->features_in_gap), OBJ_SEQFEAT, sfp);
4994   }
4995   
4996   if (internal_gaps)
4997   {
4998     ValNodeAddPointer (&(faap->features_contain_gap), OBJ_SEQFEAT, sfp);
4999   }
5000 
5001   if ((faap->afgp->split_internal && internal_gaps) 
5002       || (faap->afgp->trim_ends && terminal_gaps)) 
5003   {
5004     ValNodeAddPointer (&(faap->features_to_adjust), OBJ_SEQFEAT, sfp);
5005   }
5006 }
5007 
5008 
5009 static void AdjustFeaturesForGapsChangeNotify (Pointer data)
5010 {
5011   AdjustFeatForGapFormPtr dlg;
5012   FeatForAdjustData       ffad;
5013   ValNodePtr              err_list;
5014   SeqEntryPtr             sep;
5015   ClickableItemPtr        cip;
5016 
5017   dlg = (AdjustFeatForGapFormPtr) data;
5018 
5019   if (dlg == NULL) return;
5020 
5021   err_list = TestDialog (dlg->dlg);
5022   if (err_list == NULL) 
5023   {
5024     Enable (dlg->accept_btn);
5025   } 
5026   else
5027   {
5028     err_list = ValNodeFree (err_list);
5029     Disable (dlg->accept_btn);
5030   }
5031 
5032   /* clear clickable list display */
5033   PointerToDialog (dlg->clickable_list, NULL);
5034   /* re-create list of features */
5035   dlg->feat_list = FreeClickableList (dlg->feat_list);
5036 
5037   ffad.afgp = DialogToPointer (dlg->dlg);
5038   ffad.features_contain_gap = NULL;
5039   ffad.features_in_gap = NULL;
5040   ffad.features_to_adjust = NULL;
5041 
5042   if (ffad.afgp->feature_list != NULL)
5043   {
5044     sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
5045     VisitFeaturesInSep (sep, &(ffad), FindFeaturesToBeAdjustedForGapsCallback);
5046   }
5047 
5048   if (ffad.features_to_adjust != NULL) {
5049     cip = NewClickableItem (0, "%d features will be adjusted", ffad.features_to_adjust);
5050     ValNodeAddPointer (&(dlg->feat_list), 0, cip);
5051   }
5052   if (ffad.features_in_gap != NULL) {
5053     cip = NewClickableItem (0, "%d features are completely contained in gaps and will be deleted", ffad.features_in_gap);
5054     ValNodeAddPointer (&(dlg->feat_list), 0, cip);
5055   }
5056   if (ffad.features_contain_gap != NULL) {
5057     cip = NewClickableItem (0, "%d features contain internal gaps", ffad.features_contain_gap);
5058     ValNodeAddPointer (&(dlg->feat_list), 0, cip);
5059   }
5060 
5061   /* pass list of features to clickable list display */
5062   PointerToDialog (dlg->clickable_list, dlg->feat_list);
5063 
5064 }
5065 
5066 
5067 static void DoAdjustFeaturesForGaps (ButtoN b)
5068 {
5069   AdjustFeatForGapFormPtr dlg;
5070   AdjustFeatForGapPtr     data;
5071   SeqEntryPtr             sep;
5072 
5073   dlg = (AdjustFeatForGapFormPtr) GetObjectExtra (b);
5074 
5075   if (dlg == NULL) return;
5076 
5077   data = (AdjustFeatForGapPtr) DialogToPointer (dlg->dlg);
5078 
5079   sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
5080   VisitFeaturesInSep (sep, data, AdjustFeatureForGapsCallback);
5081 
5082   /* remove features entirely in the gap */
5083   MarkFeaturesInGapsForDeletion (data);
5084   DeleteMarkedObjects (dlg->input_entityID, 0, NULL);
5085   RenormalizeNucProtSets (sep, TRUE);
5086 
5087   ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
5088   ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
5089 
5090   data = AdjustFeatForGapFree(data);
5091   
5092   Remove (dlg->form);  
5093 }
5094 
5095 
5096 static void MakeGapFeatureReport (ButtoN b)
5097 {
5098   FILE                    *fp;
5099   Char                    path [PATH_MAX];
5100   AdjustFeatForGapFormPtr dlg;
5101   Int4                    num_disc = 0;
5102   Boolean                 show_all = FALSE;
5103 
5104 
5105   dlg = (AdjustFeatForGapFormPtr) GetObjectExtra (b);
5106 
5107   if (dlg == NULL) return;
5108   
5109   num_disc = CountChosenDiscrepancies (dlg->feat_list, FALSE);
5110 
5111   if (num_disc == 0) 
5112   {
5113     if (ANS_CANCEL == Message (MSG_OKC, "No items selected!  Export all?"))
5114     {
5115       return;
5116     }
5117     else
5118     {
5119       show_all = TRUE;
5120     }
5121   }
5122   
5123   path [0] = '\0';
5124   if (GetOutputFileName (path, sizeof (path), NULL)) {
5125 #ifdef WIN_MAC
5126     fp = FileOpen (path, "r");
5127     if (fp != NULL) {
5128       FileClose (fp);
5129     } else {
5130       FileCreate (path, "TEXT", "ttxt");
5131     }
5132 #endif
5133     fp = FileOpen (path, "w");
5134     if (fp != NULL) {
5135       WriteClickableListReport (fp, dlg->feat_list, show_all, FALSE);
5136       FileClose (fp);
5137       return;
5138     }
5139   }
5140 }
5141 
5142 
5143 extern void AdjustFeaturesForGaps (IteM i)
5144 {
5145   BaseFormPtr             bfp;
5146   AdjustFeatForGapFormPtr dlg;
5147   WindoW                  w;
5148   GrouP                   h, c;
5149   ButtoN                  b;
5150 
5151 #ifdef WIN_MAC
5152   bfp = currentFormDataPtr;
5153 #else
5154   bfp = GetObjectExtra (i);
5155 #endif
5156   if (bfp == NULL) return;
5157 
5158   dlg = (AdjustFeatForGapFormPtr) MemNew (sizeof (AdjustFeatforGapFormData));
5159   if (dlg == NULL) return;
5160     
5161   w = FixedWindow (-50, -33, -10, -10, "Adjust Features for Gaps", StdCloseWindowProc);
5162   SetObjectExtra (w, dlg, StdCleanupFormProc);
5163   dlg->form = (ForM) w;
5164   dlg->input_entityID = bfp->input_entityID;
5165   h = HiddenGroup (w, -1, 0, NULL);
5166   SetGroupSpacing (h, 10, 10);
5167   
5168   dlg->clickable_list =  CreateClickableListDialogEx (h, "", "Features", NULL, NULL,
5169                                                       ScrollToDiscrepancyItem, EditDiscrepancyItem, NULL,
5170                                                       GetDiscrepancyItemText,
5171                                                       stdCharWidth * 15,
5172                                                       stdCharWidth * 30,
5173                                                       TRUE, TRUE);
5174 
5175   dlg->dlg = AdjustFeaturesForGapDialog (h, bfp->input_entityID, AdjustFeaturesForGapsChangeNotify, dlg);
5176 
5177   c = HiddenGroup (h, 3, 0, NULL);
5178   SetGroupSpacing (c, 10, 10);
5179   dlg->accept_btn = PushButton (c, "Accept", DoAdjustFeaturesForGaps);
5180   SetObjectExtra (dlg->accept_btn, dlg, NULL);
5181   PushButton (c, "Cancel", StdCancelButtonProc);
5182   b = PushButton (c, "Make Report", MakeGapFeatureReport);
5183   SetObjectExtra (b, dlg, NULL);
5184   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->clickable_list,
5185                               (HANDLE) dlg->dlg,
5186                               (HANDLE) c,
5187                               NULL);
5188   RealizeWindow (w);
5189   AdjustFeaturesForGapsChangeNotify (dlg);
5190   Show (w);
5191   Select (w);
5192 }
5193 
5194 
5195 static ValNodePtr GapLocationsFromNs (BioseqPtr bsp, Int4Ptr gap_sizes)
5196 
5197 {
5198   CharPtr     bases, txt;
5199   Char        ch;
5200   Int4        len;
5201   ValNodePtr  seq_ext;
5202   Boolean     unknown_greater_than_or_equal = FALSE;
5203   Boolean     known_greater_than_or_equal = FALSE;
5204   Int4        unknown_gap_size = 0;
5205   Int4        known_gap_size = 0;
5206   Int4        gap_len;
5207   Boolean     make_unknown_size;
5208   GapLocInfoPtr glip;
5209   ValNodePtr  result_list = NULL;
5210   Int4        start_pos = 0;
5211   
5212 
5213   if (bsp == NULL || bsp->repr != Seq_repr_raw || ISA_aa (bsp->mol)) 
5214   {
5215     return NULL;
5216   }
5217   
5218   if (gap_sizes == NULL)
5219   {
5220     known_greater_than_or_equal = TRUE;
5221   }
5222   else
5223   {
5224     unknown_gap_size = gap_sizes[0];
5225     known_gap_size = gap_sizes[1];
5226     if (unknown_gap_size < 0)
5227     {
5228       unknown_greater_than_or_equal = TRUE;
5229       unknown_gap_size = 0 - unknown_gap_size;
5230     }
5231     if (known_gap_size < 0)
5232     {
5233       known_greater_than_or_equal = TRUE;
5234       known_gap_size = 0 - known_gap_size;
5235     }
5236   }
5237 
5238   bases = GetSequenceByBsp (bsp);
5239   if (bases == NULL) return NULL;
5240 
5241   for (txt = bases, ch = *txt; ch != '\0'; txt++, ch = *txt) {
5242     if (ch == 'N') break;
5243   }
5244   if (ch != 'N') {
5245     MemFree (bases);
5246     return NULL;
5247   }
5248 
5249   seq_ext = NULL;
5250   len = 0;
5251 
5252   txt = bases;
5253   ch = *txt;
5254 
5255   gap_len = 0;
5256   while (ch != '\0') {
5257 
5258     if (ch == 'N') {
5259       gap_len = StringSpn (txt, "N");
5260       if (gap_len == unknown_gap_size
5261           || (gap_len > unknown_gap_size && unknown_greater_than_or_equal)
5262           || gap_len == known_gap_size
5263           || (gap_len > known_gap_size && known_greater_than_or_equal))
5264       {
5265         make_unknown_size = FALSE;
5266         if (gap_len == 0)
5267         {
5268           make_unknown_size = FALSE;
5269         }
5270         else if (gap_len == unknown_gap_size)
5271         {
5272           make_unknown_size = TRUE;
5273         }
5274         else if (gap_len == known_gap_size)
5275         {
5276           make_unknown_size = FALSE;
5277         }
5278         else if (gap_len > unknown_gap_size && unknown_greater_than_or_equal)
5279         {
5280           if (!known_greater_than_or_equal)
5281           {
5282                 make_unknown_size = TRUE;
5283           }
5284           else if (unknown_gap_size > known_gap_size)
5285           {
5286                 make_unknown_size = TRUE;
5287           }
5288           else if (gap_len < known_gap_size)
5289           {
5290                 make_unknown_size = TRUE;
5291           }
5292         }
5293         
5294         /* Add Location to List */
5295         glip = (GapLocInfoPtr) MemNew (sizeof (GapLocInfoData));
5296         if (glip != NULL)
5297         {
5298           glip->start_pos = start_pos;
5299           glip->is_known = ! make_unknown_size;
5300           glip->length = gap_len;
5301           glip->replace = TRUE;
5302           ValNodeAddPointer (&result_list, 0, glip);
5303         }
5304       }
5305       txt += gap_len;
5306       start_pos += gap_len;
5307       ch = *txt;
5308       gap_len = 0;
5309     } else {
5310       gap_len = StringCSpn (txt, "N");
5311       txt+=gap_len;
5312       start_pos += gap_len;
5313       ch = *txt;
5314       gap_len = 0;
5315     }
5316   }
5317   
5318   MemFree (bases);
5319   return result_list;
5320 }
5321 
5322 static SeqLocPtr 
5323 RemoveGapLocationsFromSeqLoc 
5324 (SeqLocPtr  slp, 
5325  ValNodePtr gap_locs, 
5326  BioseqPtr  bsp,
5327  BoolPtr    loc_changed)
5328 {
5329   ValNodePtr    gap_vnp;
5330   GapLocInfoPtr glip;
5331   SeqLocPtr   loc_list = NULL, prev_loc = NULL;
5332   SeqIdPtr    sip, before_sip, after_sip;
5333   Boolean     changed, partial5, partial3;
5334   SeqLocPtr   before = NULL, after = NULL;
5335 
5336   if (loc_changed != NULL)
5337   {
5338     *loc_changed = FALSE;
5339   }
5340   
5341   if (slp == NULL || gap_locs == NULL || bsp == NULL)
5342   {
5343     return slp;
5344   }
5345   
5346   sip = SeqLocId (slp);
5347   if (sip == NULL)
5348   {
5349     return slp;
5350   }
5351   
5352   CheckSeqLocForPartial (slp, &partial5, &partial3);
5353   
5354   before = SeqLocCopy (slp);
5355   loc_list = before;
5356   
5357   for (gap_vnp = gap_locs;
5358        gap_vnp != NULL;
5359        gap_vnp = gap_vnp->next)
5360   {
5361     glip = (GapLocInfoPtr) gap_vnp->data.ptrvalue;
5362     if (glip == NULL || glip->is_known)
5363     {
5364       continue;
5365     }
5366     if (GapInLocation (glip->start_pos, glip->length, before))
5367     {
5368       if (loc_changed != NULL)
5369       {
5370         *loc_changed = TRUE;
5371       }
5372       /* we make a copy of the original location */
5373       after = SeqLocCopy (before);
5374       
5375       /* note - we need to use duplicates of the SeqID returned by
5376        * SeqLocId, just in case the first location in a mixed location 
5377        * is deleted, which would free the result from SeqLocId 
5378        */
5379       after_sip = SeqIdDup (SeqLocId (after));
5380       before_sip = SeqIdDup (SeqLocId (before));
5381       /* in the "after" location, we free everything before the 
5382        * end of the gap.
5383        */
5384       after = SeqLocDeleteEx (after, after_sip,
5385                               0, glip->start_pos + glip->length - 1,
5386                               FALSE, &changed, &partial5, &partial3);
5387                               
5388       /* in the "before" location, we free everything after the
5389        * beginning of the gap.
5390        */
5391       before = SeqLocDeleteEx (before, before_sip, 
5392                                glip->start_pos, bsp->length,
5393                                FALSE, &changed, &partial5, &partial3);
5394         
5395       /* we're done with these IDs now */                  
5396       after_sip = SeqIdFree (after_sip);
5397       before_sip = SeqIdFree (before_sip);                          
5398                           
5399       if (before == NULL)
5400       {
5401         if (prev_loc == NULL)
5402         {
5403           loc_list = after;
5404         }
5405         else
5406         {
5407           prev_loc->next = after;
5408         }
5409       }
5410       else
5411       {
5412         before->next = after;
5413         prev_loc = before;
5414       }        
5415       before = after;
5416     }
5417   }
5418 
5419   slp = SeqLocFree (slp);
5420   return loc_list;  
5421 }
5422 
5423 
5424 static void AdjustCodingRegionLocationsForGapLocations (BioseqPtr bsp, ValNodePtr gap_list)
5425 {
5426   SeqFeatPtr        sfp;
5427   SeqMgrFeatContext fcontext;
5428   BioseqPtr         protbsp = NULL, new_protbsp = NULL;
5429   SeqFeatPtr        new_sfp;
5430   CdRegionPtr       crp;
5431   Boolean           partial5, partial3;
5432   Uint2             entityID;
5433   Boolean           loc_changed;
5434   
5435   if (bsp == NULL || gap_list == NULL)
5436   {
5437     return;
5438   }
5439   
5440   entityID = bsp->idx.entityID;
5441   
5442   for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &fcontext);
5443        sfp != NULL;
5444        sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &fcontext))
5445   {
5446     CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5447     loc_changed = FALSE;
5448     sfp->location = RemoveGapLocationsFromSeqLoc (sfp->location, gap_list, bsp, &loc_changed);
5449     if (!loc_changed) {
5450         continue;
5451     }
5452     if (loc_changed)
5453     {
5454       AddCDSGapComment (sfp);
5455     }
5456    
5457     while (sfp->location->next != NULL)
5458     {
5459       new_sfp = CreateNewFeatureOnBioseq (bsp, SEQFEAT_CDREGION, NULL);
5460                   if (new_sfp != NULL)
5461                   {
5462                     /* create copy of coding region data */
5463                     crp = (CdRegionPtr) AsnIoMemCopy ((CdRegionPtr) sfp->data.value.ptrvalue,
5464                                                        (AsnReadFunc) CdRegionAsnRead,
5465                                                        (AsnWriteFunc) CdRegionAsnWrite);
5466         new_sfp->data.value.ptrvalue = crp;
5467         new_sfp->location = sfp->location->next;
5468         new_sfp->comment = StringSave (sfp->comment);
5469 
5470         protbsp = BioseqFindFromSeqLoc (sfp->product);        
5471         if (protbsp != NULL)
5472         {
5473           new_protbsp = AddProteinSequenceCopy (protbsp, bsp, new_sfp, entityID);                                                  
5474         }
5475         
5476         /* still to do:
5477          * adjust frame to match prior protein
5478          */
5479       
5480         sfp->location->next = NULL;
5481         
5482         /* fix partials */
5483         SetSeqLocPartial (sfp->location, partial5, TRUE);
5484         sfp->partial = TRUE;
5485         
5486         /* adjust frame */
5487         AdjustFrame (sfp, protbsp);
5488 
5489         /* retranslate coding region */
5490         SeqEdTranslateOneCDS (sfp, bsp, entityID, Sequin_GlobalAlign2Seq);
5491         
5492         /* set partials on product */
5493         if (protbsp == NULL)
5494         {
5495           protbsp = BioseqFindFromSeqLoc (sfp->product);
5496         }
5497         SetProductSequencePartials (protbsp, partial5, partial3);
5498 
5499         partial5 = TRUE;
5500         sfp = new_sfp;
5501         protbsp = new_protbsp;
5502                   }
5503                   else
5504                   {
5505                     return; /* bail */
5506                   }
5507     }
5508     /* fix partials for last feature */
5509     SetSeqLocPartial (sfp->location, partial5, partial3);
5510     sfp->partial = partial5 || partial3;
5511     
5512     /* adjust frame */
5513     AdjustFrame (sfp, protbsp);
5514 
5515     /* retranslate coding region */
5516     SeqEdTranslateOneCDS (sfp, bsp, entityID, Sequin_GlobalAlign2Seq);
5517     /* set partials on product */
5518     if (protbsp == NULL)
5519     {
5520       protbsp = BioseqFindFromSeqLoc (sfp->product);
5521     }
5522     SetProductSequencePartials (protbsp, partial5, partial3);
5523   }
5524 }
5525 
5526 extern void 
5527 PrepareCodingRegionLocationsForDeltaConversionCallback
5528 (BioseqPtr bsp, Pointer userdata)
5529 {
5530   Int4Ptr gap_sizes;
5531   ValNodePtr gap_locations;
5532   
5533   if (bsp == NULL)
5534   {
5535     return;
5536   }
5537   
5538   gap_sizes = (Int4Ptr) userdata;
5539   
5540   gap_locations = GapLocationsFromNs (bsp, gap_sizes);
5541   
5542   AdjustCodingRegionLocationsForGapLocations (bsp, gap_locations);
5543   
5544   gap_locations = ValNodeFreeData (gap_locations);
5545 }
5546 
5547 static Int4 
5548 CalculateGapCoverage 
5549 (BioseqPtr         bsp, 
5550  SeqLocPtr         slp, 
5551  SeqMgrFeatContext context,
5552  Boolean           include_terminal_gaps)
5553 {
5554   DeltaSeqPtr       dsp;
5555   SeqLocPtr         loc;
5556   SeqLitPtr         slip;
5557   Int4              seq_offset = 0;
5558   Int4              covered = 0;
5559   Int4              k, start, stop;
5560 
5561   if (slp == NULL
5562       || bsp == NULL || !ISA_na (bsp->mol) 
5563       || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4)
5564   {
5565     return 0;
5566   }
5567   
5568   dsp = (DeltaSeqPtr) bsp->seq_ext;
5569   while (dsp != NULL && seq_offset < context.right)
5570   {
5571     if (dsp->choice == 1)
5572     {
5573       loc = (SeqLocPtr) dsp->data.ptrvalue;
5574       if (loc != NULL)
5575       {
5576         seq_offset += SeqLocLen (loc);
5577       }
5578     }
5579     else if (dsp->choice == 2)
5580     {
5581       slip = (SeqLitPtr) dsp->data.ptrvalue;
5582       if (slip != NULL)
5583       {
5584         if (IsDeltaSeqKnownGap (dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp))
5585         {        
5586           if (seq_offset <= context.left && seq_offset + slip->length >= context.right)
5587           {
5588             /* gap covers entire location */
5589             return SeqLocLen (slp);
5590           }
5591           else if (include_terminal_gaps || 
5592                    (seq_offset > context.left 
5593                     && seq_offset + slip->length < context.right))
5594           {
5595             /* we only count internal gaps */
5596             for (k = 0; k < context.numivals; k += 2) 
5597             {
5598               start = context.ivals [k];
5599               stop = context.ivals [k + 1];
5600               if (seq_offset <= start && seq_offset + slip->length > stop)
5601               {
5602                 /* gap covers entire interval */
5603                 covered += stop - start;
5604               }
5605               else if (seq_offset > start && seq_offset + slip->length < stop)
5606               {
5607                 /* interval covers entire gap */
5608                 covered += slip->length;
5609               }
5610               else if (seq_offset < start && seq_offset + slip->length < stop)
5611               {
5612                 /* gap covers left end of interval */
5613                 covered += seq_offset + slip->length - start;
5614               }
5615               else if (seq_offset > start && seq_offset + slip->length > stop)
5616               {
5617                 /* gap covers right end of interval */
5618                 covered += stop - seq_offset;
5619               }
5620             }
5621           }
5622         }
5623         seq_offset += slip->length;
5624       }
5625     }
5626     dsp = dsp->next;
5627   }
5628 
5629   return covered;
5630   
5631 }
5632 
5633 static SeqLocPtr 
5634 RemoveTerminalGapsFromLocation
5635 (BioseqPtr         bsp, 
5636  SeqLocPtr         slp,
5637  SeqMgrFeatContext context)
5638 {
5639   DeltaSeqPtr       dsp;
5640   SeqLocPtr         loc, slp_copy;
5641   SeqLitPtr         slip;
5642   Int4              seq_offset = 0;
5643   SeqIdPtr          sip;
5644   Boolean           changed = FALSE, partial5, partial3;
5645 
5646   if (slp == NULL)
5647   {
5648     return NULL;
5649   }
5650   
5651   CheckSeqLocForPartial (slp, &partial5, &partial3);
5652   
5653   slp_copy = (SeqLocPtr) AsnIoMemCopy (slp, 
5654                                        (AsnReadFunc) SeqLocAsnRead,
5655                                        (AsnWriteFunc) SeqLocAsnWrite);
5656   if (bsp == NULL || !ISA_na (bsp->mol) 
5657       || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4)
5658   {
5659     return slp_copy;
5660   }
5661   
5662   dsp = (DeltaSeqPtr) bsp->seq_ext;
5663   while (dsp != NULL && seq_offset < context.right && slp_copy != NULL)
5664   {
5665     if (dsp->choice == 1)
5666     {
5667       loc = (SeqLocPtr) dsp->data.ptrvalue;
5668       if (loc != NULL)
5669       {
5670         seq_offset += SeqLocLen (loc);
5671       }
5672     }
5673     else if (dsp->choice == 2)
5674     {
5675       slip = (SeqLitPtr) dsp->data.ptrvalue;
5676       if (slip != NULL)
5677       {
5678         if (IsDeltaSeqKnownGap (dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp))
5679         {        
5680           if (seq_offset <= context.left && seq_offset + slip->length >= context.right)
5681           {
5682             slp_copy = SeqLocFree (slp_copy);
5683           }
5684           else if (seq_offset <= context.left && seq_offset + slip->length >= context.left)
5685           {
5686             sip = SeqIdDup (SeqLocId (slp_copy));
5687             slp_copy = SeqLocDeleteEx (slp_copy, sip,
5688                               context.left, seq_offset + slip->length - 1,
5689                               FALSE, &changed, &partial5, &partial3);
5690             sip = SeqIdFree (sip);
5691 
5692           }
5693           
5694           if (seq_offset <= context.right && seq_offset + slip->length >= context.right)
5695           {
5696             sip = SeqIdDup (SeqLocId (slp_copy));
5697             slp_copy = SeqLocDeleteEx (slp_copy, sip,
5698                               seq_offset, context.right,
5699                               FALSE, &changed, &partial5, &partial3);
5700             sip = SeqIdFree (sip);
5701           }
5702         }
5703         seq_offset += slip->length;
5704       }
5705     }
5706     dsp = dsp->next;
5707   }
5708 
5709   if (slp_copy != NULL)  
5710   {
5711     SetSeqLocPartial (slp_copy, partial5, partial3);
5712   }
5713 
5714   return slp_copy;
5715 }
5716 
5717 static void 
5718 AdjustOneCodingRegionWithTerminalGapsOnBioseq 
5719 (BioseqPtr         bsp,
5720  SeqFeatPtr        sfp,
5721  SeqMgrFeatContext context)
5722 {
5723   SeqLocPtr         adjusted_loc;
5724   Int4              loc_len, adjusted_len;
5725   Boolean           partial5, partial3;
5726   BioseqPtr         protbsp;
5727   SeqFeatPtr        gene_sfp;
5728   SeqMgrFeatContext gene_context;
5729 
5730   if (bsp == NULL || !ISA_na (bsp->mol) 
5731       || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4
5732       || sfp == NULL
5733       || (sfp->data.choice != SEQFEAT_CDREGION && sfp->idx.subtype != FEATDEF_mRNA))
5734   {
5735     return;
5736   }
5737   
5738   loc_len = SeqLocLen (sfp->location);
5739   
5740   adjusted_loc = RemoveTerminalGapsFromLocation (bsp, sfp->location, context);
5741   adjusted_len = SeqLocLen (adjusted_loc);
5742   if (adjusted_loc != NULL && adjusted_len < loc_len)
5743   {
5744     gene_sfp = SeqMgrGetOverlappingGene (sfp->location, &gene_context);
5745     if (gene_sfp != NULL 
5746         && SeqLocCompare (gene_sfp->location, sfp->location) == SLC_A_EQ_B)
5747     {
5748       gene_sfp->location = SeqLocFree (gene_sfp->location);
5749       gene_sfp->location = (SeqLocPtr) AsnIoMemCopy (adjusted_loc,
5750                                                      (AsnReadFunc) SeqLocAsnRead,
5751                                                      (AsnWriteFunc) SeqLocAsnWrite);
5752     }
5753   
5754     sfp->location = SeqLocFree (sfp->location);
5755     sfp->location = adjusted_loc;
5756     adjusted_loc = NULL;
5757     CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
5758     sfp->partial = partial5 || partial3;
5759     
5760     protbsp = BioseqFindFromSeqLoc (sfp->product);
5761 
5762     if (sfp->data.choice == SEQFEAT_CDREGION)
5763     {
5764       /* adjust frame */
5765       AdjustFrame (sfp, protbsp);
5766 
5767       /* retranslate coding region */
5768       SeqEdTranslateOneCDS (sfp, bsp, sfp->idx.entityID, Sequin_GlobalAlign2Seq);
5769               
5770       /* set partials on product */
5771       SetProductSequencePartials (protbsp, partial5, partial3);
5772     }
5773   }
5774   
5775   adjusted_loc = SeqLocFree (adjusted_loc);
5776   
5777 }
5778 
5779 static void AdjustCodingRegionsEndingInGapOnBioseq (BioseqPtr bsp, Pointer userdata)
5780 {
5781   SeqMgrFeatContext context;
5782   SeqFeatPtr        sfp;
5783   
5784   if (bsp == NULL || !ISA_na (bsp->mol) 
5785       || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4)
5786   {
5787     return;
5788   }
5789     
5790   for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &context);
5791        sfp != NULL;
5792        sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &context))
5793   {
5794     AdjustOneCodingRegionWithTerminalGapsOnBioseq (bsp, sfp, context);
5795   }
5796   for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_RNA, FEATDEF_mRNA, &context);
5797        sfp != NULL;
5798        sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_RNA, FEATDEF_mRNA, &context))
5799   {
5800     AdjustOneCodingRegionWithTerminalGapsOnBioseq (bsp, sfp, context);
5801   }
5802 }
5803 
5804 extern void AdjustCodingRegionsEndingInGap (IteM i)
5805 {
5806   BaseFormPtr bfp;
5807   SeqEntryPtr sep;
5808 
5809 #ifdef WIN_MAC
5810   bfp = currentFormDataPtr;
5811 #else
5812   bfp = GetObjectExtra (i);
5813 #endif
5814   if (bfp == NULL) return;
5815   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
5816   if (sep == NULL) return;
5817 
5818   VisitBioseqsInSep (sep, NULL, AdjustCodingRegionsEndingInGapOnBioseq);
5819   DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
5820   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
5821   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
5822 }
5823 
5824 typedef struct cdstomiscfeatform
5825 {
5826   FEATURE_FORM_BLOCK
5827   
5828   GrouP  all_or_percent_grp;
5829   DialoG string_constraint_dlg;
5830   
5831   Boolean             convert_all;
5832   FilterSetPtr        fsp;
5833   StringConstraintXPtr scp;
5834   BioseqPtr           bsp;
5835 } CDSToMiscFeatFormData, PNTR CDSToMiscFeatFormPtr;
5836 
5837 static void ConvertCDSToMiscFeatFeatureCallback (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr fsp)
5838 {
5839   CDSToMiscFeatFormPtr cmffp;
5840   Int4                 orig_len, covered_len;
5841   SeqMgrFeatContext    context;
5842   SeqEntryPtr          oldscope;
5843   CDStoMiscFeatData    cmfd;
5844 
5845   cmffp = (CDSToMiscFeatFormPtr) userdata;
5846   
5847   if (sfp == NULL || cmffp == NULL || cmffp->bsp == NULL)
5848   {
5849     return;
5850   }
5851   
5852   sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, cmffp->bsp, sfp->idx.itemID, 0, sfp, &context);
5853   if (sfp == NULL)
5854   {
5855     return;
5856   }
5857   
5858   oldscope = SeqEntrySetScope (NULL);
5859 
5860   orig_len = SeqLocLen (sfp->location);
5861   covered_len = CalculateGapCoverage (cmffp->bsp, sfp->location, context, cmffp->convert_all);
5862   if (covered_len >= orig_len / 2 || (cmffp->convert_all && covered_len > 0))
5863   {
5864     cmfd.must_have_stops = FALSE;
5865     cmfd.viral = FALSE;
5866     cmfd.opts = NULL;
5867     ConvertCDSToMiscFeat (sfp, &cmfd);
5868   }
5869   
5870   SeqEntrySetScope (oldscope);
5871 }
5872 
5873 static void ConvertGappedCodingRegionsToMiscFeatBioseqCallback (BioseqPtr bsp, Pointer userdata)
5874 {
5875   CDSToMiscFeatFormPtr cmffp;
5876   SeqEntryPtr          sep;
5877   
5878   if (bsp == NULL || !ISA_na (bsp->mol) 
5879       || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4
5880       || userdata == NULL)
5881   {
5882     return;
5883   }
5884   
5885   sep = SeqMgrGetSeqEntryForData (bsp);
5886   
5887   cmffp = (CDSToMiscFeatFormPtr) userdata;
5888   cmffp->bsp = bsp;
5889   
5890   OperateOnSeqEntryConstrainedObjects (sep, cmffp->fsp, 
5891                                        ConvertCDSToMiscFeatFeatureCallback,
5892                                        NULL, SEQFEAT_CDREGION, FEATDEF_CDS, 0, cmffp);
5893 
5894 }
5895 
5896 static void AcceptCDSToMiscFeat (ButtoN b)
5897 {
5898   CDSToMiscFeatFormPtr cmffp;
5899   SeqEntryPtr          sep;
5900   
5901   cmffp = (CDSToMiscFeatFormPtr) GetObjectExtra (b);
5902   if (cmffp == NULL)
5903   {
5904     return;
5905   }
5906   
5907   if (GetValue (cmffp->all_or_percent_grp) == 2)
5908   {
5909     cmffp->convert_all = TRUE;
5910   }
5911   else
5912   {
5913     cmffp->convert_all = FALSE;
5914   }
5915   
5916   cmffp->fsp = FilterSetNew();
5917   cmffp->fsp->scp = DialogToPointer (cmffp->string_constraint_dlg);
5918 
5919   sep = GetTopSeqEntryForEntityID (cmffp->input_entityID);
5920   if (sep == NULL) return;
5921 
5922   VisitBioseqsInSep (sep, cmffp, ConvertGappedCodingRegionsToMiscFeatBioseqCallback);
5923   DeleteMarkedObjects (cmffp->input_entityID, 0, NULL);
5924   RenormalizeNucProtSets (sep, TRUE);
5925   ObjMgrSetDirtyFlag (cmffp->input_entityID, TRUE);
5926   ObjMgrSendMsg (OM_MSG_UPDATE, cmffp->input_entityID, 0, 0);
5927   Remove (cmffp->form);  
5928 }
5929 
5930 extern void ConvertCodingRegionsWithInternalKnownGapToMiscFeat (IteM i)
5931 {
5932   BaseFormPtr          bfp;
5933   CDSToMiscFeatFormPtr cmffp;
5934   WindoW               w;
5935   GrouP                h, c;
5936   ButtoN               b;
5937 
5938 #ifdef WIN_MAC
5939   bfp = currentFormDataPtr;
5940 #else
5941   bfp = GetObjectExtra (i);
5942 #endif
5943   if (bfp == NULL) return;
5944 
5945   cmffp = (CDSToMiscFeatFormPtr) MemNew (sizeof (CDSToMiscFeatFormData));
5946   if (cmffp == NULL) return;
5947     
5948   w = FixedWindow (-50, -33, -10, -10, "Convert Coding Regions With Gaps to Misc_Feat", StdCloseWindowProc);
5949   SetObjectExtra (w, cmffp, StdCleanupFormProc);
5950   cmffp->form = (ForM) w;
5951   cmffp->input_entityID = bfp->input_entityID;
5952   h = HiddenGroup (w, -1, 0, NULL);
5953   SetGroupSpacing (h, 10, 10);
5954   
5955   cmffp->all_or_percent_grp = HiddenGroup (h, 0, 2, NULL);
5956   SetGroupSpacing (cmffp->all_or_percent_grp, 10, 10);
5957   RadioButton (cmffp->all_or_percent_grp, "Convert only when internal gap covers 50% or more of the coding region");
5958   RadioButton (cmffp->all_or_percent_grp, "Convert all coding regions with gaps (both terminal and internal)");
5959   SetValue (cmffp->all_or_percent_grp, 1);
5960   
5961   cmffp->string_constraint_dlg = StringConstraintDialogX (h, "Where feature text", FALSE);
5962 
5963   c = HiddenGroup (h, 2, 0, NULL);
5964   SetGroupSpacing (c, 10, 10);
5965   b = PushButton (c, "Accept", AcceptCDSToMiscFeat);
5966   SetObjectExtra (b, cmffp, NULL);
5967   PushButton (c, "Cancel", StdCancelButtonProc);
5968   AlignObjects (ALIGN_CENTER, (HANDLE) cmffp->all_or_percent_grp,
5969                               (HANDLE) cmffp->string_constraint_dlg,
5970                               (HANDLE) c,
5971                               NULL);
5972   RealizeWindow (w);
5973   Show (w);
5974   Select (w);
5975 }
5976 
5977 
5978 /*---------------------------------------------------------------------*/
5979 /*                                                                     */
5980 /* Apply_AddCDS () --                                                  */
5981 /*                                                                     */
5982 /*---------------------------------------------------------------------*/
5983 
5984 static void Apply_AddCDS (Uint2        entityID,
5985                           SeqEntryPtr  sep,
5986                           SeqEntryPtr  nsep,
5987                           ApplyFormPtr afp,
5988                           Boolean      suppressDups)
5989 {
5990   ByteStorePtr       bs;
5991   BioseqPtr          bsp;
5992   Char               ch;
5993   CdRegionPtr        crp;
5994   RnaRefPtr          rrp;
5995   ValNodePtr         descr;
5996   Int2               genCode;
5997   Int2               i;
5998   MolInfoPtr         mip;
5999   SeqEntryPtr        old;
6000   CharPtr            prot;
6001   ProtRefPtr         prp;
6002   SeqEntryPtr        psep;
6003   CharPtr            ptr;
6004   SeqFeatPtr         sfp;
6005   SeqIdPtr           sip;
6006   Char               str [128];
6007   ValNodePtr         vnp;
6008   SeqEntryPtr        parent_sep;
6009   SeqEntryPtr        gene_sep;
6010   SeqFeatPtr         prot_sfp, mRNA_sfp;
6011 
6012   /* If necessary then check for duplication before adding */
6013 
6014   if (suppressDups &&
6015       entityID > 0 &&
6016       AlreadyHasFeatOrDesc (sep, SEQFEAT_CDREGION, 0, 0))
6017     return;
6018 
6019   /* determine the parent of this sequence (for use when segmented) */
6020   parent_sep = NULL;
6021   if (IS_Bioseq (sep))
6022   {
6023     parent_sep = GetBestTopParentForData (entityID, sep->data.ptrvalue);
6024   }
6025   if (parent_sep == NULL)
6026   {
6027     parent_sep = sep;
6028   }
6029 
6030   /*Create a new CDS feature */
6031 
6032   genCode = SeqEntryToGeneticCode (parent_sep, NULL, NULL, 0);
6033   crp = CreateNewCdRgn (1, FALSE, genCode);
6034   if (NULL == crp)
6035     return;
6036   
6037   sfp = CreateNewFeature (nsep, NULL, SEQFEAT_CDREGION, NULL);  
6038 
6039   if (NULL == sfp)
6040     return;
6041   
6042   sfp->data.value.ptrvalue = (Pointer) crp;
6043   
6044   /* set the comment */
6045   if (afp->feature_details_data->featcomment != NULL) {
6046       sfp->comment = StringSave (afp->feature_details_data->featcomment);
6047   }
6048 
6049   /* adjust the location of the new feature */
6050   SetApplyFeatureLocation (sfp, afp);
6051   
6052   /* Fill in the fields of the new CDS feature */
6053   if (afp->feature_details_data->reading_frame < 1 
6054       || afp->feature_details_data->reading_frame > 3)
6055   {
6056     if (!SetBestFrameByLocation (sfp)) {
6057       str [0] = '\0';
6058       if (IS_Bioseq (nsep)) {
6059         bsp = (BioseqPtr) nsep->data.ptrvalue;
6060         if (bsp != NULL) {
6061           sip = SeqIdFindBest (bsp->id, 0);
6062           SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str) - 1);
6063         }
6064       }
6065       (afp->errcount)++;
6066       ValNodeCopyStr (&(afp->ambigList), 0, str);
6067     }
6068   }
6069   else
6070   {
6071     crp->frame = afp->feature_details_data->reading_frame;
6072   }
6073 
6074   /* Create corresponding protein sequence data for the CDS */
6075 
6076   bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
6077   if (NULL == bs)
6078     return;
6079 
6080   prot = BSMerge (bs, NULL);
6081   bs = BSFree (bs);
6082   if (NULL == prot)
6083     return;
6084 
6085   ptr = prot;
6086   ch = *ptr;
6087   while (ch != '\0') {
6088     *ptr = TO_UPPER (ch);
6089     ptr++;
6090     ch = *ptr;
6091   }
6092   i = (Int2) StringLen (prot);
6093   if (i > 0 && prot [i - 1] == '*') {
6094     prot [i - 1] = '\0';
6095   }
6096   bs = BSNew (1000);
6097   if (bs != NULL) {
6098     ptr = prot;
6099     BSWrite (bs, (VoidPtr) ptr, (Int4) StringLen (ptr));
6100   }
6101 
6102   /* Create the product protein Bioseq */
6103   
6104   bsp = BioseqNew ();
6105   if (NULL == bsp)
6106     return;
6107   
6108   bsp->repr = Seq_repr_raw;
6109   bsp->mol = Seq_mol_aa;
6110   bsp->seq_data_type = Seq_code_ncbieaa;
6111   bsp->seq_data = (SeqDataPtr) bs;
6112   bsp->length = BSLen (bs);
6113   bs = NULL;
6114   old = SeqEntrySetScope (sep);
6115   bsp->id = MakeNewProteinSeqId (sfp->location, NULL);
6116   SeqMgrAddToBioseqIndex (bsp);
6117   SeqEntrySetScope (old);
6118   
6119   /* Create a new SeqEntry for the Prot Bioseq */
6120   
6121   psep = SeqEntryNew ();
6122   if (NULL == psep)
6123     return;
6124   
6125   psep->choice = 1;
6126   psep->data.ptrvalue = (Pointer) bsp;
6127   SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, psep);
6128   
6129   /* Add a descriptor to the protein Bioseq */
6130   
6131   mip = MolInfoNew ();
6132   if (NULL == mip)
6133     return;
6134   
6135   mip->biomol = 8;
6136   mip->tech = 8;
6137   if (afp->noLeft && afp->noRight) {
6138     mip->completeness = 5;
6139   } else if (afp->noLeft) {
6140     mip->completeness = 3;
6141   } else if (afp->noRight) {
6142     mip->completeness = 4;
6143   }
6144   vnp = CreateNewDescriptor (psep, Seq_descr_molinfo);
6145   if (NULL == vnp)
6146     return;
6147   
6148   vnp->data.ptrvalue = (Pointer) mip;
6149   
6150   /**/
6151   
6152   descr = ExtractBioSourceAndPubs (parent_sep);
6153 
6154   AddSeqEntryToSeqEntry (parent_sep, psep, TRUE);
6155   nsep = FindNucSeqEntry (parent_sep);
6156   ReplaceBioSourceAndPubs (parent_sep, descr);
6157   SetSeqFeatProduct (sfp, bsp);
6158   
6159   /* create a full-length protein feature for the new protein sequence */
6160   if (! StringHasNoText (afp->feature_details_data->protName) 
6161       && ! StringHasNoText (afp->feature_details_data->protDesc))
6162   {
6163     prp = CreateNewProtRef (afp->feature_details_data->protName, 
6164                             afp->feature_details_data->protDesc, 
6165                             NULL, NULL);
6166   }
6167   else if (!StringHasNoText (afp->feature_details_data->protName))
6168   {
6169     prp = CreateNewProtRef (afp->feature_details_data->protName, NULL, NULL, NULL);
6170   }
6171   else if (!StringHasNoText (afp->feature_details_data->protDesc))
6172   {
6173     prp = CreateNewProtRef (NULL, afp->feature_details_data->protDesc, NULL, NULL);
6174   }
6175   else
6176   { 
6177     prp = ProtRefNew ();
6178   }
6179   
6180   if (prp != NULL) {
6181     prot_sfp = CreateNewFeature (psep, NULL, SEQFEAT_PROT, NULL);
6182     if (prot_sfp != NULL) {
6183       prot_sfp->data.value.ptrvalue = (Pointer) prp;
6184       SetSeqLocPartial (prot_sfp->location, afp->noLeft, afp->noRight);
6185       prot_sfp->partial = (afp->noLeft || afp->noRight);
6186     }
6187   }
6188   
6189   /* after the feature has been created, then adjust it for gaps */
6190   /* Note - this step may result in multiple coding regions being created. */
6191   AdjustCDSLocationsForUnknownGapsCallback (sfp, NULL);
6192 
6193   /* if requested, also add mRNA feature */
6194   if (afp->also_add_mRNA_btn != NULL && GetStatus(afp->also_add_mRNA_btn)) {
6195     mRNA_sfp = CreateNewFeature (nsep, NULL, SEQFEAT_RNA, NULL); 
6196     rrp = RnaRefNew ();
6197     if (rrp != NULL) {
6198       rrp->type = 2;
6199       if (!StringHasNoText(afp->feature_details_data->protName)) {
6200           rrp->ext.choice = 1;
6201           rrp->ext.value.ptrvalue = StringSave (afp->feature_details_data->protName);
6202       }    
6203     }
6204         mRNA_sfp->data.value.ptrvalue = rrp;
6205     SetApplyFeatureLocation (mRNA_sfp, afp);
6206     AdjustCDSLocationsForUnknownGapsCallback (mRNA_sfp, NULL);
6207   }
6208 
6209   /* Create a Gene ref feature on the nuc seq or segment */
6210   /* we can only create a feature where the sep->choice is 1 */
6211   if (sep->choice == 1)
6212   {
6213     gene_sep = sep;
6214   }
6215   else
6216   {
6217     gene_sep = nsep;
6218   }
6219 
6220   if (! StringHasNoText (afp->feature_details_data->geneName)) {
6221     if (entityID > 0 
6222         && suppressDups
6223         && AlreadyHasFeatOrDesc (gene_sep, SEQFEAT_GENE, 0, 0))
6224     {
6225       return;
6226     }
6227 
6228     ApplyGene (afp->feature_details_data->geneName, afp, gene_sep, sfp);
6229   }
6230 }
6231 
6232 static void CheckTitle (SeqEntryPtr sep, GetSamplePtr gsp)
6233 {
6234   BioseqPtr         bsp;
6235   BioseqSetPtr      bssp = NULL, part_set;
6236   SeqDescrPtr       sdp;
6237   
6238   if (sep == NULL || sep->data.ptrvalue == NULL
6239       || gsp == NULL)
6240   {
6241     return;
6242   }
6243   
6244   if (IS_Bioseq_set (sep)) {
6245     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6246     if (bssp != NULL 
6247         && bssp->_class == BioseqseqSet_class_nuc_prot 
6248         && bssp->seq_set != NULL) 
6249     {
6250       sep = bssp->seq_set;
6251     }
6252   }
6253   
6254   if (IS_Bioseq_set (sep))
6255   {
6256     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6257     if (bssp != NULL 
6258         && bssp->_class == BioseqseqSet_class_segset 
6259         && bssp->seq_set != NULL) 
6260     {
6261       /* first do parts */
6262       if (bssp->seq_set->next != NULL 
6263           && IS_Bioseq_set (bssp->seq_set->next)
6264           && bssp->seq_set->next->data.ptrvalue != NULL)
6265       {
6266         part_set = (BioseqSetPtr) bssp->seq_set->next->data.ptrvalue;
6267         if (part_set->_class == BioseqseqSet_class_parts)
6268         {
6269           for (sep = part_set->seq_set; sep != NULL; sep = sep->next)
6270           {
6271             CheckTitle (sep, gsp);
6272           }
6273         }
6274       }
6275       
6276       /* now do master */
6277       sep = bssp->seq_set;
6278     }
6279   }  
6280 
6281   if (!IS_Bioseq (sep))
6282   {
6283     return;
6284   }
6285     
6286   bsp = (BioseqPtr) sep->data.ptrvalue;
6287   sdp = bsp->descr;
6288   while (sdp != NULL && sdp->choice != Seq_descr_title)
6289   {
6290     sdp = sdp->next;
6291   }
6292   if (sdp != NULL)
6293   {
6294     gsp->num_found ++;
6295     if (gsp->sample_text == NULL)
6296     {
6297       gsp->sample_text = StringSave (sdp->data.ptrvalue);
6298     }
6299     else if (StringCmp (gsp->sample_text, sdp->data.ptrvalue) != 0)
6300     {
6301       gsp->all_same = FALSE;
6302     }
6303   }
6304   
6305   
6306 }
6307 
6308 static void ApplyOneTitle (SeqEntryPtr sep, ExistingTextPtr etp, CharPtr defline)
6309 {
6310   BioseqPtr         bsp;
6311   BioseqSetPtr      bssp, part_set;
6312   SeqDescrPtr       sdp;
6313   
6314   if (sep == NULL || sep->data.ptrvalue == NULL
6315       || StringHasNoText (defline))
6316   {
6317     return;
6318   }
6319   
6320   if (IS_Bioseq_set (sep)) {
6321     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6322     if (bssp != NULL 
6323         && bssp->_class == BioseqseqSet_class_nuc_prot 
6324         && bssp->seq_set != NULL) 
6325     {
6326       sep = bssp->seq_set;
6327     }
6328   }
6329   
6330   if (IS_Bioseq_set (sep))
6331   {
6332     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6333     if (bssp != NULL 
6334         && bssp->_class == BioseqseqSet_class_segset 
6335         && bssp->seq_set != NULL) 
6336     {
6337       /* first do parts */
6338       if (bssp->seq_set->next != NULL 
6339           && IS_Bioseq_set (bssp->seq_set->next)
6340           && bssp->seq_set->next->data.ptrvalue != NULL)
6341       {
6342         part_set = (BioseqSetPtr) bssp->seq_set->next->data.ptrvalue;
6343         if (part_set->_class == BioseqseqSet_class_parts)
6344         {
6345           for (sep = part_set->seq_set; sep != NULL; sep = sep->next)
6346           {
6347             ApplyOneTitle (sep, etp, defline);
6348           }
6349         }
6350       }
6351       
6352       /* now do master */
6353       sep = bssp->seq_set;
6354     }
6355   }    
6356 
6357   if (!IS_Bioseq (sep))
6358   {
6359     return;
6360   }
6361     
6362   bsp = (BioseqPtr) sep->data.ptrvalue;
6363   sdp = bsp->descr;
6364   while (sdp != NULL && sdp->choice != Seq_descr_title)
6365   {
6366     sdp = sdp->next;
6367   }
6368 
6369   if (sdp == NULL)
6370   {
6371     sdp = CreateNewDescriptor (sep, Seq_descr_title);
6372   }
6373   
6374   if (sdp != NULL) {
6375     sdp->data.ptrvalue = HandleExistingText (sdp->data.ptrvalue,
6376                                              StringSave (defline), etp);
6377   }
6378   
6379 }
6380 
6381 /*---------------------------------------------------------------------*/
6382 /*                                                                     */
6383 /* RealApplyBioFeatToAll () --                                         */
6384 /*                                                                     */
6385 /*---------------------------------------------------------------------*/
6386 
6387 static void RealApplyBioFeatToAll (Uint2        entityID,
6388                                                            SeqEntryPtr  sep,
6389                                                            SeqEntryPtr  nsep,
6390                                    ApplyFormPtr afp,
6391                                                            Boolean      suppressDups)
6392 
6393 {
6394   ImpFeatPtr         ifp;
6395   SeqFeatPtr         sfp = NULL;
6396   SeqFeatPtr         gene_sfp;
6397   Boolean            put_comment_on_gene = FALSE;
6398 
6399   /* Check parameters */
6400 
6401   if (sep == NULL || nsep == NULL || afp == NULL)
6402     return;
6403 
6404   /* Add a title feature */
6405 
6406   if (afp->type == CHECK_TITLE)
6407   {
6408     CheckTitle (sep, afp->gsp);
6409     return;
6410   }
6411   else if (afp->type == ADD_TITLE) 
6412   {
6413     if (entityID == 0 && SeqEntryGetTitle (sep) != NULL)
6414     {
6415       return;
6416     }
6417     ApplyOneTitle (sep, afp->etp, afp->feature_details_data->defline);
6418     return;
6419   }
6420 
6421   /* Add a CDS feature */
6422 
6423   else if (afp->type == ADD_CDS)
6424     Apply_AddCDS (entityID, sep, nsep, afp, suppressDups);
6425 
6426   /* Add an rRNA feature */
6427 
6428   else if (afp->type == ADD_RRNA) {
6429     if (suppressDups && entityID > 0 
6430         && AlreadyHasRNA (sep, afp->feature_details_data->rnaType)) {
6431       return;
6432     }
6433    
6434     sfp = CreateNewFeature (nsep, NULL, SEQFEAT_RNA, NULL);
6435     ApplyRnaTypeToSeqFeat (sfp, afp->feature_details_data->rnaType);
6436     if (! StringHasNoText (afp->feature_details_data->rnaName)) {
6437       ApplyProductToRNA (sfp, afp->feature_details_data->rnaName);
6438     }
6439     
6440     SetApplyFeatureLocation (sfp, afp);      
6441     AddToComment (sfp, afp->feature_details_data->featcomment);
6442 
6443     if (! StringHasNoText (afp->feature_details_data->geneName)) {
6444       if (entityID > 0 
6445         && suppressDups
6446               && AlreadyHasFeatOrDesc (sep, SEQFEAT_GENE, 0, 0))
6447       {
6448                return;        
6449       }
6450       ApplyGene (afp->feature_details_data->geneName, afp, nsep, sfp);
6451 
6452     }
6453   }
6454 
6455   /* Add an Import feature */
6456 
6457   else if (afp->type == ADD_IMP) {
6458     if (afp->feature_details_data->featdef_choice == FEATDEF_GENE)
6459     {
6460       put_comment_on_gene = TRUE;
6461     }
6462     else 
6463     {
6464       ifp = ImpFeatNew ();
6465       if (ifp != NULL) {
6466         ifp->key = StringSave (afp->feature_details_data->featdef_name);
6467         sfp = CreateNewFeature (nsep, NULL, SEQFEAT_IMP, NULL);
6468         if (sfp != NULL) {
6469           sfp->data.value.ptrvalue = (Pointer) ifp;
6470           SetApplyFeatureLocation (sfp, afp);
6471           if (! StringHasNoText (afp->feature_details_data->featcomment)) 
6472           {
6473             sfp->comment = StringSave (afp->feature_details_data->featcomment);
6474           }
6475           sfp->qual = DialogToPointer (afp->gbquals);
6476         }
6477       }
6478     }
6479     if (! StringHasNoText (afp->feature_details_data->geneName) 
6480                 || ! StringHasNoText (afp->feature_details_data->geneDesc)) 
6481     {
6482       if (entityID > 0 
6483           && suppressDups
6484                 && AlreadyHasFeatOrDesc (sep, SEQFEAT_GENE, 0, 0)) 
6485       {
6486               return;        
6487       }
6488       gene_sfp = ApplyGene (afp->feature_details_data->geneName, afp, nsep, sfp);
6489 
6490       if (gene_sfp != NULL && ! StringHasNoText (afp->feature_details_data->featcomment) && put_comment_on_gene)
6491       {
6492         gene_sfp->comment = StringSave (afp->feature_details_data->featcomment);
6493       }
6494     }
6495   }
6496 }
6497 
6498 /*---------------------------------------------------------------------*/
6499 /*                                                                     */
6500 /* ApplyBioFeatToRaw () --                                             */
6501 /*                                                                     */
6502 /*---------------------------------------------------------------------*/
6503 
6504 static void ApplyBioFeatToRaw (Uint2        entityID,
6505                                SeqEntryPtr  parentSep,
6506                                SeqEntryPtr  sep,
6507                                ApplyFormPtr afp,
6508                                Int2         onlythis)
6509 
6510 {
6511   BioseqPtr     bsp;
6512   BioseqSetPtr  bssp;
6513   Int2          count;
6514   SeqEntryPtr   nucSep;
6515 
6516   /* Check parameters */
6517 
6518   if (sep == NULL || afp == NULL)
6519     return;
6520 
6521   /* If it is a set then recurse until we get to the raw Bioseq */
6522 
6523   if (IS_Bioseq_set (sep)) {
6524     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6525     if (bssp != NULL) {
6526       if (onlythis != 0 && bssp->_class == BioseqseqSet_class_parts) {
6527         for (sep = bssp->seq_set, count = 1;
6528              sep != NULL && count != onlythis;
6529              sep = sep->next, count++)
6530           continue;
6531         if (sep != NULL) {
6532           ApplyBioFeatToRaw (entityID, parentSep, sep, afp, onlythis);
6533         }
6534       } else {
6535         for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
6536           ApplyBioFeatToRaw (entityID, parentSep, sep, afp, onlythis);
6537         }
6538       }
6539       return;
6540     }
6541   }
6542 
6543   /* Get the nucleotide Bioseq */
6544 
6545   nucSep = FindNucSeqEntry (sep);
6546   if (nucSep == NULL)
6547     return;
6548 
6549   bsp = (BioseqPtr) nucSep->data.ptrvalue;
6550   if (bsp == NULL)
6551     return;
6552   
6553   /* If we've got a raw Bioseq then do the apply */
6554 
6555   if (bsp->repr == Seq_repr_raw) {
6556     RealApplyBioFeatToAll (entityID, nucSep, nucSep, afp, FALSE);
6557     /*
6558     RealApplyBioFeatToAll (entityID, parentSep, nucSep, afp, FALSE);
6559     */
6560   }
6561 }
6562 
6563 /*---------------------------------------------------------------------*/
6564 /*                                                                     */
6565 /* ApplyBioFeatToAll () --                                             */
6566 /*                                                                     */
6567 /*---------------------------------------------------------------------*/
6568 
6569 static void ApplyBioFeatToAll (Uint2        entityID,
6570                                SeqEntryPtr  sep,
6571                                ApplyFormPtr afp)
6572 
6573 {
6574   BioseqSetPtr  bssp;
6575   SeqEntryPtr   nsep;
6576   Int2          onlythis;
6577   Char          str [32];
6578   Boolean       suppressDups = FALSE;
6579 
6580   /* Check parameters */
6581 
6582   if (sep == NULL || afp == NULL)
6583     return;
6584   
6585   if (afp->add_to_seq_with_like_feature != NULL)
6586   {
6587     suppressDups = ! GetStatus (afp->add_to_seq_with_like_feature);
6588   }
6589 
6590   /* If it is a set then recurse until we get to a Bioseq */
6591 
6592   if (IS_Bioseq_set (sep)) {
6593     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6594     if (bssp != NULL) {
6595       if (bssp->_class == BioseqseqSet_class_genbank || IsPopPhyEtcSet (bssp->_class)) {
6596         for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
6597           ApplyBioFeatToAll (entityID, sep, afp);
6598         }
6599         return;
6600       } else if (bssp->_class == BioseqseqSet_class_gen_prod_set) {
6601         /* just the first item */
6602         ApplyBioFeatToAll (entityID, bssp->seq_set, afp);
6603         return;
6604       }
6605     }
6606   }
6607 
6608   /* Get the nucleotide Bioseq */
6609 
6610   nsep = FindNucSeqEntry (sep);
6611   if (nsep == NULL)
6612     return;
6613 
6614   /* Apply the feature */
6615 
6616   if (afp->applyToParts != NULL && GetStatus (afp->applyToParts)) {
6617     GetTitle (afp->onlyThisPart, str, sizeof (str));
6618     if (! StrToInt (str, &onlythis)) {
6619       onlythis = 0;
6620     }
6621     ApplyBioFeatToRaw (entityID, sep, sep, afp, onlythis);
6622   } else {
6623     RealApplyBioFeatToAll (entityID, sep, nsep, afp, suppressDups);
6624   }
6625 }
6626 
6627 /*---------------------------------------------------------------------*/
6628 /*                                                                     */
6629 /* ApplyBioFeatToAll () --                                             */
6630 /*                                                                     */
6631 /*---------------------------------------------------------------------*/
6632 
6633 static void ApplyBioFeatToList (Uint2        entityID,
6634                                SeqEntryPtr  sep,
6635                                ApplyFormPtr afp,
6636                                ValNodePtr   id_list)
6637 
6638 {
6639   BioseqPtr     bsp;
6640   SeqEntryPtr   nsep, oldscope;
6641   Int2          onlythis;
6642   Char          str [32];
6643   Boolean       suppressDups = FALSE;
6644   ValNodePtr    vnp;
6645 
6646   /* Check parameters */
6647 
6648   if (sep == NULL || afp == NULL || id_list == NULL)
6649     return;
6650   
6651   if (afp->add_to_seq_with_like_feature != NULL)
6652   {
6653     suppressDups = ! GetStatus (afp->add_to_seq_with_like_feature);
6654   }
6655 
6656   oldscope = SeqEntrySetScope (sep);
6657   for (vnp = id_list; vnp != NULL; vnp = vnp->next) {
6658      bsp = BioseqFind (vnp->data.ptrvalue);
6659      if (bsp != NULL) {
6660        sep = SeqMgrGetSeqEntryForData (bsp);
6661        
6662        /* Get the nucleotide Bioseq */
6663        nsep = FindNucSeqEntry (sep);
6664        if (nsep == NULL)
6665          continue;
6666 
6667        /* Apply the feature */
6668 
6669        if (afp->applyToParts != NULL && GetStatus (afp->applyToParts)) {
6670          GetTitle (afp->onlyThisPart, str, sizeof (str));
6671          if (! StrToInt (str, &onlythis)) {
6672            onlythis = 0;
6673          }
6674          ApplyBioFeatToRaw (entityID, sep, sep, afp, onlythis);
6675        } else {
6676          RealApplyBioFeatToAll (entityID, sep, nsep, afp, suppressDups);
6677        }
6678     }
6679   }
6680 }
6681 
6682 
6683 Int2 ApplyAnnotationToAll (Int2 type, SeqEntryPtr sep,
6684                            ButtoN partialLft, ButtoN partialRgt,
6685                            TexT geneName, TexT protName, 
6686                            TexT protDesc, TexT rnaName,
6687                            TexT featcomment, TexT defline)
6688 
6689 {
6690   ApplyFormData  afd;
6691   RnaTypeData    rtd;
6692 
6693   MemSet ((Pointer) (&afd), 0, sizeof (ApplyFormData));
6694   afd.type = type;
6695   afd.errcount = 0;
6696   afd.ambigList = NULL;
6697   afd.partial5 = partialLft;
6698   afd.partial3 = partialRgt;
6699   afd.noLeft = GetStatus (afd.partial5);
6700   afd.noRight = GetStatus (afd.partial3);
6701   afd.feature_details_data = BatchApplyFeatureDetailsNew ();
6702   if (afd.feature_details_data == NULL)
6703   {
6704     return 1;
6705   }
6706   
6707   if (ADD_RRNA == type)
6708   {
6709     rtd.ncrna_class = NULL;
6710     rtd.rna_featdef = FEATDEF_rRNA;
6711     afd.feature_details_data->rnaType = &rtd;
6712   }
6713 
6714   if (geneName != NULL && ! TextHasNoText (geneName))
6715     afd.feature_details_data->geneName = SaveStringFromText (geneName);
6716   if (protName != NULL && ! TextHasNoText (protName))
6717     afd.feature_details_data->protName = SaveStringFromText (protName);
6718   if (protDesc != NULL && ! TextHasNoText (protDesc))
6719     afd.feature_details_data->protDesc = SaveStringFromText (protDesc);
6720   if (rnaName != NULL && ! TextHasNoText (rnaName))
6721     afd.feature_details_data->rnaName = SaveStringFromText (rnaName);
6722   if (featcomment != NULL && ! TextHasNoText (featcomment))
6723     afd.feature_details_data->featcomment = SaveStringFromText (featcomment);
6724   if (defline != NULL && ! TextHasNoText (defline))
6725     afd.feature_details_data->defline = SaveStringFromText (defline);
6726   ApplyBioFeatToAll (0, sep, &afd);
6727   if (afd.type == ADD_CDS) {
6728     return afd.errcount;
6729   }
6730   return 0;
6731 }
6732 
6733 static void CommonApplyToAllProcBfpInfo (Uint2 entityID,
6734                                          Uint4 itemID,
6735                                          Uint2 itemtype,
6736                                          Int2 type);
6737 
6738 static void NowReadyToApplyToAll (ApplyFormPtr afp, DialoG gbquals)
6739 
6740 {
6741   Uint2        parenttype;
6742   Pointer      parentptr;
6743   CharPtr      plural;
6744   SeqEntryPtr  sep;
6745   CharPtr      tmp;
6746   SeqEntryPtr  top;
6747   ValNodePtr   vnp;
6748   Char         path [PATH_MAX];
6749   FILE         *fp;
6750   ValNodePtr   id_list = NULL;
6751 
6752   if (afp == NULL) return;
6753   afp->gbquals = gbquals;
6754   sep = GetTopSeqEntryForEntityID (afp->input_entityID);
6755   if (sep == NULL) return;
6756   Hide (afp->form);
6757   WatchCursor ();
6758   Update ();
6759   afp->noLeft = GetStatus (afp->partial5);
6760   afp->noRight = GetStatus (afp->partial3);
6761   top = sep;
6762   if (afp->type == ADD_CDS) {
6763     GetSeqEntryParent (top, &parentptr, &parenttype);
6764   }
6765 
6766   if (afp->all_or_some_grp != NULL && GetValue (afp->all_or_some_grp) == 2) {  
6767     tmp = SaveStringFromText (afp->accession_list_txt);
6768     id_list = ParseAccessionNumberListFromString(tmp, sep);
6769     tmp = MemFree (tmp);
6770     if (id_list == NULL) {
6771       ArrowCursor();
6772       Update();
6773       Show (afp->form);
6774       return;
6775     }
6776     ApplyBioFeatToList (afp->input_entityID, sep, afp, id_list);
6777     id_list = FreeSeqIdList (id_list);
6778     tmp = MemFree (tmp);
6779   } else {
6780     ApplyBioFeatToAll (afp->input_entityID, sep, afp);
6781   }
6782   ArrowCursor ();
6783   Update ();
6784   if (afp->errcount > 0 && afp->type == ADD_CDS) {
6785     TmpNam (path);
6786     fp = FileOpen (path, "w");
6787     if (fp != NULL) {
6788       if (afp->errcount > 1) {
6789         plural = "records";
6790       } else {
6791         plural = "record";
6792       }
6793       fprintf (fp, "Possible ambiguous frames detected in %d %s\n",
6794                (int) afp->errcount, plural);
6795       for (vnp = afp->ambigList; vnp != NULL; vnp = vnp->next) {
6796         tmp = (CharPtr) vnp->data.ptrvalue;
6797         fprintf (fp, "%s\n", tmp);
6798       }
6799       FileClose (fp);
6800       LaunchGeneralTextViewer (path, "Ambiguous Frames");
6801       FileRemove (path);
6802     }
6803   }
6804   ObjMgrSetDirtyFlag (afp->input_entityID, TRUE);
6805   ObjMgrSendMsg (OM_MSG_UPDATE, afp->input_entityID, 0, 0);
6806   if (GetStatus (afp->leaveDlgUp))
6807   {
6808     afp->ambigList = ValNodeFreeData (afp->ambigList);
6809     Show (afp->form);
6810   }
6811   else
6812   {
6813     Remove (afp->form);
6814   }
6815 }
6816 
6817 typedef struct qualsform {
6818   FEATURE_FORM_BLOCK
6819 
6820   ApplyFormPtr  afp;
6821 } QualsForm, PNTR QualsFormPtr;
6822 
6823 static void CallNowReady (ButtoN b)
6824 
6825 {
6826   QualsFormPtr  qfp;
6827 
6828   qfp = (QualsFormPtr) GetObjectExtra (b);
6829   if (qfp == NULL) return;
6830   Hide (qfp->form);
6831   NowReadyToApplyToAll (qfp->afp, qfp->gbquals);
6832   Remove (qfp->form);
6833 }
6834 
6835 
6836 static void DoTheApplyToAllProc (ButtoN b)
6837 
6838 {
6839   ApplyFormPtr       afp;
6840   CharPtr            name;
6841   QualsFormPtr       qfp;
6842   WindoW             w;
6843 
6844   afp = GetObjectExtra (b);
6845   if (afp == NULL) {
6846     Remove (ParentWindow (b));
6847     return;
6848   }
6849   
6850   afp->feature_details_data = DialogToPointer (afp->feature_details_dlg);
6851   
6852   if (afp->type == ADD_IMP) {
6853     /* if gene, do not collect quals */
6854     if (afp->feature_details_data->featdef_choice != FEATDEF_GENE)
6855     {      
6856       qfp = (QualsFormPtr) MemNew (sizeof (QualsForm));
6857       if (qfp != NULL) {
6858         Hide (afp->form);
6859         Update ();
6860         name = afp->feature_details_data->featdef_name;
6861         qfp->afp = afp;
6862         w = FixedWindow (-50, -33, -10, -10, "Qualifiers", StdCloseWindowProc);
6863         SetObjectExtra (w, qfp, StdCleanupFormProc);
6864         qfp->form = (ForM) w;
6865         CreateStandardEditMenu (w);
6866         qfp->gbquals = NewCreateImportFields (w, name, NULL, FALSE);
6867         b = PushButton (w, "Okay", CallNowReady);
6868         SetObjectExtra (b, qfp, NULL);
6869         AlignObjects (ALIGN_CENTER, (HANDLE) qfp->gbquals, (HANDLE) b, NULL);
6870         RealizeWindow (w);
6871         Show (w);
6872         Select (w);
6873       }
6874     } else {
6875       NowReadyToApplyToAll (afp, NULL);
6876     }
6877   }
6878   else if (afp->type == ADD_TITLE)
6879   {
6880     afp->gsp = GetSampleNew ();
6881     afp->type = CHECK_TITLE;
6882     NowReadyToApplyToAll (afp, NULL);
6883     afp->etp = GetExistingTextHandlerInfo (afp->gsp == NULL ? 0 : afp->gsp->num_found, FALSE);
6884     afp->gsp = GetSampleFree (afp->gsp);
6885     afp->type = ADD_TITLE;
6886     if (afp->etp == NULL
6887         || afp->etp->existing_text_choice != eExistingTextChoiceCancel)
6888     {
6889       NowReadyToApplyToAll (afp, NULL);
6890     }
6891     afp->etp = MemFree (afp->etp);
6892   } else {
6893     NowReadyToApplyToAll (afp, NULL);
6894   }
6895 }
6896 
6897 static void ApplyToPartsProc (ButtoN b)
6898 
6899 {
6900   ApplyFormPtr  afp;
6901 
6902   afp = (ApplyFormPtr) GetObjectExtra (b);
6903   if (afp == NULL) return;
6904   if (GetStatus (b)) {
6905     SafeEnable (afp->onlyThisPart);
6906   } else {
6907     SafeDisable (afp->onlyThisPart);
6908   }
6909 }
6910 
6911 static void LookForParts (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
6912 
6913 {
6914   BioseqSetPtr  bssp;
6915   BoolPtr       rsult;
6916 
6917   if (IS_Bioseq_set (sep)) {
6918     bssp = (BioseqSetPtr) sep->data.ptrvalue;
6919     if (bssp != NULL && bssp->_class == BioseqseqSet_class_parts) {
6920       rsult = (BoolPtr) mydata;
6921       if (rsult != NULL) {
6922         *rsult = TRUE;
6923       }
6924     }
6925   }
6926 }
6927 
6928 extern Boolean HasPartsSet (SeqEntryPtr sep);
6929 extern Boolean HasPartsSet (SeqEntryPtr sep)
6930 
6931 {
6932   Boolean  rsult = FALSE;
6933 
6934   SeqEntryExplore (sep, (Pointer) (&rsult), LookForParts);
6935   return rsult;
6936 }
6937 
6938 static void EnableApplyCdsCoords (GrouP g)
6939 {
6940   ApplyFormPtr afp;
6941   
6942   afp = (ApplyFormPtr) GetObjectExtra (g);
6943   if (afp == NULL) return;
6944   if (GetValue (g) == 1)
6945   {
6946         Disable (afp->left_end);
6947         Disable (afp->right_end);
6948   }
6949   else
6950   {
6951         Enable (afp->left_end);
6952         Enable (afp->right_end);
6953   }
6954 }
6955 
6956 static void ApplyMessageProc (ForM f, Int2 mssg)
6957 
6958 {
6959   ApplyFormPtr  afp;
6960 
6961   afp = (ApplyFormPtr) GetObjectExtra (f);
6962   if (afp != NULL) {
6963     if (afp->appmessage != NULL) {
6964       afp->appmessage (f, mssg);
6965     }
6966   }
6967 }
6968 
6969 static void CleanupApplyToAllForm (GraphiC g, VoidPtr data)
6970 
6971 {
6972   ApplyFormPtr  afp;
6973 
6974   afp = (ApplyFormPtr) data;
6975   if (afp != NULL) {
6976     afp->feature_details_data = BatchApplyFeatureDetailsFree (afp->feature_details_data);
6977     ValNodeFreeData (afp->ambigList);
6978   }
6979   StdCleanupFormProc (g, data);
6980 }
6981 
6982 static void ChangeAllOrSome (GrouP g)
6983 {
6984   ApplyFormPtr       afp;
6985 
6986   afp = (ApplyFormPtr) GetObjectExtra (g);
6987   if (afp != NULL) {
6988     if (GetValue(g) == 1) {
6989       Disable (afp->accession_list_txt);
6990     } else {
6991       Enable (afp->accession_list_txt);
6992     }
6993   }
6994 }
6995 
6996 
6997 static void EnableApplyFeatureAccept (Pointer data)
6998 {
6999   ApplyFormPtr afp;
7000 
7001   afp = (ApplyFormPtr) data;
7002   if (afp == NULL) return;
7003 
7004   if (OkToAcceptBatchApplyFeatureDetails (afp->feature_details_dlg))
7005   {
7006     Enable (afp->accept);
7007   } 
7008   else
7009   {
7010     Disable (afp->accept);
7011   }
7012 }
7013 
7014 
7015 static void CommonApplyToAllProcBfpInfo (Uint2 entityID,
7016                                          Uint4 itemID,
7017                                          Uint2 itemtype,
7018                                          Int2 type)
7019 {
7020   ApplyFormPtr       afp;
7021   GrouP              c;
7022   GrouP              g = NULL;
7023   GrouP              h;
7024   GrouP              r2, r3, r4;
7025   SeqEntryPtr        sep;
7026   StdEditorProcsPtr  sepp;
7027   WindoW             w;
7028   GrouP              x;
7029   GrouP              parts_group = NULL;
7030   GrouP              feature_details = NULL;
7031   GrouP              indexer_only_group = NULL;
7032 
7033   sep = GetTopSeqEntryForEntityID (entityID);
7034   if (sep == NULL) return;
7035   afp = (ApplyFormPtr) MemNew (sizeof (ApplyFormData));
7036   if (afp == NULL) return;
7037   w = FixedWindow (-50, -33, -10, -10, "Automatic Processing", StdCloseWindowProc);
7038   SetObjectExtra (w, afp, CleanupApplyToAllForm);
7039   afp->form = (ForM) w;
7040   afp->formmessage = ApplyMessageProc;
7041 
7042   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
7043   if (sepp != NULL) {
7044     SetActivate (w, sepp->activateForm);
7045     afp->appmessage = sepp->handleMessages;
7046   }
7047 
7048   afp->input_entityID = entityID;
7049   afp->input_itemID = itemID;
7050   afp->input_itemtype = itemtype;
7051 
7052   h = HiddenGroup (w, -1, 0, NULL);
7053   SetGroupSpacing (h, 10, 10);
7054 
7055   afp->type = type;
7056   afp->errcount = 0;
7057 
7058   if (HasPartsSet (sep)) {
7059     parts_group = HiddenGroup (h, 1, 0, NULL);
7060     afp->applyToParts = CheckBox (parts_group, "Apply to segmented parts, not segmented sequence", ApplyToPartsProc);
7061     SetObjectExtra (afp->applyToParts, afp, NULL);
7062     x = HiddenGroup (parts_group, 2, 0, NULL);
7063     StaticPrompt (x, "Apply only to particular numbered segment", 0, dialogTextHeight, programFont, 'l');
7064     afp->onlyThisPart = DialogText (x, "", 4, NULL);
7065     Disable (afp->onlyThisPart);
7066   }
7067 
7068   afp->strand_group = NULL;
7069   afp->add_to_seq_with_like_feature = NULL;
7070   afp->also_add_mRNA_btn = NULL;
7071 
7072   if (type == ADD_CDS || type == ADD_RRNA || type == ADD_IMP) {
7073     /* create group to hold feature details */
7074     feature_details = HiddenGroup (h, -1, 0, NULL);
7075     
7076     /* group for feature completeness */
7077     g = HiddenGroup (feature_details, 2, 0, NULL);
7078     afp->partial5 = CheckBox (g, "Incomplete at 5' end", NULL);
7079     afp->partial3 = CheckBox (g, "Incomplete at 3' end", NULL);
7080     
7081     /* group for strand */
7082     afp->strand_group = HiddenGroup (feature_details, 2, 0, NULL);
7083     SetObjectExtra (afp->strand_group, afp, NULL);
7084     RadioButton (afp->strand_group, "Plus Strand");
7085     RadioButton (afp->strand_group, "Minus Strand");
7086     SetValue (afp->strand_group, 1);
7087     
7088     /* coordinates */
7089     if (indexerVersion)
7090     {
7091       indexer_only_group = HiddenGroup (feature_details, -1, 0, NULL);
7092       r2 = HiddenGroup (indexer_only_group, 5, 0, NULL);
7093       afp->use_whole_interval = HiddenGroup (r2, 0, 2, EnableApplyCdsCoords);
7094       SetObjectExtra (afp->use_whole_interval, afp, NULL);
7095       RadioButton (afp->use_whole_interval, "Use Whole Sequence Interval");
7096       RadioButton (afp->use_whole_interval, "Use these coordinates:");
7097       r3 = HiddenGroup (r2, 0, 2, NULL);
7098       StaticPrompt (r3, "", 0, dialogTextHeight, programFont, 'l');
7099       r4 = HiddenGroup (r3, 4, 0, NULL);
7100       StaticPrompt (r4, "From", 0, dialogTextHeight, programFont, 'l');
7101       afp->left_end = DialogText (r4, "1", 5, NULL);
7102       StaticPrompt (r4, "To", 0, dialogTextHeight, programFont, 'l');
7103       afp->right_end = DialogText (r4, "1", 5, NULL);
7104       SetValue (afp->use_whole_interval, 1);
7105       Disable (afp->left_end);
7106       Disable (afp->right_end);
7107       
7108       /* apply to some sequences or all sequences */
7109       afp->all_or_some_grp = HiddenGroup (indexer_only_group, 1, 0, ChangeAllOrSome);
7110       SetObjectExtra (afp->all_or_some_grp, afp, NULL);
7111       RadioButton (afp->all_or_some_grp, "Apply to all sequences");
7112       RadioButton (afp->all_or_some_grp, "Apply to sequences in this list");
7113       afp->accession_list_txt = DialogText (afp->all_or_some_grp, "", 25, NULL);
7114       SetValue (afp->all_or_some_grp, 1);
7115       ChangeAllOrSome(afp->all_or_some_grp);
7116       
7117       /* add to features that already have same */
7118       if (type == ADD_CDS)
7119       {
7120         afp->add_to_seq_with_like_feature = CheckBox (indexer_only_group, "Also add to sequences that already have a CDS", NULL);
7121         afp->also_add_mRNA_btn = CheckBox (indexer_only_group, "Also add mRNA", NULL);
7122         SetStatus (afp->also_add_mRNA_btn, FALSE);
7123       }
7124       else if (type == ADD_RRNA)
7125       {
7126         afp->add_to_seq_with_like_feature = CheckBox (indexer_only_group, "Also add to sequences that already have an rRNA", NULL);
7127       }
7128       else if (type == ADD_IMP)
7129       {
7130         afp->add_to_seq_with_like_feature = CheckBox (indexer_only_group, "Also add to sequences that already have this feature", NULL);
7131       }
7132       SafeSetStatus (afp->add_to_seq_with_like_feature, TRUE);
7133       AlignObjects (ALIGN_CENTER, (HANDLE) r2,
7134                                    (HANDLE) afp->add_to_seq_with_like_feature,
7135                                    (HANDLE) afp->also_add_mRNA_btn,
7136                                    NULL);
7137     }
7138     else
7139     {
7140       afp->use_whole_interval = NULL;
7141       afp->all_or_some_grp = NULL;
7142       afp->accession_list_txt = NULL;
7143     }
7144     
7145     AlignObjects (ALIGN_CENTER, (HANDLE) g,
7146                                 (HANDLE) afp->strand_group,
7147                                 (HANDLE) indexer_only_group,
7148                                 NULL);
7149   }
7150   afp->feature_details_dlg = BatchApplyFeatureDetailsDialog (h, type, EnableApplyFeatureAccept, afp);
7151         
7152 
7153   afp->gbquals = NULL;
7154 
7155   c = HiddenGroup (h, 4, 0, NULL);
7156   afp->accept = DefaultButton (c, "Accept", DoTheApplyToAllProc);
7157   SetObjectExtra (afp->accept, afp, NULL);
7158   PushButton (c, "Cancel", StdCancelButtonProc);
7159   afp->leaveDlgUp = CheckBox (c, "Leave Dialog Up", NULL);
7160 
7161   if (parts_group == NULL)
7162   {
7163     AlignObjects (ALIGN_CENTER, (HANDLE) c,
7164                                 (HANDLE) afp->feature_details_dlg,    
7165                                 (HANDLE) feature_details, 
7166                                 NULL);
7167   }
7168   else
7169   {
7170     AlignObjects (ALIGN_CENTER, (HANDLE) parts_group,
7171                                 (HANDLE) c, 
7172                                 (HANDLE) afp->feature_details_dlg,
7173                                 (HANDLE) feature_details, 
7174                                 NULL);
7175   }
7176   
7177   EnableApplyFeatureAccept (afp);
7178   RealizeWindow (w);
7179   Show (w);
7180   SendMessageToDialog (afp->feature_details_dlg, VIB_MSG_ENTER);
7181   Update ();
7182 }
7183 
7184 extern void CommonApplyToAllProc (BaseFormPtr bfp, Int2 type)
7185 {
7186   if (bfp == NULL) return;
7187   CommonApplyToAllProcBfpInfo (bfp->input_entityID,
7188                                bfp->input_itemID,
7189                                bfp->input_itemtype, type);
7190 }
7191 
7192 static void CommonApplyToAllProcMenuItem (IteM i, Int2 type)
7193 {
7194   BaseFormPtr bfp;
7195 
7196 #ifdef WIN_MAC
7197   bfp = currentFormDataPtr;
7198 #else
7199   bfp = GetObjectExtra (i);
7200 #endif
7201   if (bfp == NULL) return;
7202 
7203   CommonApplyToAllProc (bfp, type);
7204 }
7205 
7206 extern void ApplyTitle (IteM i)
7207 
7208 {
7209   CommonApplyToAllProcMenuItem (i, ADD_TITLE);
7210 }
7211 
7212 extern void ApplyCDS (IteM i)
7213 
7214 {
7215   CommonApplyToAllProcMenuItem (i, ADD_CDS);
7216 }
7217 
7218 extern void ApplyRRNA (IteM i)
7219 
7220 {
7221   CommonApplyToAllProcMenuItem (i, ADD_RRNA);
7222 }
7223 
7224 extern void ApplyImpFeat (IteM i)
7225 
7226 {
7227   CommonApplyToAllProcMenuItem (i, ADD_IMP);
7228 }
7229 
7230 #define SUBMISSION_PAGE   0
7231 #define CONTACT_PAGE      1
7232 #define AUTHOR_PAGE       2
7233 #define AFFILIATION_PAGE  3
7234 
7235 typedef struct submitform {
7236   FORM_MESSAGE_BLOCK
7237   GrouP           pages [4];
7238   Int2            currentPage;
7239   DialoG          tbs;
7240 
7241   GrouP           hup;
7242   GrouP           dateGrp;
7243 
7244   TexT            title;
7245   DialoG          reldate;
7246   TexT            firstname;
7247   TexT            middleinit;
7248   TexT            lastname;
7249   PopuP           suffix;
7250   DialoG          phonefaxemail;
7251   DialoG          authors;
7252   TexT            consortium;
7253   DialoG          affil;
7254 
7255   Boolean         visitedContact;
7256   Boolean         visitedAuthor;
7257 
7258   ButtoN          nextBtn;
7259   ButtoN          prevBtn;
7260   BtnActnProc     goToNext;
7261   BtnActnProc     goToPrev;
7262 } SubmitForm, PNTR SubmitFormPtr;
7263 
7264 static AuthListPtr AddConsortiumToAuthList (AuthListPtr alp, TexT consortium)
7265 
7266 {
7267   AuthorPtr    ap;
7268   ValNodePtr   names;
7269   PersonIdPtr  pid;
7270 
7271   if (TextHasNoText (consortium)) return alp;
7272   if (alp == NULL) {
7273     alp = AuthListNew ();
7274     alp->choice = 1;
7275   }
7276   pid = PersonIdNew ();
7277   if (pid == NULL) return NULL;
7278   pid->choice = 5;
7279   pid->data = SaveStringFromText (consortium);
7280   ap = AuthorNew ();
7281   if (ap == NULL) return NULL;
7282   ap->name = pid;
7283   names = ValNodeAdd (&(alp->names));
7284   names->choice = 1;
7285   names->data.ptrvalue = ap;
7286   return alp;
7287 }
7288 
7289 static void AuthListToConsortium (AuthListPtr alp, TexT consortium)
7290 
7291 {
7292   AuthorPtr    ap;
7293   ValNodePtr   names;
7294   PersonIdPtr  pid;
7295   CharPtr      str;
7296 
7297   if (alp == NULL || consortium == NULL) return;
7298   if (alp->choice != 1) return;
7299   for (names = alp->names; names != NULL; names = names->next) {
7300     ap = names->data.ptrvalue;
7301     if (ap == NULL) continue;
7302     pid = ap->name;
7303     if (pid == NULL || pid->choice != 5) continue;
7304     str = (CharPtr) pid->data;
7305     SafeSetTitle (consortium, str);
7306   }
7307 }
7308 
7309 static void SequinBlockPtrToSubmitForm (ForM f, Pointer data)
7310 
7311 {
7312   AuthorPtr       ap;
7313   DatePtr         dp;
7314   NameStdPtr      nsp;
7315   PersonIdPtr     pid;
7316   SubmitFormPtr   sbfp;
7317   SequinBlockPtr  sbp;
7318   CharPtr         str;
7319   CharPtr         txt;
7320 
7321   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7322   sbp = (SequinBlockPtr) data;
7323   if (sbfp != NULL) {
7324     if (sbp != NULL) {
7325       SafeSetTitle (sbfp->title, sbp->citsubtitle);
7326       PointerToDialog (sbfp->reldate, (Pointer) sbp->releasedate);
7327       ap = sbp->contactperson;
7328       if (ap != NULL) {
7329         pid = ap->name;
7330         if (pid != NULL && pid->choice == 2) {
7331           nsp = pid->data;
7332           if (nsp != NULL) {
7333             str = NameStdPtrToAuthorSpreadsheetString (nsp);
7334             if (str != NULL) {
7335               txt = ExtractTagListColumn (str, 0);
7336               SafeSetTitle (sbfp->firstname, txt);
7337               MemFree (txt);
7338               txt = ExtractTagListColumn (str, 1);
7339               SafeSetTitle (sbfp->middleinit, txt);
7340               MemFree (txt);
7341               txt = ExtractTagListColumn (str, 2);
7342               SafeSetTitle (sbfp->lastname, txt);
7343               MemFree (txt);
7344               txt = ExtractTagListColumn (str, 3);
7345               if (! StringHasNoText (txt)) {
7346                 SetEnumPopupByName (sbfp->suffix, name_suffix_alist, txt);
7347               }
7348               /*
7349               SafeSetTitle (sbfp->suffix, txt);
7350               */
7351               MemFree (txt);
7352               MemFree (str);
7353             }
7354           }
7355         }
7356         PointerToDialog (sbfp->phonefaxemail, (Pointer) ap->affil);
7357       }
7358       PointerToDialog (sbfp->authors, (Pointer) sbp->citsubauthors);
7359       AuthListToConsortium (sbp->citsubauthors, sbfp->consortium);
7360       PointerToDialog (sbfp->affil, (Pointer) sbp->citsubaffil);
7361       if (sbp->holduntilpublished) {
7362         SafeSetValue (sbfp->hup, 2);
7363         SafeShow (sbfp->dateGrp);
7364       } else {
7365         SafeSetValue (sbfp->hup, 1);
7366         SafeHide (sbfp->dateGrp);
7367       }
7368       sbfp->visitedAuthor = TRUE;
7369       SetValue (sbfp->tbs, 0);
7370     } else {
7371       SafeSetTitle (sbfp->title, NULL);
7372       dp = DateCurr ();
7373       if (dp != NULL) {
7374         dp->data [3] = 0; /* force to end of month */
7375         dp = DateAdvance (dp, 12);
7376         /*
7377         (dp->data [1])++;
7378         if (dp->data [2] == 2 && dp->data [3] > 28) {
7379           dp->data [3] = 28;
7380         }
7381         */
7382         PointerToDialog (sbfp->reldate, (Pointer) dp);
7383       } else {
7384         PointerToDialog (sbfp->reldate, NULL);
7385       }
7386       DateFree (dp);
7387       SafeSetTitle (sbfp->firstname, "");
7388       SafeSetTitle (sbfp->middleinit, "");
7389       SafeSetTitle (sbfp->lastname, "");
7390       PointerToDialog (sbfp->phonefaxemail, NULL);
7391       PointerToDialog (sbfp->authors, NULL);
7392       SafeSetTitle (sbfp->consortium, "");
7393       PointerToDialog (sbfp->affil, NULL);
7394       SafeSetValue (sbfp->hup, 1);
7395       SafeHide (sbfp->dateGrp);
7396       SetValue (sbfp->tbs, 0);
7397     }
7398   }
7399 }
7400 
7401 static Pointer SubmitFormToSequinBlockPtr (ForM f)
7402 
7403 {
7404   AffilPtr        affil;
7405   AuthorPtr       ap;
7406   NameStdPtr      nsp;
7407   PersonIdPtr     pid;
7408   SubmitFormPtr   sbfp;
7409   SequinBlockPtr  sbp;
7410   Char            sfx [32];
7411   Char            str [128];
7412   Uint2           suffixVal;
7413   CharPtr         txt;
7414 
7415   sbp = NULL;
7416   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7417   if (sbfp != NULL) {
7418     sbp = (SequinBlockPtr) MemNew (sizeof (SequinBlock));
7419     if (sbp != NULL) {
7420       sbp->citsubtitle = SaveStringFromTextAndStripNewlines (sbfp->title);
7421       ap = AuthorNew ();
7422       if (ap != NULL) {
7423         pid = PersonIdNew ();
7424         ap->name = pid;
7425         if (pid != NULL) {
7426           pid->choice = 2;
7427           str [0] = '\0';
7428           txt = SaveStringFromText (sbfp->firstname);
7429           StringCat (str, txt);
7430           StringCat (str, "\t");
7431           MemFree (txt);
7432           txt = SaveStringFromText (sbfp->middleinit);
7433           StringCat (str, txt);
7434           StringCat (str, "\t");
7435           MemFree (txt);
7436           txt = SaveStringFromText (sbfp->lastname);
7437           StringCat (str, txt);
7438           StringCat (str, "\t");
7439           MemFree (txt);
7440           suffixVal = GetValue (sbfp->suffix);
7441           sprintf (sfx, "%d", (int) (suffixVal - 1));
7442           StringCat (str, sfx);
7443           StringCat (str, "\n");
7444           txt = StringSave (str);
7445           nsp = AuthorSpreadsheetStringToNameStdPtr (txt);
7446           MemFree (txt);
7447           pid->data = nsp;
7448           if (nsp != NULL) {
7449             if (StringHasNoText (nsp->names [0])) {
7450               ap = AuthorFree (ap);
7451             }
7452           }
7453         }
7454         affil = (AffilPtr) DialogToPointer (sbfp->phonefaxemail);
7455         if (affil != NULL) {
7456           if (affil->choice == 2) {
7457             affil->affil = MemFree (affil->affil);
7458             affil->div = MemFree (affil->div);
7459             affil->city = MemFree (affil->city);
7460             affil->sub = MemFree (affil->sub);
7461             affil->country = MemFree (affil->country);
7462             affil->street = MemFree (affil->street);
7463             affil->postal_code = MemFree (affil->postal_code);
7464             if (affil->phone == NULL && affil->fax == NULL &&
7465                 affil->email == NULL) {
7466               affil = AffilFree (affil);
7467             }
7468           } else {
7469             affil = AffilFree (affil);
7470           }
7471         }
7472         if (affil != NULL) {
7473           if (ap == NULL) {
7474             ap = AuthorNew();
7475           }
7476           ap->affil = affil;
7477         }
7478       }
7479       sbp->contactperson = ap;
7480       sbp->citsubauthors = (AuthListPtr) DialogToPointer (sbfp->authors);
7481       sbp->citsubauthors = AddConsortiumToAuthList (sbp->citsubauthors, sbfp->consortium);
7482       sbp->citsubaffil = (AffilPtr) DialogToPointer (sbfp->affil);
7483       if (GetValue (sbfp->hup) == 2) {
7484         sbp->holduntilpublished = TRUE;
7485         sbp->releasedate = (DatePtr) DialogToPointer (sbfp->reldate);
7486       }
7487       if (sbp->contactperson == NULL &&
7488           sbp->citsubauthors == NULL &&
7489           sbp->citsubaffil == NULL) {
7490         sbp = SequinBlockFree (sbp);
7491       }
7492     }
7493   }
7494   return (Pointer) sbp;
7495 }
7496 
7497 static void SubmitBlockPtrToSubmitForm (ForM f, Pointer data)
7498 
7499 {
7500   AuthorPtr       ap;
7501   AuthListPtr     authors;
7502   ContactInfoPtr  cip;
7503   CitSubPtr       csp;
7504   DatePtr         dp;
7505   NameStdPtr      nsp;
7506   PersonIdPtr     pid;
7507   SubmitFormPtr   sbfp;
7508   SubmitBlockPtr  sbp;
7509   CharPtr         str;
7510   CharPtr         txt;
7511 
7512   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7513   sbp = (SubmitBlockPtr) data;
7514   if (sbfp != NULL) {
7515     if (sbp != NULL) {
7516       PointerToDialog (sbfp->reldate, (Pointer) sbp->reldate);
7517       cip = sbp->contact;
7518       if (cip != NULL) {
7519         ap = cip->contact;
7520         if (ap != NULL) {
7521           pid = ap->name;
7522           if (pid != NULL && pid->choice == 2) {
7523             nsp = pid->data;
7524             if (nsp != NULL) {
7525               str = NameStdPtrToAuthorSpreadsheetString (nsp);
7526               if (str != NULL) {
7527                 txt = ExtractTagListColumn (str, 0);
7528                 SafeSetTitle (sbfp->firstname, txt);
7529                 MemFree (txt);
7530                 txt = ExtractTagListColumn (str, 1);
7531                 SafeSetTitle (sbfp->middleinit, txt);
7532                 MemFree (txt);
7533                 txt = ExtractTagListColumn (str, 2);
7534                 SafeSetTitle (sbfp->lastname, txt);
7535                 MemFree (txt);
7536                 txt = ExtractTagListColumn (str, 3);
7537                 if (! StringHasNoText (txt)) {
7538                   SetEnumPopupByName (sbfp->suffix, name_suffix_alist, txt);
7539                 }
7540                 /*
7541                 SafeSetTitle (sbfp->suffix, txt);
7542                 */
7543                 MemFree (txt);
7544                 MemFree (str);
7545               }
7546             }
7547           }
7548           PointerToDialog (sbfp->phonefaxemail, (Pointer) ap->affil);
7549         }
7550       }
7551       csp = sbp->cit;
7552       if (csp != NULL) {
7553         authors = csp->authors;
7554         if (authors != NULL) {
7555           PointerToDialog (sbfp->authors, (Pointer) authors);
7556           AuthListToConsortium (authors, sbfp->consortium);
7557           PointerToDialog (sbfp->affil, (Pointer) authors->affil);
7558         }
7559       }
7560       if (sbp->hup) {
7561         SafeSetValue (sbfp->hup, 2);
7562         SafeShow (sbfp->dateGrp);
7563       } else {
7564         SafeSetValue (sbfp->hup, 1);
7565         SafeHide (sbfp->dateGrp);
7566       }
7567       sbfp->visitedAuthor = TRUE;
7568       SetValue (sbfp->tbs, 0);
7569     } else {
7570       SafeSetTitle (sbfp->title, NULL);
7571       dp = DateCurr ();
7572       if (dp != NULL) {
7573         dp->data [3] = 0; /* force to end of month */
7574         dp = DateAdvance (dp, 12);
7575         PointerToDialog (sbfp->reldate, (Pointer) dp);
7576       } else {
7577         PointerToDialog (sbfp->reldate, NULL);
7578       }
7579       DateFree (dp);
7580       SafeSetTitle (sbfp->firstname, "");
7581       SafeSetTitle (sbfp->middleinit, "");
7582       SafeSetTitle (sbfp->lastname, "");
7583       SafeSetValue (sbfp->suffix, 0);
7584       PointerToDialog (sbfp->phonefaxemail, NULL);
7585       PointerToDialog (sbfp->authors, NULL);
7586       SafeSetTitle (sbfp->consortium, "");
7587       PointerToDialog (sbfp->affil, NULL);
7588       SafeSetValue (sbfp->hup, 1);
7589       SafeHide (sbfp->dateGrp);
7590       SetValue (sbfp->tbs, 0);
7591     }
7592   }
7593 }
7594 
7595 static void TitleToSubmitBlockForm(ForM f, Pointer data)
7596 
7597 {
7598   CharPtr         man_title;
7599   SubmitFormPtr   sbfp;
7600 
7601   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7602   man_title = (CharPtr) data;
7603   if (sbfp != NULL) 
7604   {
7605     if (man_title == NULL) {
7606       SetTitle (sbfp->title, "");
7607     } else {
7608       SetTitle (sbfp->title, man_title);
7609     }
7610   }
7611 }
7612 
7613 static ValNodePtr TestSubmitForm (ForM f)
7614 
7615 {
7616   AffilPtr       affil;
7617   AuthListPtr    authors;
7618   DatePtr        dp;
7619   ValNodePtr     head;
7620   SubmitFormPtr  sbfp;
7621 
7622   head = NULL;
7623 
7624   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7625   if (sbfp != NULL) {
7626 
7627     if (TextHasNoText (sbfp->firstname)) {
7628       head = AddStringToValNodeChain (head, "first name", 1);
7629     }
7630     if (TextHasNoText (sbfp->lastname)) {
7631       head = AddStringToValNodeChain (head, "last name", 1);
7632     }
7633     affil = DialogToPointer (sbfp->phonefaxemail);
7634     if (affil != NULL) {
7635       if (StringHasNoText (affil->phone)) {
7636         head = AddStringToValNodeChain (head, "telephone number", 0);
7637       }
7638       if (StringHasNoText (affil->fax)) {
7639         head = AddStringToValNodeChain (head, "fax number", 0);
7640       }
7641       if (StringHasNoText (affil->email)) {
7642         head = AddStringToValNodeChain (head, "e-mail address", 0);
7643       }
7644     } else {
7645       head = AddStringToValNodeChain (head, "telephone number", 0);
7646       head = AddStringToValNodeChain (head, "fax number", 0);
7647       head = AddStringToValNodeChain (head, "e-mail address", 0);
7648     }
7649     affil = AffilFree (affil);
7650 
7651     if (GetValue (sbfp->hup) == 2) {
7652       dp = DialogToPointer (sbfp->reldate);
7653       if (dp == NULL) {
7654         head = AddStringToValNodeChain (head, "release date", 1);
7655       }
7656       dp = DateFree (dp);
7657     }
7658     if (TextHasNoText (sbfp->title)) {
7659       head = AddStringToValNodeChain (head, "manuscript title", 1);
7660     }
7661 
7662     authors = DialogToPointer (sbfp->authors);
7663     authors = AddConsortiumToAuthList (authors, sbfp->consortium);
7664     if (authors == NULL) {
7665       head = AddStringToValNodeChain (head, "author names", 1);
7666     }
7667     authors = AuthListFree (authors);
7668     affil = DialogToPointer (sbfp->affil);
7669     if (affil == NULL) {
7670       head = AddStringToValNodeChain (head, "affiliation", 1);
7671     }
7672     affil = AffilFree (affil);
7673 
7674   }
7675 
7676   return head;
7677 }
7678 
7679 /*
7680 static Boolean ReadSubmitBlock (ForM f, CharPtr filename)
7681 
7682 {
7683   AsnIoPtr        aip;
7684   Char            path [PATH_MAX];
7685   SubmitFormPtr   sbfp;
7686   SubmitBlockPtr  sbp;
7687 
7688   path [0] = '\0';
7689   StringNCpy_0 (path, filename, sizeof (path));
7690   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7691   if (sbfp != NULL) {
7692     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
7693       aip = AsnIoOpen (path, "r");
7694       if (aip != NULL) {
7695         sbp = SubmitBlockAsnRead (aip, NULL);
7696         AsnIoClose (aip);
7697         if (sbp != NULL) {
7698           SubmitBlockPtrToSubmitForm (f, (Pointer) sbp);
7699           sbp = SubmitBlockFree (sbp);
7700           Update ();
7701           return TRUE;
7702         }
7703       }
7704     }
7705   }
7706   return FALSE;
7707 }
7708 */
7709 
7710 
7711 static Pointer ReadNextASNObject (FILE *fp, Uint2Ptr datatypeptr, Uint2Ptr entityIDptr)
7712 {
7713   AsnIoPtr       aip;
7714   Pointer        dataptr = NULL;
7715   Int4           pos;
7716   ObjMgrPtr      omp;
7717   ObjMgrTypePtr  omtp = NULL;
7718   FileCache      fc;
7719   CharPtr        str, tag, pEnd;
7720   Char           line [4096];
7721     
7722   if (fp == NULL) {
7723       return NULL;
7724   }
7725   
7726   FileCacheSetup (&fc, fp);
7727 
7728   pos = FileCacheTell (&fc);
7729   
7730   str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
7731   while (str != NULL && StringHasNoText (str)) {
7732     str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
7733   }
7734 
7735   if (str == NULL) return NULL; /* already at end of file */
7736 
7737   if (StringStr (str, "::=") == NULL) return NULL;
7738 
7739   /* first skip past empty space at start of line */
7740   tag = str;
7741   while (*tag != '\0' && IS_WHITESP (*tag)) {
7742     tag++;
7743   }
7744   pEnd = tag;
7745   while (*pEnd != '\0' && !IS_WHITESP (*pEnd)) {
7746     pEnd++;
7747   }
7748   *pEnd = 0;
7749 
7750   omp = ObjMgrReadLock ();
7751   omtp = ObjMgrTypeFind (omp, 0, tag, NULL);
7752   ObjMgrUnlock ();
7753 
7754   if (omtp == NULL) {
7755       return NULL;
7756   }
7757   FileCacheFree (&fc, FALSE);
7758   fseek (fp, pos, SEEK_SET);
7759 
7760   aip = AsnIoNew (ASNIO_TEXT_IN, fp, NULL, NULL, NULL);
7761   aip->scan_for_start = TRUE;
7762   dataptr = (*(omtp->asnread)) (aip, NULL);
7763   pos = AsnIoTell (aip);
7764   AsnIoFree (aip, FALSE);
7765   fseek (fp, pos, SEEK_SET);
7766 
7767   if (dataptr == NULL) {
7768     ErrPostEx (SEV_ERROR, 0, 0, "Couldn't read type [%s]", omtp->asnname);
7769   } else {
7770     if (datatypeptr != NULL) {
7771       *datatypeptr = omtp->datatype;
7772     }
7773     if (entityIDptr != NULL) {
7774       *entityIDptr = ObjMgrRegister (omtp->datatype, dataptr);
7775     }
7776   }
7777   return dataptr;
7778 }
7779 
7780 
7781 static Boolean ReadSubmitBlock (ForM f, CharPtr filename)
7782 
7783 {
7784   Pointer         dataptr;
7785   Uint2           datatype;
7786   Uint2           entityID;
7787   SubmitFormPtr   sbfp;
7788   SubmitBlockPtr  sbp;
7789   SeqSubmitPtr    ssp;
7790   Char            path [PATH_MAX];
7791   CharPtr         man_title;
7792   CitGenPtr       cgp;
7793   FILE           * fp;
7794   PubdescPtr      pdp;
7795   ValNodePtr      sdp;
7796   
7797 
7798   path [0] = '\0';
7799   StringNCpy_0 (path, filename, sizeof (path));
7800   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7801   if (sbfp != NULL) {
7802     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
7803           fp = FileOpen(path, "r");
7804       dataptr = ReadNextASNObject (fp, &datatype, &entityID);
7805       sbp = NULL;
7806       man_title = NULL;
7807       while (dataptr != NULL) {
7808         if (entityID > 0) {
7809           switch (datatype) {
7810             case OBJ_SUBMIT_BLOCK :
7811               if (sbp == NULL) {
7812                 sbp = (SubmitBlockPtr) AsnIoMemCopy (dataptr,
7813                                                      (AsnReadFunc) SubmitBlockAsnRead,
7814                                                      (AsnWriteFunc) SubmitBlockAsnWrite);
7815               }
7816               break;
7817             case OBJ_SEQSUB :
7818               if (sbp == NULL) {
7819                 ssp = (SeqSubmitPtr) dataptr;
7820                 if (ssp != NULL) {
7821                   sbp = (SubmitBlockPtr) AsnIoMemCopy (ssp->sub,
7822                                                        (AsnReadFunc) SubmitBlockAsnRead,
7823                                                        (AsnWriteFunc) SubmitBlockAsnWrite);
7824                 }
7825               }
7826               break;
7827             case OBJ_SEQDESC:
7828               sdp = (ValNodePtr) dataptr;
7829               if (sdp->choice == Seq_descr_pub && sdp->data.ptrvalue != NULL && man_title == NULL) {
7830                 pdp = (PubdescPtr) sdp->data.ptrvalue;
7831                 sdp = pdp->pub;
7832                 while (sdp != NULL && sdp->choice != PUB_Gen) {
7833                   sdp = sdp->next;
7834                 }
7835                 if (sdp != NULL && sdp->data.ptrvalue != NULL) {
7836                   cgp = (CitGenPtr) sdp->data.ptrvalue;
7837                   if (StringICmp (cgp->cit, "unpublished") == 0 
7838                       && !StringHasNoText (cgp->title)) {
7839                     man_title = StringSave (cgp->title);
7840                   }
7841                 }
7842               }
7843               break;
7844             default :
7845               break;
7846           }
7847         }
7848         ObjMgrDelete (datatype, dataptr);
7849         dataptr = ReadNextASNObject (fp, &datatype, &entityID);
7850       }
7851       FileClose (fp);
7852       if (sbp != NULL || man_title != NULL) {
7853         if (sbp != NULL) {
7854           SubmitBlockPtrToSubmitForm (f, sbp);
7855           sbp = SubmitBlockFree (sbp);
7856         }
7857         if (man_title != NULL) {
7858           TitleToSubmitBlockForm (f, man_title);
7859           man_title = MemFree (man_title);
7860         }
7861         Update ();
7862         return TRUE;
7863       }
7864     }
7865   }
7866   return FALSE;
7867 }
7868 
7869 static SeqDescrPtr MakeUnpubPub (CharPtr title, AuthListPtr alp, AffilPtr affil)
7870 
7871 {
7872   CitGenPtr    cgp;
7873   PubdescPtr   pdp;
7874   ValNodePtr   pep;
7875   SeqDescrPtr  vnp;
7876 
7877   if (StringHasNoText (title) || alp == NULL) return NULL;
7878   pdp = PubdescNew ();
7879   if (pdp == NULL) return NULL;
7880   vnp = SeqDescrNew (NULL);
7881   if (vnp == NULL) return NULL;
7882   vnp->choice = Seq_descr_pub;
7883   vnp->data.ptrvalue = (Pointer) pdp;
7884   pdp->reftype = 0;
7885   pep = ValNodeNew (NULL);
7886   pdp->pub = pep;
7887   if (pep != NULL) {
7888     cgp = CitGenNew ();
7889     if (cgp != NULL) {
7890       pep->choice = PUB_Gen;
7891       pep->data.ptrvalue = cgp;
7892       cgp->cit = StringSave ("unpublished");
7893       cgp->authors = alp;
7894       if (alp != NULL) {
7895         alp->affil = affil;
7896         if (affil != NULL) {
7897           affil->phone = MemFree (affil->phone);
7898           affil->fax = MemFree (affil->fax);
7899           affil->email = MemFree (affil->email);
7900         }
7901       }
7902       cgp->title = StringSave (title);
7903     }
7904   }
7905   return vnp;
7906 }
7907 
7908 extern SubmitBlockPtr ConvertSequinBlockToSubmitBlock (SequinBlockPtr sqp);
7909 
7910 NLM_EXTERN void AsnPrintNewLine PROTO((AsnIoPtr aip));
7911 
7912 static Boolean WriteSubmitBlock (ForM f, CharPtr filename)
7913 
7914 {
7915   AffilPtr        affil;
7916   AsnIoPtr        aip;
7917   AuthListPtr     alp;
7918   Char            path [PATH_MAX];
7919   SubmitFormPtr   sbfp;
7920   SubmitBlockPtr  sbp;
7921   SeqDescrPtr     sdp;
7922   SequinBlockPtr  sqp;
7923   CharPtr         title;
7924 #ifdef WIN_MAC
7925   FILE            *fp;
7926 #endif
7927 
7928   path [0] = '\0';
7929   StringNCpy_0 (path, filename, sizeof (path));
7930   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7931   if (sbfp != NULL) {
7932     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
7933 #ifdef WIN_MAC
7934       fp = FileOpen (path, "r");
7935       if (fp != NULL) {
7936         FileClose (fp);
7937       } else {
7938         FileCreate (path, "TEXT", "ttxt");
7939       }
7940 #endif
7941       sqp = (SequinBlockPtr) SubmitFormToSequinBlockPtr (f);
7942       if (sqp != NULL) {
7943         title = StringSaveNoNull (sqp->citsubtitle);
7944         alp = AsnIoMemCopy ((Pointer) sqp->citsubauthors,
7945                             (AsnReadFunc) AuthListAsnRead,
7946                             (AsnWriteFunc) AuthListAsnWrite);
7947         affil = AsnIoMemCopy ((Pointer) sqp->citsubaffil,
7948                               (AsnReadFunc) AffilAsnRead,
7949                               (AsnWriteFunc) AffilAsnWrite);
7950         sbp = ConvertSequinBlockToSubmitBlock (sqp);
7951         if (sbp != NULL) {
7952           aip = AsnIoOpen (path, "w");
7953           if (aip != NULL) {
7954             sbp->tool = MemFree (sbp->tool);
7955             SubmitBlockAsnWrite (sbp, aip, NULL);
7956             AsnPrintNewLine (aip);
7957             sdp = MakeUnpubPub (title, alp, affil);
7958             if (sdp != NULL) {
7959               AsnIoReset (aip);
7960               SeqDescAsnWrite (sdp, aip, NULL);
7961               AsnPrintNewLine (aip);
7962               SeqDescFree (sdp);
7963             }
7964             AsnIoClose (aip);
7965             sbp = SubmitBlockFree (sbp);
7966             return TRUE;
7967           }
7968         }
7969       }
7970     }
7971   }
7972   return FALSE;
7973 }
7974 
7975 static Boolean ReadContactPage (ForM f, CharPtr filename)
7976 
7977 {
7978   AsnIoPtr        aip;
7979   AuthorPtr       ap;
7980   ContactInfoPtr  cip;
7981   NameStdPtr      nsp;
7982   Char            path [PATH_MAX];
7983   PersonIdPtr     pid;
7984   SubmitFormPtr   sbfp;
7985   CharPtr         str;
7986   CharPtr         txt;
7987 
7988   path [0] = '\0';
7989   StringNCpy_0 (path, filename, sizeof (path));
7990   sbfp = (SubmitFormPtr) GetObjectExtra (f);
7991   if (sbfp != NULL) {
7992     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
7993       aip = AsnIoOpen (path, "r");
7994       if (aip != NULL) {
7995         cip = ContactInfoAsnRead (aip, NULL);
7996         AsnIoClose (aip);
7997         if (cip != NULL) {
7998           ap = cip->contact;
7999           if (ap != NULL) {
8000             pid = ap->name;
8001             if (pid != NULL && pid->choice == 2) {
8002               nsp = pid->data;
8003               if (nsp != NULL) {
8004                 str = NameStdPtrToAuthorSpreadsheetString (nsp);
8005                 if (str != NULL) {
8006                   txt = ExtractTagListColumn (str, 0);
8007                   SafeSetTitle (sbfp->firstname, txt);
8008                   MemFree (txt);
8009                   txt = ExtractTagListColumn (str, 1);
8010                   SafeSetTitle (sbfp->middleinit, txt);
8011                   MemFree (txt);
8012                   txt = ExtractTagListColumn (str, 2);
8013                   SafeSetTitle (sbfp->lastname, txt);
8014                   MemFree (txt);
8015                   txt = ExtractTagListColumn (str, 3);
8016                   if (! StringHasNoText (txt)) {
8017                     SetEnumPopupByName (sbfp->suffix, name_suffix_alist, txt);
8018                   }
8019                   MemFree (txt);
8020                   MemFree (str);
8021                 }
8022               }
8023             }
8024             PointerToDialog (sbfp->phonefaxemail, (Pointer) ap->affil);
8025           }
8026           cip = ContactInfoFree (cip);
8027           Update ();
8028           return TRUE;
8029         }
8030       }
8031     }
8032   }
8033   return FALSE;
8034 }
8035 
8036 static Boolean WriteContactPage (ForM f, CharPtr filename)
8037 
8038 {
8039   AffilPtr        affil;
8040   AsnIoPtr        aip;
8041   AuthorPtr       ap;
8042   ContactInfoPtr  cip;
8043   NameStdPtr      nsp;
8044   Char            path [PATH_MAX];
8045   PersonIdPtr     pid;
8046   SubmitFormPtr   sbfp;
8047   Char            sfx [32];
8048   Char            str [128];
8049   Uint2           suffixVal;
8050   CharPtr         txt;
8051 #ifdef WIN_MAC
8052   FILE            *fp;
8053 #endif
8054 
8055   path [0] = '\0';
8056   StringNCpy_0 (path, filename, sizeof (path));
8057   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8058   if (sbfp != NULL) {
8059     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
8060 #ifdef WIN_MAC
8061       fp = FileOpen (path, "r");
8062       if (fp != NULL) {
8063         FileClose (fp);
8064       } else {
8065         FileCreate (path, "TEXT", "ttxt");
8066       }
8067 #endif
8068       aip = AsnIoOpen (path, "w");
8069       if (aip != NULL) {
8070         cip = ContactInfoNew ();
8071         if (cip != NULL) {
8072           ap = AuthorNew ();
8073           if (ap != NULL) {
8074             pid = PersonIdNew ();
8075             ap->name = pid;
8076             if (pid != NULL) {
8077               pid->choice = 2;
8078               str [0] = '\0';
8079               txt = SaveStringFromText (sbfp->firstname);
8080               StringCat (str, txt);
8081               StringCat (str, "\t");
8082               MemFree (txt);
8083               txt = SaveStringFromText (sbfp->middleinit);
8084               StringCat (str, txt);
8085               StringCat (str, "\t");
8086               MemFree (txt);
8087               txt = SaveStringFromText (sbfp->lastname);
8088               StringCat (str, txt);
8089               StringCat (str, "\t");
8090               MemFree (txt);
8091               suffixVal = GetValue (sbfp->suffix);
8092               sprintf (sfx, "%d", (int) (suffixVal - 1));
8093               StringCat (str, sfx);
8094               StringCat (str, "\n");
8095               txt = StringSave (str);
8096               nsp = AuthorSpreadsheetStringToNameStdPtr (txt);
8097               MemFree (txt);
8098               pid->data = nsp;
8099               if (nsp != NULL) {
8100                 if (StringHasNoText (nsp->names [0])) {
8101                   ap = AuthorFree (ap);
8102                 }
8103               }
8104             }
8105             affil = (AffilPtr) DialogToPointer (sbfp->phonefaxemail);
8106             if (affil != NULL) {
8107               if (affil->choice == 2) {
8108                 affil->affil = MemFree (affil->affil);
8109                 affil->div = MemFree (affil->div);
8110                 affil->city = MemFree (affil->city);
8111                 affil->sub = MemFree (affil->sub);
8112                 affil->country = MemFree (affil->country);
8113                 affil->street = MemFree (affil->street);
8114                 affil->postal_code = MemFree (affil->postal_code);
8115                 if (affil->phone == NULL && affil->fax == NULL &&
8116                     affil->email == NULL) {
8117                   affil = AffilFree (affil);
8118                 }
8119               } else {
8120                 affil = AffilFree (affil);
8121               }
8122             }
8123             ap->affil = affil;
8124           }
8125           cip->contact = ap;
8126           ContactInfoAsnWrite (cip, aip, NULL);
8127           AsnIoClose (aip);
8128           cip = ContactInfoFree (cip);
8129           return TRUE;
8130         }
8131       }
8132     }
8133   }
8134   return FALSE;
8135 }
8136 
8137 static Boolean ReadAuthListPage (ForM f, CharPtr filename)
8138 
8139 {
8140   AsnIoPtr       aip;
8141   AuthListPtr    alp;
8142   Char           path [PATH_MAX];
8143   SubmitFormPtr  sbfp;
8144 
8145   path [0] = '\0';
8146   StringNCpy_0 (path, filename, sizeof (path));
8147   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8148   if (sbfp != NULL) {
8149     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
8150       aip = AsnIoOpen (path, "r");
8151       if (aip != NULL) {
8152         alp = AuthListAsnRead (aip, NULL);
8153         AsnIoClose (aip);
8154         if (alp != NULL) {
8155           PointerToDialog (sbfp->authors, alp);
8156           AuthListToConsortium (alp, sbfp->consortium);
8157           alp = AuthListFree (alp);
8158           Update ();
8159           return TRUE;
8160         }
8161       }
8162     }
8163   }
8164   return FALSE;
8165 }
8166 
8167 static Boolean WriteAuthListPage (ForM f, CharPtr filename)
8168 
8169 {
8170   AsnIoPtr       aip;
8171   AuthListPtr    alp;
8172   Char           path [PATH_MAX];
8173   SubmitFormPtr  sbfp;
8174 #ifdef WIN_MAC
8175   FILE           *fp;
8176 #endif
8177 
8178   path [0] = '\0';
8179   StringNCpy_0 (path, filename, sizeof (path));
8180   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8181   if (sbfp != NULL) {
8182     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
8183 #ifdef WIN_MAC
8184       fp = FileOpen (path, "r");
8185       if (fp != NULL) {
8186         FileClose (fp);
8187       } else {
8188         FileCreate (path, "TEXT", "ttxt");
8189       }
8190 #endif
8191       aip = AsnIoOpen (path, "w");
8192       if (aip != NULL) {
8193         alp = DialogToPointer (sbfp->authors);
8194         alp = AddConsortiumToAuthList (alp, sbfp->consortium);
8195         AuthListAsnWrite (alp, aip, NULL);
8196         AsnIoClose (aip);
8197         alp = AuthListFree (alp);
8198         return TRUE;
8199       }
8200     }
8201   }
8202   return FALSE;
8203 }
8204 
8205 static Boolean ReadAffilPage (ForM f, CharPtr filename)
8206 
8207 {
8208   AffilPtr       affil;
8209   AsnIoPtr       aip;
8210   Char           path [PATH_MAX];
8211   SubmitFormPtr  sbfp;
8212 
8213   path [0] = '\0';
8214   StringNCpy_0 (path, filename, sizeof (path));
8215   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8216   if (sbfp != NULL) {
8217     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
8218       aip = AsnIoOpen (path, "r");
8219       if (aip != NULL) {
8220         affil = AffilAsnRead (aip, NULL);
8221         AsnIoClose (aip);
8222         if (affil != NULL) {
8223           affil->phone = MemFree (affil->phone);
8224           affil->fax = MemFree (affil->fax);
8225           affil->email = MemFree (affil->email);
8226           PointerToDialog (sbfp->affil, affil);
8227           affil = AffilFree (affil);
8228           Update ();
8229           return TRUE;
8230         }
8231       }
8232     }
8233   }
8234   return FALSE;
8235 }
8236 
8237 static Boolean WriteAffilPage (ForM f, CharPtr filename)
8238 
8239 {
8240   AffilPtr       affil;
8241   AsnIoPtr       aip;
8242   Char           path [PATH_MAX];
8243   SubmitFormPtr  sbfp;
8244 #ifdef WIN_MAC
8245   FILE           *fp;
8246 #endif
8247 
8248   path [0] = '\0';
8249   StringNCpy_0 (path, filename, sizeof (path));
8250   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8251   if (sbfp != NULL) {
8252     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
8253 #ifdef WIN_MAC
8254       fp = FileOpen (path, "r");
8255       if (fp != NULL) {
8256         FileClose (fp);
8257       } else {
8258         FileCreate (path, "TEXT", "ttxt");
8259       }
8260 #endif
8261       aip = AsnIoOpen (path, "w");
8262       if (aip != NULL) {
8263         affil = DialogToPointer (sbfp->affil);
8264         affil->phone = MemFree (affil->phone);
8265         affil->fax = MemFree (affil->fax);
8266         affil->email = MemFree (affil->email);
8267         AffilAsnWrite (affil, aip, NULL);
8268         AsnIoClose (aip);
8269         affil = AffilFree (affil);
8270         return TRUE;
8271       }
8272     }
8273   }
8274   return FALSE;
8275 }
8276 
8277 static Boolean ImportSubmitForm (ForM f, CharPtr filename)
8278 
8279 {
8280   SubmitFormPtr  sbfp;
8281 
8282   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8283   if (sbfp != NULL) {
8284     switch (sbfp->currentPage) {
8285       case SUBMISSION_PAGE :
8286         return ReadSubmitBlock (f, filename);
8287       case CONTACT_PAGE :
8288         return ReadContactPage (f, filename);
8289       case AUTHOR_PAGE :
8290         return ReadAuthListPage (f, filename);
8291       case AFFILIATION_PAGE :
8292         return ReadAffilPage (f, filename);
8293       default :
8294         break;
8295     }
8296   }
8297   return FALSE;
8298 }
8299 
8300 static Boolean ExportSubmitForm (ForM f, CharPtr filename)
8301 
8302 {
8303   SubmitFormPtr  sbfp;
8304 
8305   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8306   if (sbfp != NULL) {
8307     switch (sbfp->currentPage) {
8308       case SUBMISSION_PAGE :
8309         return WriteSubmitBlock (f, filename);
8310       case CONTACT_PAGE :
8311         return WriteContactPage (f, filename);
8312       case AUTHOR_PAGE :
8313         return WriteAuthListPage (f, filename);
8314       case AFFILIATION_PAGE :
8315         return WriteAffilPage (f, filename);
8316       default :
8317         break;
8318     }
8319   }
8320   return FALSE;
8321 }
8322 
8323 static void CopyContactToAuthors (SubmitFormPtr sbfp)
8324 
8325 {
8326   AuthListPtr  alp;
8327   AuthorPtr    ap;
8328   ValNodePtr   names;
8329   NameStdPtr   nsp;
8330   PersonIdPtr  pid;
8331   Char         sfx [32];
8332   Char         str [128];
8333   Uint2        suffixVal;
8334   CharPtr      txt;
8335 
8336   if (sbfp == NULL) return;
8337   ap = NULL;
8338   alp = AuthListNew ();
8339   if (alp != NULL) {
8340     alp->choice = 1;
8341     names = ValNodeNew (NULL);
8342     alp->choice = 1;
8343     alp->names = names;
8344     if (names != NULL) {
8345       ap = AuthorNew ();
8346       if (ap != NULL) {
8347         pid = PersonIdNew ();
8348         ap->name = pid;
8349         if (pid != NULL) {
8350           pid->choice = 2;
8351           str [0] = '\0';
8352           txt = SaveStringFromText (sbfp->firstname);
8353           StringCat (str, txt);
8354           StringCat (str, "\t");
8355           MemFree (txt);
8356           txt = SaveStringFromText (sbfp->middleinit);
8357           StringCat (str, txt);
8358           StringCat (str, "\t");
8359           MemFree (txt);
8360           txt = SaveStringFromText (sbfp->lastname);
8361           StringCat (str, txt);
8362           StringCat (str, "\t");
8363           MemFree (txt);
8364           suffixVal = GetValue (sbfp->suffix);
8365           sprintf (sfx, "%d", (int) (suffixVal - 1));
8366           /*
8367           txt = SaveStringFromText (sbfp->suffix);
8368           MemFree (txt);
8369           */
8370           StringCat (str, sfx);
8371           StringCat (str, "\n");
8372           txt = StringSave (str);
8373           nsp = AuthorSpreadsheetStringToNameStdPtr (txt);
8374           MemFree (txt);
8375           pid->data = nsp;
8376           if (nsp != NULL) {
8377             if (StringHasNoText (nsp->names [0])) {
8378               ap = AuthorFree (ap);
8379             }
8380           }
8381         }
8382       }
8383       names->choice = 1;
8384       names->data.ptrvalue = ap;
8385     }
8386     if (ap == NULL) {
8387       alp = AuthListFree (alp);
8388     }
8389     if (alp != NULL) {
8390        PointerToDialog (sbfp->authors, (Pointer) alp);
8391        AuthListToConsortium (alp, sbfp->consortium);
8392     }
8393   }
8394   alp = AuthListFree (alp);
8395 }
8396 
8397 static void SetSubmitterImportExportItems (SubmitFormPtr sbfp)
8398 
8399 {
8400   IteM  exportItm;
8401   IteM  importItm;
8402 
8403   if (sbfp != NULL) {
8404     importItm = FindFormMenuItem ((BaseFormPtr) sbfp, VIB_MSG_IMPORT);
8405     exportItm = FindFormMenuItem ((BaseFormPtr) sbfp, VIB_MSG_EXPORT);
8406     switch (sbfp->currentPage) {
8407       case SUBMISSION_PAGE :
8408         SafeSetTitle (importItm, "Import Submitter Info...");
8409         SafeSetTitle (exportItm, "Export Submitter Info...");
8410         SafeEnable (importItm);
8411         SafeEnable (exportItm);
8412         break;
8413       case CONTACT_PAGE :
8414         SafeSetTitle (importItm, "Import Contact...");
8415         SafeSetTitle (exportItm, "Export Contact...");
8416         SafeEnable (importItm);
8417         SafeEnable (exportItm);
8418         break;
8419       case AUTHOR_PAGE :
8420         SafeSetTitle (importItm, "Import Authors...");
8421         SafeSetTitle (exportItm, "Export Authors...");
8422         SafeEnable (importItm);
8423         SafeEnable (exportItm);
8424         break;
8425       case AFFILIATION_PAGE :
8426         SafeSetTitle (importItm, "Import Affiliation...");
8427         SafeSetTitle (exportItm, "Export Affiliation...");
8428         SafeEnable (importItm);
8429         SafeEnable (exportItm);
8430         break;
8431       default :
8432         break;
8433     }
8434   }
8435 }
8436 
8437 static void EnterSubmitPage (SubmitFormPtr sbfp, Int2 page)
8438 
8439 {
8440   AuthListPtr  alp;
8441 
8442   if (sbfp != NULL) {
8443     switch (page) {
8444       case SUBMISSION_PAGE :
8445         Select (sbfp->title);
8446         SafeSetTitle (sbfp->prevBtn, "<< Prev Form");
8447         SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8448         break;
8449       case CONTACT_PAGE :
8450         Select (sbfp->firstname);
8451         sbfp->visitedContact = TRUE;
8452         SafeSetTitle (sbfp->prevBtn, "<< Prev Page");
8453         SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8454         break;
8455       case AUTHOR_PAGE :
8456         alp = (AuthListPtr) DialogToPointer (sbfp->authors);
8457         alp = AddConsortiumToAuthList (alp, sbfp->consortium);
8458         if (sbfp->visitedContact && alp == NULL) {
8459           CopyContactToAuthors (sbfp);
8460         }
8461         AuthListFree (alp);
8462         /*
8463         if (sbfp->visitedContact && (! sbfp->visitedAuthor)) {
8464           CopyContactToAuthors (sbfp);
8465         }
8466         */
8467         SendMessageToDialog (sbfp->authors, VIB_MSG_ENTER);
8468         sbfp->visitedAuthor = TRUE;
8469         SafeSetTitle (sbfp->prevBtn, "<< Prev Page");
8470         SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8471         break;
8472       case AFFILIATION_PAGE :
8473         SendMessageToDialog (sbfp->affil, VIB_MSG_ENTER);
8474         SafeSetTitle (sbfp->prevBtn, "<< Prev Page");
8475         SafeSetTitle (sbfp->nextBtn, "Next Form >>");
8476         break;
8477       default :
8478         break;
8479     }
8480   }
8481 }
8482 
8483 static void ChangeSubmitFormPage (VoidPtr data, Int2 newval, Int2 oldval)
8484 
8485 {
8486   SubmitFormPtr  sbfp;
8487 
8488   sbfp = (SubmitFormPtr) data;
8489   if (sbfp != NULL) {
8490     sbfp->currentPage = newval;
8491     SafeHide (sbfp->pages [oldval]);
8492     Update ();
8493 #ifdef WIN_MAC
8494     EnterSubmitPage (sbfp, newval);
8495 #endif
8496     SetSubmitterImportExportItems (sbfp);
8497     SafeShow (sbfp->pages [newval]);
8498 #ifndef WIN_MAC
8499     EnterSubmitPage (sbfp, newval);
8500 #endif
8501     Update ();
8502     switch (newval) {
8503       case SUBMISSION_PAGE :
8504         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Submission Page");
8505         break;
8506       case CONTACT_PAGE :
8507         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Contact Page");
8508         break;
8509       case AUTHOR_PAGE :
8510         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Authors Page");
8511         break;
8512       case AFFILIATION_PAGE :
8513         SendHelpScrollMessage (helpForm, "Submitting Authors Form", "Affiliation Page");
8514         break;
8515       default :
8516         break;
8517     }
8518   }
8519 }
8520 
8521 static void NextSubmitFormBtn (ButtoN b)
8522 
8523 {
8524   SubmitFormPtr  sbfp;
8525   CharPtr        txt;
8526   Boolean        ok = TRUE;
8527 
8528   sbfp = (SubmitFormPtr) GetObjectExtra (b);
8529   if (sbfp != NULL) {
8530     if (sbfp->currentPage == 0)
8531     {
8532       txt = SaveStringFromText (sbfp->title);
8533       if (StringHasNoText (txt))
8534       {
8535         Message (MSG_ERROR, "You must supply a tentative title for your manuscript.");
8536         MemFree (txt);
8537         return;
8538       }
8539       MemFree (txt);
8540     }
8541     else if (sbfp->currentPage == 1)
8542     {
8543       txt = SaveStringFromText (sbfp->firstname);
8544       if (StringHasNoText (txt))
8545       {
8546         ok = FALSE;
8547       }
8548       MemFree (txt);
8549       txt = SaveStringFromText (sbfp->lastname);
8550       if (StringHasNoText (txt))
8551       {
8552         ok = FALSE;
8553       }
8554       MemFree (txt);
8555       if (!ok)
8556       {
8557         Message (MSG_ERROR, "You must supply a first and last name for the contact.");
8558         return;
8559       }
8560     }
8561     if (sbfp->currentPage < 3) {
8562       SetValue (sbfp->tbs, sbfp->currentPage + 1);
8563     } else if (sbfp->goToNext != NULL) {
8564       (sbfp->goToNext) (b);
8565     }
8566   }
8567 }
8568 
8569 static void PrevSubmitFormBtn (ButtoN b)
8570 
8571 {
8572   SubmitFormPtr  sbfp;
8573 
8574   sbfp = (SubmitFormPtr) GetObjectExtra (b);
8575   if (sbfp != NULL) {
8576     if (sbfp->currentPage > 0) {
8577       SetValue (sbfp->tbs, sbfp->currentPage - 1);
8578     } else if (sbfp->goToPrev != NULL) {
8579       (sbfp->goToPrev) (b);
8580     }
8581   }
8582 }
8583 
8584 static void ChangeHup (GrouP g)
8585 
8586 {
8587   Boolean        hup;
8588   SubmitFormPtr  sbfp;
8589 
8590   sbfp = (SubmitFormPtr) GetObjectExtra (g);
8591   if (sbfp != NULL) {
8592     hup = (Boolean) (GetValue (sbfp->hup) == 2);
8593     if (hup) {
8594       SafeShow (sbfp->dateGrp);
8595     } else {
8596       SafeHide (sbfp->dateGrp);
8597     }
8598   }
8599 }
8600 
8601 static CharPtr  submitFormTabs [] = {
8602   "Submission", "Contact", "Authors", "Affiliation", NULL
8603 };
8604 
8605 static void SubmitFormMessage (ForM f, Int2 mssg)
8606 
8607 {
8608   SubmitFormPtr  sbfp;
8609 
8610   sbfp = (SubmitFormPtr) GetObjectExtra (f);
8611   if (sbfp != NULL) {
8612     switch (mssg) {
8613       case VIB_MSG_IMPORT :
8614         ImportSubmitForm (f, NULL);
8615         break;
8616       case VIB_MSG_EXPORT :
8617         ExportSubmitForm (f, NULL);
8618         break;
8619       case VIB_MSG_CUT :
8620         StdCutTextProc (NULL);
8621         break;
8622       case VIB_MSG_COPY :
8623         StdCopyTextProc (NULL);
8624         break;
8625       case VIB_MSG_PASTE :
8626         StdPasteTextProc (NULL);
8627         break;
8628       case VIB_MSG_DELETE :
8629         StdDeleteTextProc (NULL);
8630         break;
8631       default :
8632         if (sbfp->appmessage != NULL) {
8633           sbfp->appmessage (f, mssg);
8634         }
8635         break;
8636     }
8637   }
8638 }
8639 
8640 static void InitSubmitterFormActivate (WindoW w)
8641 
8642 {
8643   SubmitFormPtr  sbfp;
8644 
8645   sbfp = (SubmitFormPtr) GetObjectExtra (w);
8646   if (sbfp != NULL) {
8647     if (sbfp->activate != NULL) {
8648       sbfp->activate (w);
8649     }
8650     SetSubmitterImportExportItems (sbfp);
8651   }
8652 }
8653 
8654 extern ForM CreateInitSubmitterForm (Int2 left, Int2 top, CharPtr title,
8655                                      BtnActnProc goToNext,
8656                                      BtnActnProc goBack,
8657                                      WndActnProc activateForm)
8658 
8659 {
8660   GrouP              c;
8661   GrouP              g;
8662   GrouP              h;
8663   GrouP              j;
8664   GrouP              m;
8665   GrouP              n;
8666   GrouP              q;
8667   SubmitFormPtr      sbfp;
8668   StdEditorProcsPtr  sepp;
8669   GrouP              t;
8670   WindoW             w;
8671   GrouP              x;
8672   GrouP              z;
8673   GrouP              g1, g2;
8674   GrouP              p;
8675   DatePtr            dp;
8676 
8677   w = NULL;
8678   sbfp = MemNew (sizeof (SubmitForm));
8679   if (sbfp != NULL) {
8680     w = FixedWindow (left, top, -10, -10, title, NULL);
8681     SetObjectExtra (w, sbfp, StdCleanupFormProc);
8682     sbfp->form = (ForM) w;
8683     sbfp->toform = SequinBlockPtrToSubmitForm;
8684     sbfp->fromform = SubmitFormToSequinBlockPtr;
8685     sbfp->testform = TestSubmitForm;
8686     sbfp->importform = ImportSubmitForm;
8687     sbfp->exportform = ExportSubmitForm;
8688     sbfp->formmessage = SubmitFormMessage;
8689 
8690 #ifndef WIN_MAC
8691     CreateSqnInitialFormMenus (w);
8692 #endif
8693 
8694     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
8695     if (sepp != NULL) {
8696       sbfp->appmessage = sepp->handleMessages;
8697     }
8698 
8699     SetGroupSpacing (w, 10, 10);
8700 
8701     j = HiddenGroup (w, -1, 0, NULL);
8702     SetGroupSpacing (j, 10, 10);
8703 
8704     sbfp->tbs = CreateFolderTabs (j, submitFormTabs, 0, 0, 0,
8705                                   SYSTEM_FOLDER_TAB,
8706                                   ChangeSubmitFormPage, (Pointer) sbfp);
8707     sbfp->currentPage = SUBMISSION_PAGE;
8708 
8709     sbfp->visitedContact = FALSE;
8710     sbfp->visitedAuthor = FALSE;
8711 
8712     h = HiddenGroup (w, 0, 0, NULL);
8713 
8714     q = HiddenGroup (h, -1, 0, NULL);
8715     SetGroupSpacing (q, 10, 20);
8716     m = HiddenGroup (q, -1, 0, NULL);
8717     g = HiddenGroup (m, 0, -4, NULL);
8718     SetGroupSpacing (g, 3, 10);
8719     StaticPrompt (g, "When may we release your sequence record?",
8720                   0, stdLineHeight, programFont, 'l');
8721     sbfp->hup = HiddenGroup (g, 0, -2, ChangeHup);
8722     SetObjectExtra (sbfp->hup, sbfp, NULL);
8723     RadioButton (sbfp->hup, "Immediately After Processing");
8724     RadioButton (sbfp->hup, "Release Date:");
8725     SetValue (sbfp->hup, 1);
8726     sbfp->dateGrp = HiddenGroup (m, -1, 0, NULL);
8727     /* StaticPrompt (sbfp->dateGrp, "Release Date: ", 0, popupMenuHeight, programFont, 'l'); */
8728 
8729     dp = DateCurr ();
8730     if (dp != NULL && dp->data[0] == 1) {
8731       sbfp->reldate = CreateDateDialogEx (sbfp->dateGrp, NULL, dp->data[1] + 1900, 10);
8732     } else {
8733       sbfp->reldate = CreateDateDialog (sbfp->dateGrp, NULL);
8734     }
8735     p = MultiLinePrompt (sbfp->dateGrp, 
8736                          "NOTE: Sequences must be released when the accession number or any portion of the sequence is published.",
8737                          25 * stdCharWidth, programFont);
8738     AlignObjects (ALIGN_CENTER, (HANDLE) sbfp->reldate, (HANDLE) p, NULL);
8739     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) sbfp->dateGrp, NULL);
8740     Hide (sbfp->dateGrp);
8741     t = HiddenGroup (q, 1, 0, NULL);
8742     StaticPrompt (t, "Tentative title for manuscript (required)", 0, 0, programFont, 'c');
8743     sbfp->title = ScrollText (t, 25, 4, programFont, TRUE, NULL);
8744     AlignObjects (ALIGN_CENTER, (HANDLE) sbfp->reldate,
8745                   (HANDLE) sbfp->title, (HANDLE) t, NULL);
8746     sbfp->pages [SUBMISSION_PAGE] = q;
8747     Hide (sbfp->pages [SUBMISSION_PAGE]);
8748 
8749     q = HiddenGroup (h, -1, 0, NULL);
8750     SetGroupSpacing (q, 10, 20);
8751     n = HiddenGroup (q, 4, 0, NULL);
8752     SetGroupSpacing (n, -1, 2);
8753     StaticPrompt (n, "First Name", 0, 0, programFont, 'c');
8754     StaticPrompt (n, "M.I.", 0, 0, programFont, 'c');
8755     StaticPrompt (n, "Last Name", 0, 0, programFont, 'c');
8756     StaticPrompt (n, "Sfx", 0, 0, programFont, 'c');
8757     sbfp->firstname = DialogText (n, "", 8, NULL);
8758     sbfp->middleinit = DialogText (n, "", 4, NULL);
8759     sbfp->lastname = DialogText (n, "", 9, NULL);
8760     /*
8761     sbfp->suffix = DialogText (n, "", 3, NULL);
8762     sbfp->suffix = PopupList (n, TRUE, SuffixPopup_Callback);
8763     */
8764     sbfp->suffix = PopupList (n, TRUE, NULL);
8765     SetObjectExtra (sbfp->suffix, sbfp, NULL);
8766     InitEnumPopup (sbfp->suffix, name_suffix_alist, NULL);
8767     SetEnumPopup (sbfp->suffix, name_suffix_alist, 0);
8768 
8769     sbfp->phonefaxemail = CreateExtAffilDialog (q, NULL, NULL, &x);
8770     Show (x);
8771     Show (sbfp->phonefaxemail);
8772     AlignObjects (ALIGN_CENTER, (HANDLE) n, (HANDLE) sbfp->phonefaxemail, NULL);
8773     sbfp->pages [CONTACT_PAGE] = q;
8774     Hide (sbfp->pages [CONTACT_PAGE]);
8775 
8776     q = HiddenGroup (h, -1, 0, NULL);
8777     SetGroupSpacing (q, 10, 20);
8778     sbfp->authors = CreateAuthorDialog (q, 3, -1);
8779     z = HiddenGroup (q, 0, 2, NULL);
8780     g1 = HiddenGroup (z, 2, 0, NULL);
8781     StaticPrompt (g1, "Consortium", 0, stdLineHeight, programFont, 'l');
8782     sbfp->consortium = DialogText (g1, "", 16, NULL);
8783     g2 = HiddenGroup (z, 1, 0, NULL);
8784     MultiLinePrompt (g2, "The consortium field should be used when a "
8785                          "consortium is responsible for the sequencing or "
8786                          "publication of the data.  Individual authors may "
8787                          "be listed along with a consortium name.",
8788                           25 * stdCharWidth, programFont);
8789     AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) g2, NULL);
8790     AlignObjects (ALIGN_CENTER, (HANDLE) sbfp->authors, (HANDLE) z, NULL);
8791     sbfp->pages [AUTHOR_PAGE] = q;
8792     Hide (sbfp->pages [AUTHOR_PAGE]);
8793 
8794     q = HiddenGroup (h, -1, 0, NULL);
8795     SetGroupSpacing (q, 10, 20);
8796     sbfp->affil = CreateExtAffilDialog (q, NULL, &g, NULL);
8797     Show (g);
8798     Show (sbfp->affil);
8799     sbfp->pages [AFFILIATION_PAGE] = q;
8800     Hide (sbfp->pages [AFFILIATION_PAGE]);
8801 
8802     c = HiddenGroup (w, 4, 0, NULL);
8803     SetGroupSpacing (c, 10, 2);
8804     sbfp->goToPrev = goBack;
8805     sbfp->prevBtn = PushButton (c, " << Prev Form ", PrevSubmitFormBtn);
8806     SetObjectExtra (sbfp->prevBtn, sbfp, NULL);
8807     sbfp->goToNext = goToNext;
8808     sbfp->nextBtn = PushButton (c, " Next Page >> ", NextSubmitFormBtn);
8809     SetObjectExtra (sbfp->nextBtn, sbfp, NULL);
8810 
8811     AlignObjects (ALIGN_CENTER,
8812                   (HANDLE) sbfp->pages [SUBMISSION_PAGE],
8813                   (HANDLE) sbfp->pages [CONTACT_PAGE],
8814                   (HANDLE) sbfp->pages [AUTHOR_PAGE],
8815                   (HANDLE) sbfp->pages [AFFILIATION_PAGE],
8816                   (HANDLE) sbfp->tbs, (HANDLE) c, NULL);
8817 
8818     RealizeWindow (w);
8819 
8820     SafeSetTitle (sbfp->prevBtn, "<< Prev Form");
8821     SafeSetTitle (sbfp->nextBtn, "Next Page >>");
8822 
8823     sbfp->activate = activateForm;
8824     SetActivate (w, InitSubmitterFormActivate);
8825 
8826     Show (sbfp->pages [sbfp->currentPage]);
8827     EnterSubmitPage (sbfp, sbfp->currentPage);
8828   }
8829   return (ForM) w;
8830 }
8831 
8832 extern void AddCodonListTotRNA (tRNAPtr trna, ValNodePtr codons)
8833 {
8834   ValNodePtr vnp;
8835   Int2       j, k, q;
8836   Char       str [8];
8837   Char       ch;
8838   Uint1      codon [4]; 
8839   Uint1      code;
8840 
8841   if (trna == NULL) return;
8842 
8843   for (j = 0; j < 6; j++) {
8844     trna->codon [j] = 255;
8845   }
8846   
8847   if (codons == NULL)
8848   {
8849     return;
8850   }
8851   
8852   for (vnp = codons, j = 0; vnp != NULL && j < 6; vnp = vnp->next) {
8853     str [0] = '\0';
8854     StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
8855     if (str [0] != '\0') {
8856       k = 0;
8857       q = 0;
8858       ch = str [k];
8859       while (ch != '\0' && q < 3) {
8860         ch = TO_UPPER (ch);
8861         if (StringChr ("ACGTU", ch) != NULL) {
8862           if (ch == 'U') {
8863             ch = 'T';
8864           }
8865           codon [q] = (Uint1) ch;
8866           q++;
8867         }
8868         k++;
8869         ch = str [k];
8870       }
8871       codon [q] = 0;
8872       if (q == 3) {
8873         code = IndexForCodon (codon, Seq_code_iupacna);
8874         if (code != INVALID_R