NCBI C Toolkit Cross Reference

C/sequin/sequin1.c


  1 /*   sequin1.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:  sequin1.c
 27 *
 28 * Author:  Jonathan Kans
 29 *
 30 * Version Creation Date:   1/22/95
 31 *
 32 * $Revision: 6.719 $
 33 *
 34 * File Description: 
 35 *
 36 * Modifications:  
 37 * --------------------------------------------------------------------------
 38 * Date     Name        Description of modification
 39 * -------  ----------  -----------------------------------------------------
 40 *
 41 *
 42 * ==========================================================================
 43 */
 44 
 45 #ifndef CODECENTER
 46 static char *date_of_compilation = __DATE__;
 47 static char *time_of_compilation = __TIME__;
 48 #else
 49 static char *date_of_compilation = "today";
 50 static char *time_of_compilation = "now";
 51 #endif
 52 
 53 #include "sequin.h"
 54 #include <vsm.h>
 55 #include <vsmutil.h>
 56 #include <valid.h>
 57 #include <fstyle.h>
 58 #include <biosrc.h>
 59 #include <seqsub.h>
 60 #include <cdrgn.h>
 61 #include <import.h>
 62 #include <medview.h>
 63 #include <bspview.h>
 64 #include <pubdesc.h>
 65 #include <toasn3.h>
 66 #include <utilpub.h>
 67 #include <tofasta.h>
 68 #include <saledit.h>
 69 #include <salstruc.h>
 70 #include <salfiles.h>
 71 #include <salign.h>
 72 #include <salsap.h>
 73 #include <salutil.h>
 74 #include <salpedit.h>
 75 #include <salpanel.h>
 76 #include <salptool.h>
 77 #include <pobutil.h>
 78 #include <accutils.h>
 79 #include <netcnfg.h>
 80 #include <objproj.h>
 81 #include <suggslp.h>
 82 #include <subutil.h>
 83 #include <explore.h>
 84 #include <actutils.h>
 85 #include <pmfapi.h>
 86 #include <accid1.h>
 87 #include <ddvopen.h>
 88 #include <dotseq.h>
 89 #include <ingenwin.h>
 90 #include <util/creaders/alnread.h>
 91 #include <sqnutils.h>
 92 #include <tax3api.h>
 93 #include <validerr.h>
 94 #include <algo/blast/api/blast_api.h>
 95 #include <findrepl.h>
 96 
 97 /* USE_SMARTNET */
 98 #ifdef USE_SMARTNET
 99 #include <smartnet.h>
100 #endif
101 
102 /* USE_ENTREZ */
103 #include <accentr.h>
104 
105 #include <objmime.h>
106 #include <mmdbapi.h>
107 /*
108 #ifndef WIN16
109 #include <cn3dentr.h>
110 #include <cn3dopen.h>
111 #endif
112 */
113 
114 #include <entrez.h>
115 
116 /* USE_LOCAL */
117 #include <lsqfetch.h>
118 
119 /* USE_MEDARCH */
120 #include <medarch.h>
121 #include <medutil.h>
122 
123 #include <mla2api.h>
124 
125 
126 #ifdef USE_SPELL
127 #include <spellapi.h>
128 #endif
129 
130 #ifdef OS_MAC
131 #include <Gestalt.h>
132 #endif
133 
134 #define SEQ_APP_VER "9.80"
135 
136 CharPtr SEQUIN_APPLICATION = SEQ_APP_VER;
137 CharPtr SEQUIN_SERVICES = NULL;
138 CharPtr SEQUIN_VERSION = NULL;
139 
140 Boolean  useDesktop = FALSE;
141 Boolean  useEntrez = FALSE;
142 Boolean  useSeqFetch = FALSE;
143 Boolean  useIdLookup = FALSE;
144 Boolean  useLocal = FALSE;
145 Boolean  useBlast = FALSE;
146 Boolean  useMedarch = FALSE;
147 Boolean  newMedarch = FALSE;
148 Boolean  useTaxon = FALSE;
149 Boolean  allowDownload = FALSE;
150 Boolean  extraServices = FALSE;
151 Boolean  indexerVersion = FALSE;
152 
153 CharPtr  genomeCenter = NULL;
154 
155 Boolean  leaveAsOldAsn = FALSE;
156 Boolean  newAlignReader = TRUE;
157 
158 SeqEntryPtr     globalsep = NULL;
159 Uint2           globalEntityID = 0;
160 Char            globalPath [PATH_MAX];
161 
162 static SequinBlockPtr  globalsbp = NULL;
163 
164 static Boolean useOldGraphicView = FALSE;
165 static Boolean useOldAlignmentView = FALSE;
166 static Boolean useOldSequenceView = FALSE;
167 /* static Boolean useUdv = FALSE; */
168 
169 static Boolean gphviewscorealigns = FALSE;
170 
171 ForM  startupForm = NULL;
172 
173 #ifdef WIN_MAC
174 Boolean  termListUp = FALSE;
175 Boolean  docSumUp = FALSE;
176 Boolean  bioseqViewUp = FALSE;
177 #endif
178 
179 #ifdef WIN_MAC
180 static IteM  openItem = NULL;
181 static IteM  closeItem = NULL;
182 static IteM  importItem = NULL;
183 static IteM  exportItem = NULL;
184 static IteM  duplicateViewItem = NULL;
185 static IteM  saveItem = NULL;
186 static IteM  saveAsItem = NULL;
187 static IteM  restoreItem = NULL;
188 static IteM  prepareItem = NULL;
189 static IteM  submitItem = NULL;
190 static IteM  loadUidItem = NULL;
191 static IteM  saveUidItem = NULL;
192 static IteM  printItem = NULL;
193 
194 static IteM  undoItem = NULL;
195 static IteM  cutItem = NULL;
196 static IteM  copyItem = NULL;
197 static IteM  pasteItem = NULL;
198 static IteM  deleteItem = NULL;
199 static IteM  duplicateItem = NULL;
200 
201 static IteM  orfItem = NULL;
202 static IteM  aluItem = NULL;
203 static IteM  targetItem = NULL;
204 static IteM  findItem = NULL;
205 static IteM  findFFItem = NULL;
206 static IteM  findGeneItem = NULL;
207 static IteM  findProtItem = NULL;
208 static IteM  findPosItem = NULL;
209 static IteM  validateItem = NULL;
210 static MenU  validateMenu = NULL;
211 static MenU  vecscreenMenu = NULL;
212 static IteM  spellItem = NULL;
213 static IteM  vectorScreenItem = NULL;
214 static IteM  cddBlastItem = NULL;
215 static MenU  cddSearchMenu = NULL;
216 static IteM  cddSearchItem = NULL;
217 static IteM  editsequenceitem = NULL;
218 static IteM  editseqalignitem = NULL;
219 static IteM  editseqsubitem = NULL;
220 static IteM  edithistoryitem = NULL;
221 static MenU  updateSeqMenu = NULL;
222 static MenU  updateSeqMenuIndexer = NULL;
223 static MenU  extendSeqMenu = NULL;
224 static MenU  addSeqMenu = NULL;
225 static IteM  featPropItem = NULL;
226 static IteM  parseFileItem = NULL;
227 static IteM  updalignitem = NULL;
228 static IteM  updalignidxitem = NULL;
229 
230 static IteM  docsumfontItem = NULL;
231 static IteM  displayfontItem = NULL;
232 static IteM  preferencesItem = NULL;
233 static IteM  clearUnusedItem = NULL;
234 static IteM  legendItem = NULL;
235 static ChoicE  queryChoice = NULL;
236 static ChoicE  neighborChoice = NULL;
237 static IteM  oldAsnItem = NULL;
238 
239 extern IteM  addSecondaryItem;
240 IteM  addSecondaryItem = NULL;
241 #endif
242 
243 static Int2  startupStyle = 0;
244 
245 static ForM  termListForm = NULL;
246 static ForM  docSumForm = NULL;
247 
248 static Boolean  loadSaveUidListOK = FALSE;
249 
250 static MedlineViewProcs    medviewprocs;
251 SeqViewProcs        seqviewprocs;
252 static EntrezGlobals       entrezglobals;
253 
254 static SeqEditViewProcs    seqedprocs;
255 static StdEditorProcs      stdedprocs;
256 static StdEditorProcs      valdtrprocs;
257 static TextViewProcs       txtviewprocs;
258 static PubdescEditProcs    pubedprocs;
259 static BioSourceEditProcs  biosrcedprocs;
260 
261 /*
262 static PRGD  prgdDict = NULL;
263 */
264 
265 static Boolean  workbenchMode = FALSE;
266 static Boolean  subtoolMode = FALSE;
267 static Boolean  stdinMode = FALSE;
268 static Boolean  bioseqsetMode = FALSE;
269 static Boolean  binseqentryMode = FALSE;
270 static Boolean  entrezMode = FALSE;
271 static Boolean  nohelpMode = FALSE;
272 static Boolean  backupMode = FALSE;
273 static Uint2    subtoolDatatype = 0;
274 static Uint2    subtoolEntityID = 0;
275 
276 static Boolean  smartnetMode = FALSE;
277 static Boolean  dirsubMode = FALSE;
278 
279 #ifdef WIN_MAC
280 static MenU     newDescMenu = NULL;
281 static MenU     newFeatMenu = NULL;
282 static MenU     advTableMenu = NULL;
283 static IteM     sucItem = NULL;
284 static MenU     newPubMenu = NULL;
285 static MenU     batchApplyMenu = NULL;
286 static MenU     batchEditMenu = NULL;
287 static MenU     specialMenu = NULL;
288 static MenU     projectsMenu = NULL;
289 static MenU     analysisMenu = NULL;
290 static Boolean  initialFormsActive = FALSE;
291 #endif
292 
293 static ForM  initSubmitForm = NULL;
294 static ForM  formatForm = NULL;
295 
296 static Int2     subtoolTimerLimit = 100;
297 static Int2     subtoolTimerCount = 0;
298 static Boolean  subtoolRecordDirty = FALSE;
299 
300 static Boolean  testLatLonSubregion = FALSE;
301 static Boolean  strictLatLonCountry = FALSE;
302 
303 
304 #ifdef USE_SMARTNET
305 static Int4 SMWriteBioseqObj(VoidPtr bio_data, SMUserDataPtr sm_usr_data, 
306                              VoidPtr data);
307 static Int4 SMReadBioseqObj(VoidPtr data, CharPtr buffer, 
308                             Int4 length, void* fd);
309 #define SMART_KEY 1313
310 #define DUMB_KEY 1314
311 #endif
312 
313 
314 static FormatBlock globalFormatBlock = {SEQ_PKG_SINGLE, SEQ_FMT_FASTA, 0, SEQ_ORIG_SUBMISSION};
315 
316 ForM  helpForm = NULL;
317 
318 static CharPtr validFailMsg =
319 "Submission failed validation test.  Continue?\n\
320 (Choose Validate in the Search menu to see errors.)";
321 
322 extern Int2 GetSequinAppParam (CharPtr section, CharPtr type, CharPtr dflt, CharPtr buf, Int2 buflen)
323 
324 {
325   Int2  rsult;
326 
327   rsult = GetAppParam ("SEQUINCUSTOM", section, type, NULL, buf, buflen);
328   if (rsult) return rsult;
329   rsult = GetAppParam ("SEQUIN", section, type, dflt, buf, buflen);
330   return rsult;
331 }
332 
333 extern Boolean WriteSequinAppParam (CharPtr section, CharPtr type, CharPtr value)
334 
335 {
336   MsgAnswer  ans;
337 
338   if (indexerVersion) {
339     if (section == NULL) {
340       section = "";
341     }
342     if (type == NULL) {
343       type = "";
344     }
345     if (value == NULL) {
346       value = "";
347     }
348     ans = Message (MSG_OKC, "Writing to local .sequinrc configuration file - [%s] %s = %s", section, type, value);
349     if (ans == ANS_CANCEL) return FALSE;
350   }
351   return SetAppParam ("SEQUIN", section, type, value);
352 }
353 
354 static Boolean SetSequinAppParam (CharPtr section, CharPtr type, CharPtr value)
355 
356 {
357   Char  tmp [32];
358 
359   if (GetAppParam ("SEQUINCUSTOM", section, type, NULL, tmp, sizeof (tmp) - 1)) {
360     return SetAppParam ("SEQUINCUSTOM", section, type, value);
361   }
362   return WriteSequinAppParam (section, type, value);
363 }
364 
365 static void SetSequinAppParamTF (CharPtr section, CharPtr type, Boolean value)
366 
367 {
368   if (value) {
369     SetSequinAppParam (section, type, "TRUE");
370   } else {
371     SetSequinAppParam (section, type, "FALSE");
372   }
373 }
374 
375 static void CheckForCookedBioseqs (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
376 
377 {
378   BoolPtr    bp;
379   BioseqPtr  bsp;
380 
381   if (sep == NULL) return;
382   if (! IS_Bioseq (sep)) return;
383   bp = (BoolPtr) mydata;
384   if (bp == NULL) return;
385   bsp = (BioseqPtr) sep->data.ptrvalue;
386   if (bsp == NULL) return;
387   if (bsp->repr != Seq_repr_raw && bsp->repr != Seq_repr_seg &&
388         bsp->repr != Seq_repr_delta && bsp->repr != Seq_repr_virtual) {
389     *bp = FALSE;
390   }
391 }
392 
393 static void TaxonValidate (SeqEntryPtr sep, ValidStructPtr vsp);
394 
395 
396 typedef enum {
397   eOkToWriteEntity_Cancel = 0,
398   eOkToWriteEntity_Continue,
399   eOkToWriteEntity_Validate
400 } EOkToWriteEntity;
401 
402 static EOkToWriteEntity GetValidationCancelContinue (ValidStructPtr vsp, Boolean allow_review)
403 {
404   WindoW w;
405   GrouP  h, c, prompts;
406   PrompT p1, p2;
407   ButtoN b;
408   ModalAcceptCancelData acd;
409   CharPtr msg, msg_format = "Reject %d, Error %d, Warning %d, Info %d";
410   EOkToWriteEntity rval = eOkToWriteEntity_Cancel;
411   
412   acd.accepted = FALSE;
413   acd.cancelled = FALSE;
414   acd.third_option = FALSE;
415   
416   w = ModalWindow(-20, -13, -10, -10, NULL);
417   h = HiddenGroup (w, -1, 0, NULL);
418   SetGroupSpacing (h, 10, 10);
419   
420   prompts = HiddenGroup (h, -1, 0, NULL);
421   SetGroupSpacing (prompts, 10, 10);
422   p1 = StaticPrompt (prompts, "Submission failed validation test with:", 0, 0, programFont, 'l');
423 
424   msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (msg_format) + 75));
425   sprintf (msg, msg_format, 
426               (int) vsp->errors [4], (int) vsp->errors [3],
427               (int) vsp->errors [2], (int) vsp->errors [1]);
428   p2 = StaticPrompt (h, msg, 0, 0, programFont, 'l'); 
429   msg = MemFree (msg);
430   AlignObjects (ALIGN_CENTER, (HANDLE) p1, (HANDLE) p2, NULL);
431 
432   c = HiddenGroup (h, 3, 0, NULL);
433   SetGroupSpacing (c, 10, 10);
434   b = PushButton (c, "Continue", ModalAcceptButton);
435   SetObjectExtra (b, &acd, NULL);
436   if (allow_review) {
437     b = PushButton (c, "Review Errors", ModalThirdOptionButton);
438     SetObjectExtra (b, &acd, NULL);
439   }
440   b = PushButton (c, "Cancel", ModalCancelButton);
441   SetObjectExtra (b, &acd, NULL);
442   AlignObjects (ALIGN_CENTER, (HANDLE) prompts, (HANDLE) c, NULL);
443   
444   Show(w); 
445   Select (w);
446   while (!acd.accepted && ! acd.cancelled && ! acd.third_option)
447   {
448     ProcessExternalEvent ();
449     Update ();
450   }
451   ProcessAnEvent ();
452   Remove (w);
453   if (acd.third_option) 
454   {
455     rval = eOkToWriteEntity_Validate;
456   } 
457   else if (acd.accepted)
458   {
459     rval = eOkToWriteEntity_Continue;
460   }
461   else
462   {
463     rval = eOkToWriteEntity_Cancel;
464   }
465   return rval;
466 }
467 
468 
469 static EOkToWriteEntity OkayToWriteTheEntity (Uint2 entityID, ForM f, Boolean allow_review)
470 
471 {
472   Boolean          allRawOrSeg = TRUE;
473   EOkToWriteEntity rval = eOkToWriteEntity_Continue;
474   Int2             errors;
475   Int2             j;
476   ErrSev           oldErrSev;
477   SeqEntryPtr      sep;
478   Char             str [32];
479   ValidStructPtr   vsp;
480 
481   if (entityID < 1) return 0;
482   sep = GetTopSeqEntryForEntityID (entityID);
483   if (sep == NULL) return 0;
484 
485   if (!FixSpecialCharacters (entityID)) return 0;
486 
487   if (GetSequinAppParam ("PREFERENCES", "ASKBEFOREVALIDATE", NULL, str, sizeof (str))) {
488     if (StringICmp (str, "TRUE") == 0) {
489       if (! (subtoolMode ||smartnetMode || backupMode) ) {
490         if (Message (MSG_YN, "Do you wish to validate this entry?") == ANS_NO) return 1;
491       }
492     }
493   }
494   WatchCursor ();
495   Update ();
496   vsp = ValidStructNew ();
497   if (vsp != NULL) {
498     /*SetChecklistValue (checklistForm, 6);*/
499     SeqEntryExplore (sep, (Pointer) (&allRawOrSeg), CheckForCookedBioseqs);
500     if (allRawOrSeg) {
501       vsp->useSeqMgrIndexes = TRUE;
502     }
503     if (indexerVersion) {
504       vsp->alwaysRequireIsoJTA = TRUE;
505       if (smartnetMode) {
506         vsp->farFetchCDSproducts = TRUE;
507         vsp->farFetchMRNAproducts = TRUE;
508       }
509     }
510     oldErrSev = ErrSetMessageLevel (SEV_MAX);
511     vsp->validateAlignments = TRUE;
512     vsp->alignFindRemoteBsp = TRUE;
513     vsp->doSeqHistAssembly = FALSE;
514     if (smartnetMode) {
515       vsp->doSeqHistAssembly = TRUE;
516       vsp->farIDsInAlignments = TRUE;
517       if (useEntrez) {
518         /*
519         LookupFarSeqIDs (sep, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
520         vsp->inferenceAccnCheck = TRUE;
521         */
522       }
523       vsp->testLatLonSubregion = testLatLonSubregion;
524       vsp->strictLatLonCountry = strictLatLonCountry;
525     }
526     for (j = 0; j < 6; j++) {
527       vsp->errors [j] = 0;
528     }
529     ValidateSeqEntry (sep, vsp);
530     if (indexerVersion && useEntrez) {
531       TaxonValidate (sep, vsp);
532     }
533     ErrSetMessageLevel (oldErrSev);
534     ErrClear ();
535     ErrShow ();
536     errors = 0;
537     if (subtoolMode || smartnetMode || backupMode) {
538       for (j = 0; j < 6; j++) {
539         errors += vsp->errors [j];
540       }
541     } else {
542       for (j = 3; j < 6; j++) {
543         errors += vsp->errors [j];
544       }
545     }
546     UseWindow ((WindoW) f);
547     if (errors > 0) {
548       ArrowCursor ();
549       Update ();
550       if (subtoolMode || smartnetMode || backupMode) {
551         rval = GetValidationCancelContinue (vsp, allow_review);
552       } else {
553         if (Message (MSG_OKC, validFailMsg) == ANS_CANCEL) {
554           rval = eOkToWriteEntity_Cancel;
555         }
556       }
557     }
558     ValidStructFree (vsp);
559   }
560   ArrowCursor ();
561   Update ();
562   return rval;
563 }
564 
565 static void ReplaceString (CharPtr PNTR target, CharPtr newstr)
566 
567 {
568   if (target == NULL) return;
569   MemFree (*target);
570   *target = StringSaveNoNull (newstr);
571 }
572 
573 static void UncompressBsps (BioseqPtr bsp, Pointer userdata)
574 
575 {
576   if (ISA_na (bsp->mol)) {
577     BioseqConvert (bsp, Seq_code_iupacna);
578   } else if (ISA_aa (bsp->mol)) {
579     BioseqConvert (bsp, Seq_code_ncbieaa);
580   }
581 }
582 
583 extern Boolean WriteTheEntityID (Uint2 entityID, CharPtr path, Boolean binary)
584 
585 {
586   AsnIoPtr       aip;
587   BioseqPtr      bsp;
588   BioseqSetPtr   bssp;
589   ObjMgrDataPtr  omdp;
590   Boolean        rsult;
591   SeqEntryPtr    sep;
592   SeqSubmitPtr   ssp;
593   Char           str [16];
594 #ifdef WIN_MAC
595   FILE           *f;
596 #endif
597 
598   rsult = FALSE;
599   if (entityID < 1) return rsult;
600   if (path == NULL || path [0] == '\0') return rsult;
601   ssp = NULL;
602   sep = NULL;
603   bsp = NULL;
604   bssp = NULL;
605   omdp = ObjMgrGetData (entityID);
606   if (omdp == NULL) return rsult;
607   WatchCursor ();
608   Update ();
609 #ifdef WIN_MAC
610   f = FileOpen (path, "r");
611   if (f != NULL) {
612     FileClose (f);
613   } else {
614     FileCreate (path, "TEXT", "ttxt");
615   }
616 #endif
617   if (GetSequinAppParam ("PREFERENCES", "UNCOMPRESS", NULL, str, sizeof (str))) {
618     if (StringICmp (str, "TRUE") == 0) {
619       sep = GetTopSeqEntryForEntityID (entityID);
620       VisitBioseqsInSep (sep, NULL, UncompressBsps);
621       /*
622       SeqEntryConvert (sep, Seq_code_iupacna);
623       SeqEntryConvert (sep, Seq_code_ncbieaa);
624       */
625     }
626   }
627   if (binseqentryMode) {
628     aip = AsnIoOpen (path, "w");
629     sep = GetTopSeqEntryForEntityID (entityID);
630     rsult = SeqEntryAsnWrite (sep, aip, NULL);
631     AsnIoClose (aip);
632     ArrowCursor ();
633     Update ();
634     return rsult;
635   }
636   sep = NULL;
637   if (binary) {
638     aip = AsnIoOpen (path, "wb");
639   } else {
640     aip = AsnIoOpen (path, "w");
641   }
642   if (aip != NULL) {
643     switch (omdp->datatype) {
644       case OBJ_SEQSUB :
645         ssp = (SeqSubmitPtr) omdp->dataptr;
646         if (ssp != NULL && ssp->datatype == 1) {
647           rsult = SeqSubmitAsnWrite (ssp, aip, NULL);
648         }
649         break;
650       case OBJ_BIOSEQ :
651         sep = (SeqEntryPtr) omdp->choice;
652         if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) {
653           if (subtoolMode || bioseqsetMode) {
654             bsp = (BioseqPtr) sep->data.ptrvalue;
655             rsult = BioseqAsnWrite (bsp, aip, NULL);
656           } else {
657             rsult = SeqEntryAsnWrite (sep, aip, NULL);
658           }
659         }
660         break;
661       case OBJ_BIOSEQSET :
662         sep =  (SeqEntryPtr) omdp->choice;
663         if (sep != NULL && sep->choice == 2 && sep->data.ptrvalue != NULL) {
664           if (subtoolMode || bioseqsetMode) {
665             bssp = (BioseqSetPtr) sep->data.ptrvalue;
666             rsult = BioseqSetAsnWrite (bssp, aip, NULL);
667           } else {
668             rsult = SeqEntryAsnWrite (sep, aip, NULL);
669           }
670         }
671         break;
672       case OBJ_SEQENTRY :
673         sep =  (SeqEntryPtr) omdp->choice;
674         if (sep != NULL) {
675           rsult = SeqEntryAsnWrite (sep, aip, NULL);
676         }
677         break;
678       default :
679         break;
680     }
681     AsnIoClose (aip);
682     if (! smartnetMode) {
683       ObjMgrSetDirtyFlag (entityID, FALSE);
684     }
685   }
686   ArrowCursor ();
687   Update ();
688   return rsult;
689 }
690 
691 static ValNodePtr ExtractGivenSeqDescrUserObject (ValNodePtr PNTR headptr, CharPtr str, CharPtr cls)
692 
693 {
694   Boolean        extract_it;
695   ValNodePtr     last = NULL, vnp;
696   ObjectIdPtr    oip;
697   UserObjectPtr  uop;
698 
699   if (headptr == NULL) return NULL;
700   vnp = *headptr;
701 
702   while (vnp != NULL) {
703     extract_it = FALSE;
704     if (vnp->choice == Seq_descr_user) {
705       uop = (UserObjectPtr) vnp->data.ptrvalue;
706       if (uop != NULL) {
707         if (StringDoesHaveText (cls)) {
708           if (StringICmp (uop->_class, cls) == 0) {
709             extract_it = TRUE;
710           }
711         }
712         if (StringDoesHaveText (str)) {
713           oip = uop->type;
714           if (oip != NULL) {
715             if (StringICmp (oip->str, str) == 0) {
716               extract_it = TRUE;
717             }
718           }
719         }
720       }
721     }
722     if (extract_it) {
723       if (last == NULL) {
724         *headptr = vnp->next;
725       } else {
726         last->next = vnp->next;
727       }
728       vnp->next = NULL;
729       return vnp;
730     } else {
731       last = vnp;
732       vnp = vnp->next;
733     }
734   }
735 
736   return NULL;
737 }
738 
739 typedef struct propgenbankdata {
740   Boolean  ask;
741   Boolean  asked;
742   Boolean  bail;
743   Boolean  changed;
744 } PropGenbankData, PNTR PropGenBankPtr;
745 
746 static void DoPropagateFromGenBankBioseqSet (
747   BioseqSetPtr seqset,
748   Pointer userdata
749 )
750 
751 {
752   BioseqPtr       bsp;
753   BioseqSetPtr    bssp;
754   PropGenBankPtr  pgp;
755   SeqEntryPtr     seqentry;
756   ValNodePtr      smartuserobj;
757   ValNodePtr      sourcedescr;
758   UserObjectPtr   uop;
759 
760   if (seqset == NULL) return;
761   if (seqset->_class != BioseqseqSet_class_genbank) return;
762   pgp = (PropGenBankPtr) userdata;
763   if (pgp == NULL) return;
764 
765   seqentry = seqset->seq_set;
766   sourcedescr = seqset->descr;
767   if (sourcedescr == NULL) return;
768 
769   /* if only descriptor is tracking user object, skip */
770   if (sourcedescr->next == NULL && sourcedescr->choice == Seq_descr_user) {
771     uop = (UserObjectPtr) sourcedescr->data.ptrvalue;
772     if (uop != NULL && StringICmp (uop->_class, "SMART_V1.0") == 0) return;
773   }
774 
775   /* optionally ask if propagation is desired */
776   if (pgp->ask) {
777     if (! pgp->asked) {
778       if (Message (MSG_YN, "Propagate descriptors from top-level set?") == ANS_NO) {
779         pgp->bail = TRUE;
780       }
781       pgp->asked = TRUE;
782     }
783   }
784   if (pgp->bail) return;
785 
786   /* disconnect descriptors from parent bssp */
787   seqset->descr = NULL;
788 
789   /* extract tracking user object */
790   smartuserobj = ExtractGivenSeqDescrUserObject (&sourcedescr, NULL, "SMART_V1.0");
791 
792   while (seqentry != NULL) {
793     if (seqentry->data.ptrvalue != NULL) {
794       if (seqentry->choice == 1) {
795         bsp = (BioseqPtr) seqentry->data.ptrvalue;
796         ValNodeLink (&(bsp->descr),
797                      AsnIoMemCopy ((Pointer) sourcedescr,
798                                    (AsnReadFunc) SeqDescrAsnRead,
799                                    (AsnWriteFunc) SeqDescrAsnWrite));
800       } else if (seqentry->choice == 2) {
801         bssp = (BioseqSetPtr) seqentry->data.ptrvalue;
802         ValNodeLink (&(bssp->descr),
803                      AsnIoMemCopy ((Pointer) sourcedescr,
804                                    (AsnReadFunc) SeqDescrAsnRead,
805                                    (AsnWriteFunc) SeqDescrAsnWrite));
806       }
807       pgp->changed = TRUE;
808     }
809     seqentry = seqentry->next;
810   }
811 
812   /* free extracted original descriptors now that copies are propagated */
813   SeqDescrFree (sourcedescr);
814 
815   /* restore tracking user object */
816   if (smartuserobj != NULL) {
817     ValNodeLink (&(seqset->descr), smartuserobj);
818   }
819 
820   /* recurse */
821   VisitSetsInSet (seqset, userdata, DoPropagateFromGenBankBioseqSet);
822 }
823 
824 extern Boolean PropagateFromGenBankBioseqSet (SeqEntryPtr sep, Boolean ask)
825 
826 {
827   BioseqSetPtr     bssp;
828   PropGenbankData  pdp;
829 
830   if (sep == NULL) return FALSE;
831   if (! IS_Bioseq_set (sep)) return FALSE;
832 
833   bssp = (BioseqSetPtr) sep->data.ptrvalue;
834   if (bssp == NULL) return FALSE;
835   if (bssp->_class != BioseqseqSet_class_genbank) return FALSE;
836 
837   MemSet ((Pointer) &pdp, 0, sizeof (PropGenbankData));
838   pdp.ask = ask;
839   pdp.asked = FALSE;
840   pdp.bail = FALSE;
841   pdp.changed = FALSE;
842 
843   DoPropagateFromGenBankBioseqSet (bssp, (Pointer) &pdp);
844 
845   return pdp.changed;
846 }
847 
848 static void ForcePropagate (IteM i)
849 
850 {
851   BaseFormPtr  bfp;
852   SeqEntryPtr  sep;
853 
854 #ifdef WIN_MAC
855   bfp = (BaseFormPtr) currentFormDataPtr;
856 #else
857   bfp = (BaseFormPtr) GetObjectExtra (i);
858 #endif
859   if (bfp == NULL) return;
860   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
861   if (sep == NULL) return;
862   PropagateFromGenBankBioseqSet (sep, FALSE);
863   NormalizeDescriptorOrder (sep);
864   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
865   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
866 }
867 
868 #define SEQUIN_EDIT_TEMP_FILE "sequinEdit.temp"
869 #define SEQUIN_EDIT_BACK_FILE "sequinEdit.back"
870 #define SEQUIN_EDIT_PREV_FILE "sequinEdit.prev"
871 #define SEQUIN_EDIT_ARCH_FILE "sequinEdit.arch"
872 
873 static void SubtoolModeTimerProc (void)
874 
875 {
876   ObjMgrDataPtr  omdp;
877 
878   subtoolTimerCount++;
879   if (subtoolTimerCount > subtoolTimerLimit) {
880     subtoolTimerCount = 0;
881     if (subtoolRecordDirty) {
882       omdp = ObjMgrGetData (subtoolEntityID);
883       if (omdp != NULL) {
884         if (WriteTheEntityID (subtoolEntityID, SEQUIN_EDIT_TEMP_FILE, FALSE)) {
885           FileRemove (SEQUIN_EDIT_PREV_FILE);
886           FileRename (SEQUIN_EDIT_BACK_FILE, SEQUIN_EDIT_PREV_FILE);
887           FileRename (SEQUIN_EDIT_TEMP_FILE, SEQUIN_EDIT_BACK_FILE);
888         } else {
889           Message (MSG_POSTERR, "Unable to save automatic temporary file");
890         }
891       }
892       subtoolRecordDirty = FALSE;
893     }
894   }
895   SequinCheckSocketsProc ();
896 }
897 
898 static Int2 LIBCALLBACK SubtoolModeMsgFunc (OMMsgStructPtr ommsp)
899 
900 {
901   switch (ommsp->message) {
902     case OM_MSG_DEL :
903     case OM_MSG_CREATE :
904     case OM_MSG_UPDATE :
905       subtoolRecordDirty = TRUE;
906       break;
907     default :
908       break;
909   }
910   return OM_MSG_RET_OK;
911 }
912 
913 static void BackupModeTimerProc (void)
914 
915 {
916   ObjMgrDataPtr  omdp;
917 
918   subtoolTimerCount++;
919   if (subtoolTimerCount > subtoolTimerLimit) {
920     subtoolTimerCount = 0;
921     if (subtoolRecordDirty && subtoolEntityID > 0) {
922       omdp = ObjMgrGetData (subtoolEntityID);
923       if (omdp != NULL) {
924         if (WriteTheEntityID (subtoolEntityID, SEQUIN_EDIT_TEMP_FILE, FALSE)) {
925           FileRemove (SEQUIN_EDIT_PREV_FILE);
926           FileRename (SEQUIN_EDIT_BACK_FILE, SEQUIN_EDIT_PREV_FILE);
927           FileRename (SEQUIN_EDIT_TEMP_FILE, SEQUIN_EDIT_BACK_FILE);
928         } else {
929           Message (MSG_POSTERR, "Unable to save automatic temporary file");
930         }
931       }
932       subtoolRecordDirty = FALSE;
933     }
934   }
935   SequinCheckSocketsProc ();
936 }
937 
938 static Int2 LIBCALLBACK BackupModeMsgFunc (OMMsgStructPtr ommsp)
939 
940 {
941   switch (ommsp->message) {
942     case OM_MSG_DEL :
943     case OM_MSG_CREATE :
944     case OM_MSG_UPDATE :
945       subtoolRecordDirty = TRUE;
946       break;
947     default :
948       break;
949   }
950   return OM_MSG_RET_OK;
951 }
952 
953 static void GetDefaultTitleFromForm (ForM f, CharPtr str, size_t maxsize, CharPtr filepath)
954 
955 {
956   Char     ch;
957   Char     dfault [64];
958   Int2     j;
959   Int2     k;
960   CharPtr  ptr;
961 
962   if (f != NULL && str != NULL && maxsize > 0) {
963     dfault [0] = '\0';
964     if (StringHasNoText (filepath)) {
965       GetTitle (f, dfault, sizeof (dfault));
966     } else {
967       ptr = StringRChr (filepath, DIRDELIMCHR);
968       if (ptr != NULL) {
969         ptr++;
970         StringNCpy_0 (dfault, ptr, sizeof (dfault));
971       } else {
972         StringNCpy_0 (dfault, filepath, sizeof (dfault));
973       }
974     }
975     j = 0;
976     k = 0;
977     ch = dfault [j];
978     while (j < sizeof (dfault) && ch != '\0') {
979       if (ch <= ' ') {
980         j++;
981       } else {
982         dfault [k] = dfault [j];
983         k++;
984         j++;
985       }
986       ch = dfault [j];
987     }
988     dfault [k] = '\0';
989 #ifdef WIN_MSWIN
990     j = 0;
991     ch = dfault [j];
992     while (j < sizeof (dfault) && ch != '\0') {
993       if (ch == '_' || IS_ALPHANUM (ch)) {
994         j++;
995         ch = dfault [j];
996       } else {
997         ch = '\0';
998       }
999     }
1000     dfault [j] = '\0';
1001 #endif
1002     StringNCpy_0 (str, dfault, maxsize);
1003   }
1004 }
1005 
1006 static CharPtr gbsub = "gb-sub@ncbi.nlm.nih.gov";
1007 static CharPtr emblsub = "datasubs@ebi.ac.uk";
1008 static CharPtr ddbjsub = "ddbjsub@ddbj.nig.ac.jp";
1009 
1010 static CharPtr gbupd = "gb-admin@ncbi.nlm.nih.gov";
1011 static CharPtr emblupd = "update@ebi.ac.uk";
1012 static CharPtr ddbjupd = "ddbjupdt@ddbj.nig.ac.jp";
1013 
1014 static CharPtr ReturnSubmissionEmailAddress (Uint2 entityID)
1015 
1016 {
1017   ObjMgrDataPtr   omdp;
1018   CharPtr         rsult;
1019   SubmitBlockPtr  sbp;
1020   SeqSubmitPtr    ssp;
1021   Char            str [32];
1022   Boolean         update = FALSE;
1023 
1024   rsult = gbsub;
1025   omdp = ObjMgrGetData (entityID);
1026   if (omdp != NULL && omdp->datatype == OBJ_SEQSUB) {
1027     ssp = (SeqSubmitPtr) omdp->dataptr;
1028     if (ssp != NULL && ssp->datatype == 1) {
1029       sbp = ssp->sub;
1030       if (sbp != NULL && sbp->subtype == 2) {
1031         update = TRUE;
1032       }
1033     }
1034   }
1035   if (GetAppParam ("SEQUIN", "PREFERENCES", "DATABASE", NULL, str, sizeof (str))) {
1036     if (StringICmp (str, "GenBank") == 0) {
1037       if (update) {
1038         rsult = gbupd;
1039       } else {
1040         rsult = gbsub;
1041       }
1042     } else if (StringICmp (str, "EMBL") == 0) {
1043       if (update) {
1044         rsult = emblupd;
1045       } else {
1046         rsult = emblsub;
1047       }
1048     } else if (StringICmp (str, "DDBJ") == 0) {
1049       if (update) {
1050         rsult = ddbjupd;
1051       } else {
1052         rsult = ddbjsub;
1053       }
1054     }
1055   }
1056   return rsult;
1057 }
1058 
1059 static void DoRemoveAlignmentFromRecord (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
1060 
1061 {
1062   BioseqPtr     bsp;
1063   BioseqSetPtr  bssp;
1064   SeqAnnotPtr   nextsap;
1065   Pointer PNTR  prevsap;
1066   SeqAnnotPtr   sap;
1067 
1068   if (IS_Bioseq (sep)) {
1069     bsp = (BioseqPtr) sep->data.ptrvalue;
1070     sap = bsp->annot;
1071     prevsap = (Pointer PNTR) &(bsp->annot);
1072   } else if (IS_Bioseq_set (sep)) {
1073     bssp = (BioseqSetPtr) sep->data.ptrvalue;
1074     sap = bssp->annot;
1075     prevsap = (Pointer PNTR) &(bssp->annot);
1076   } else return;
1077   while (sap != NULL) {
1078     nextsap = sap->next;
1079     if (sap->type == 2) {
1080       *(prevsap) = sap->next;
1081       sap->next = NULL;
1082       SeqAnnotFree (sap);
1083     } else {
1084       prevsap = (Pointer PNTR) &(sap->next);
1085     }
1086     sap = nextsap;
1087   }
1088 }
1089 
1090 extern void SubmitToNCBI (IteM i);
1091 
1092 static void MissingAnnotCallback (BioseqPtr bsp, Pointer userdata)
1093 {
1094   BoolPtr p_missing;
1095   SeqFeatPtr sfp;
1096   SeqMgrFeatContext fcontext;
1097 
1098   if (bsp == NULL || ISA_aa (bsp->mol) || userdata == NULL) {
1099     return;
1100   }
1101   p_missing = (BoolPtr) userdata;
1102   if (*p_missing) {
1103     return;
1104   }
1105   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
1106   if (sfp == NULL) {
1107     *p_missing = TRUE;
1108   }
1109 }
1110 
1111   
1112 static Boolean IsAnySequenceMissingAnnotation (SeqEntryPtr sep)
1113 {
1114   Boolean rval = FALSE;
1115 
1116   VisitBioseqsInSep (sep, &rval, MissingAnnotCallback);
1117   return rval;
1118 }
1119 
1120 
1121 static void PrepareSeqSubmitProc (IteM i)
1122 
1123 {
1124   BaseFormPtr  bfp;
1125   Char         dfault [64];
1126   Char         path [PATH_MAX];
1127   CharPtr      ptr;
1128   SeqEntryPtr  sep;
1129   CharPtr      str, email_address;
1130   Boolean      update;
1131   CharPtr      fmt_file = "Submission is now written.  Please e-mail '%s' to %s.%s";
1132   CharPtr      fmt_no_file = "Submission is now written.  Please e-mail to %s.%s";
1133   CharPtr      missing_annot = "  Please include a brief summary of your submission within your correspondence.";
1134   CharPtr      note = "";
1135 
1136 #ifdef WIN_MAC
1137   bfp = (BaseFormPtr) currentFormDataPtr;
1138 #else
1139   bfp = (BaseFormPtr) GetObjectExtra (i);
1140 #endif
1141   update = FALSE;
1142   if (bfp != NULL) {
1143     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1144     if (sep != NULL) {
1145       SeqEntryPack (sep);
1146       EntryChangeGBSource (sep);
1147       EntryCheckGBBlock (sep);
1148       GetRidOfEmptyFeatsDescStrings (0, sep);
1149       GetRidOfLocusInSeqIds (0, sep);
1150       if (OkayToWriteTheEntity (bfp->input_entityID, bfp->form, FALSE) == eOkToWriteEntity_Continue) {
1151         /*SetChecklistValue (checklistForm, 7);*/
1152         path [0] = '\0';
1153         StringNCpy_0 (path, bfp->filepath, sizeof (path));
1154         dfault [0] = '\0';
1155         GetDefaultTitleFromForm (bfp->form, dfault, sizeof (dfault), bfp->filepath);
1156         ptr = StringRChr (dfault, '.');
1157         if (ptr != NULL) {
1158           *ptr = '\0';
1159         }
1160         if (StringLen (dfault) < sizeof (dfault) - 5) {
1161           StringCat (dfault, ".sqn");
1162         }
1163         if (GetOutputFileName (path, sizeof (path), dfault)) {
1164           update = PropagateFromGenBankBioseqSet (sep, TRUE);
1165           NormalizeDescriptorOrder (sep);
1166           update = TRUE; /* because of NormalizeDescriptorOrder */
1167           if (SeqEntryHasAligns (bfp->input_entityID, sep)) {
1168             if (Message (MSG_YN, "Remove alignments?") == ANS_YES) {
1169               SeqEntryExplore (sep, NULL, DoRemoveAlignmentFromRecord);
1170               update = TRUE;
1171             }
1172           }
1173           SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
1174           if (WriteTheEntityID (bfp->input_entityID, path, FALSE)) {
1175             email_address = ReturnSubmissionEmailAddress (bfp->input_entityID);
1176             if (IsAnySequenceMissingAnnotation (sep)) {
1177               note = missing_annot;
1178             }
1179             /*SetChecklistValue (checklistForm, 5);*/
1180             ptr = StringRChr (path, DIRDELIMCHR);
1181             if (ptr != NULL) {
1182               ptr++;
1183               str = MemNew (sizeof (Char) * (StringLen (ptr) + StringLen (fmt_file) + StringLen (email_address) + StringLen (note)));
1184               if (str != NULL) {
1185                 sprintf (str, fmt_file, ptr, email_address, note);
1186                 UseWindow ((WindoW) bfp->form);
1187                 Message (MSG_OK, str);
1188                 MemFree (str);
1189                 if (update) {
1190                   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1191                 }
1192                 return;
1193               }
1194             }
1195             str = MemNew (sizeof (Char) * (StringLen (fmt_file) + StringLen (email_address) + StringLen (note)));
1196             if (str != NULL) {
1197               sprintf (str, fmt_no_file, email_address, note);
1198               UseWindow ((WindoW) bfp->form);
1199               Message (MSG_OK, str);
1200               MemFree (str);
1201             }
1202           } else {
1203             UseWindow ((WindoW) bfp->form);
1204             Message (MSG_ERROR, "Unable to write file.");
1205           }
1206         } else {
1207           /*SetChecklistValue (checklistForm, 5);*/
1208           UseWindow ((WindoW) bfp->form);
1209         }
1210       }
1211     }
1212     if (update) {
1213       ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1214     }
1215   }
1216 }
1217 
1218 extern Boolean SaveSeqSubmitProc (BaseFormPtr bfp, Boolean saveAs)
1219 
1220 {
1221   Char         dfault [32];
1222   Char         path [PATH_MAX];
1223   CharPtr      ptr;
1224   SeqEntryPtr  sep;
1225   Char         suffix [32];
1226   Char         tmp [32];
1227   Boolean      update;
1228 
1229   if (bfp != NULL) {
1230     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1231     if (sep != NULL) {
1232       SeqEntryPack (sep);
1233       EntryChangeGBSource (sep);
1234       EntryCheckGBBlock (sep);
1235       GetRidOfEmptyFeatsDescStrings (0, sep);
1236       GetRidOfLocusInSeqIds (0, sep);
1237       path [0] = '\0';
1238       StringNCpy_0 (path, bfp->filepath, sizeof (path));
1239       if (StringHasNoText (path) || saveAs) {
1240         dfault [0] = '\0';
1241         GetDefaultTitleFromForm (bfp->form, dfault, sizeof (dfault), bfp->filepath);
1242         ptr = StringRChr (dfault, '.');
1243         if (ptr != NULL) {
1244           *ptr = '\0';
1245         }
1246         suffix [0] = '\0';
1247         if (GetSequinAppParam ("PREFERENCES", "SUFFIX", ".sqn", tmp, sizeof (tmp))) {
1248           if (tmp [0] == '.') {
1249             StringNCpy_0 (suffix, tmp, sizeof (suffix));
1250           } else {
1251             StringCpy (suffix, ".");
1252             StringNCpy_0 (suffix + 1, tmp, sizeof (suffix) - 1);
1253           }
1254         }
1255         if (StringLen (dfault) < sizeof (dfault) - StringLen (suffix)) {
1256           StringCat (dfault, suffix);
1257         }
1258         if (! (GetOutputFileName (path, sizeof (path), dfault))) return FALSE;
1259       }
1260       update = PropagateFromGenBankBioseqSet (sep, TRUE);
1261       NormalizeDescriptorOrder (sep);
1262       update = TRUE; /* because of NormalizeDescriptorOrder */
1263       SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
1264       if (WriteTheEntityID (bfp->input_entityID, path, FALSE)) {
1265         bfp->filepath = MemFree (bfp->filepath);
1266         bfp->filepath = StringSave (path);
1267         if (update) {
1268           ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1269         }
1270         return TRUE;
1271       } else {
1272         Message (MSG_ERROR, "Unable to write file.");
1273         if (update) {
1274           ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1275         }
1276         return FALSE;
1277       }
1278     }
1279   }
1280   return FALSE;
1281 }
1282 
1283 static void SaveBinSeqEntry (IteM i)
1284 
1285 {
1286   BaseFormPtr  bfp;
1287   Char         dfault [32];
1288   Char         path [PATH_MAX];
1289   CharPtr      ptr;
1290   Boolean      saveAs = TRUE;
1291   SeqEntryPtr  sep;
1292   Boolean      update;
1293 
1294   bfp = (BaseFormPtr) GetObjectExtra (i);
1295   if (bfp != NULL) {
1296     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1297     if (sep != NULL) {
1298       SeqEntryPack (sep);
1299       EntryChangeGBSource (sep);
1300       EntryCheckGBBlock (sep);
1301       GetRidOfEmptyFeatsDescStrings (0, sep);
1302       GetRidOfLocusInSeqIds (0, sep);
1303       path [0] = '\0';
1304       StringNCpy_0 (path, bfp->filepath, sizeof (path));
1305       if (StringHasNoText (path) || saveAs) {
1306         dfault [0] = '\0';
1307         GetDefaultTitleFromForm (bfp->form, dfault, sizeof (dfault), bfp->filepath);
1308         ptr = StringRChr (dfault, '.');
1309         if (ptr != NULL) {
1310           *ptr = '\0';
1311         }
1312         if (StringLen (dfault) < sizeof (dfault) - 5) {
1313           StringCat (dfault, ".val");
1314         }
1315         if (! (GetOutputFileName (path, sizeof (path), dfault))) return;
1316       }
1317       update = PropagateFromGenBankBioseqSet (sep, TRUE);
1318       NormalizeDescriptorOrder (sep);
1319       update = TRUE; /* because of NormalizeDescriptorOrder */
1320       SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
1321       if (WriteTheEntityID (bfp->input_entityID, path, TRUE)) {
1322         bfp->filepath = MemFree (bfp->filepath);
1323         bfp->filepath = StringSave (path);
1324         if (update) {
1325           ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1326         }
1327         return;
1328       } else {
1329         Message (MSG_ERROR, "Unable to write file.");
1330         if (update) {
1331           ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1332         }
1333       }
1334     }
1335   }
1336 }
1337 
1338 static CharPtr google_earth_1 =
1339   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
1340   "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n" \
1341   "<Document>\n" \
1342   "  <name>KmlFile</name>\n" \
1343   "  <StyleMap id=\"default_copy0+nicon=http://maps.google.com/mapfiles/kml/pal3/icon60.png+hicon=http://maps.google.com/mapfiles/kml/pal3/icon52.png\">\n" \
1344   "    <Pair>\n" \
1345   "      <key>normal</key>\n" \
1346   "      <styleUrl>#default_copy0+icon=http://maps.google.com/mapfiles/kml/pal3/icon60.png</styleUrl>\n" \
1347   "    </Pair>\n" \
1348   "    <Pair>\n" \
1349   "      <key>highlight</key>\n" \
1350   "      <styleUrl>#default_copy0+icon=http://maps.google.com/mapfiles/kml/pal3/icon52.png</styleUrl>\n" \
1351   "    </Pair>\n" \
1352   "  </StyleMap>\n" \
1353   "  <Style id=\"default_copy0+icon=http://maps.google.com/mapfiles/kml/pal3/icon60.png\">\n" \
1354   "    <IconStyle>\n" \
1355   "      <Icon>\n" \
1356   "        <href>http://maps.google.com/mapfiles/kml/pal3/icon60.png</href>\n" \
1357   "      </Icon>\n" \
1358   "    </IconStyle>\n" \
1359   "  </Style>\n" \
1360   "  <Placemark>\n";
1361 
1362 static CharPtr google_earth_2 =
1363   "    <styleUrl>#default_copy0+nicon=http://maps.google.com/mapfiles/kml/pal3/icon60.png+hicon=http://maps.google.com/mapfiles/kml/pal3/icon52.png</styleUrl>\n" \
1364   "    <Point>\n";
1365 
1366 static CharPtr google_earth_3 =
1367   "    </Point>\n" \
1368   "  </Placemark>\n" \
1369   "</Document>\n" \
1370   "</kml>\n";
1371 
1372 static Boolean LaunchedGoogleEarth (
1373   Uint2 entityID, Uint4 itemID, Uint2 itemtype
1374 )
1375 
1376 {
1377   BioSourcePtr       biop;
1378   SeqMgrDescContext  context;
1379   Boolean            format_ok = FALSE;
1380   FILE               *fp;
1381   FloatHi            lat = 0.0;
1382   FloatHi            lon = 0.0;
1383   CharPtr            lat_lon = NULL;
1384   Boolean            lat_in_range = FALSE;
1385   Boolean            lon_in_range = FALSE;
1386   Char               path [PATH_MAX];
1387   SeqDescPtr         sdp;
1388   SubSourcePtr       ssp;
1389 #ifdef OS_UNIX
1390   Char               cmmd [256];
1391 #endif
1392 
1393   if (itemtype != OBJ_SEQDESC) return FALSE;
1394 
1395   sdp = SeqMgrGetDesiredDescriptor (entityID, NULL, itemID, 0, NULL, &context);
1396   if (sdp != NULL && sdp->choice == Seq_descr_source) {
1397     biop = (BioSourcePtr) sdp->data.ptrvalue;
1398     if (biop != NULL) {
1399       for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
1400         if (ssp->subtype != SUBSRC_lat_lon) continue;
1401         lat_lon = ssp->name;
1402         if (StringHasNoText (lat_lon)) continue;
1403         IsCorrectLatLonFormat (lat_lon, &format_ok, &lat_in_range, &lon_in_range);
1404         if (! format_ok) continue;
1405         if (! lat_in_range) continue;
1406         if (! lon_in_range) continue;
1407         if (! ParseLatLon (lat_lon, &lat, &lon)) continue;
1408         TmpNam (path);
1409         /* write to original temp file, so next temp file name will not collide */
1410         fp = FileOpen (path, "w");
1411         if (fp != NULL) {
1412           fprintf (fp, "\n");
1413           FileClose (fp);
1414           RememberSqnTempFile (path);
1415         }
1416         /* now append .kml extension so proper application is launched */
1417         StringCat (path, ".kml");
1418         fp = FileOpen (path, "w");
1419         if (fp != NULL) {
1420           fprintf (fp, "%s", google_earth_1);
1421           fprintf (fp, "    <name>%s</name>\n", lat_lon);
1422           fprintf (fp, "%s", google_earth_2);
1423           fprintf (fp, "      <coordinates>%lf,%lf</coordinates>\n", (double) lon, (double) lat);
1424           fprintf (fp, "%s", google_earth_3);
1425           FileClose (fp);
1426           RememberSqnTempFile (path);
1427 #ifdef OS_UNIX
1428           sprintf (cmmd, "open %s", path);
1429           system (cmmd);
1430 #endif
1431 #ifdef WIN_MSWIN
1432           Nlm_MSWin_OpenDocument (path);
1433 #endif
1434         }
1435         return TRUE;
1436       }
1437     }
1438   }
1439 
1440   return FALSE;
1441 }
1442 
1443 static void LIBCALLBACK ValidNotify (ErrSev sev, int errcode, int subcode,
1444                                      Uint2 entityID, Uint4 itemID, Uint2 itemtype,
1445                                      Boolean select, Boolean dblClick, Boolean shftKey)
1446 
1447 {
1448   Int2  handled;
1449 
1450   if (dblClick && entityID > 0 && itemID > 0 && itemtype > 0) {
1451     if (itemtype == OBJ_SEQDESC && shftKey) {
1452       if (LaunchedGoogleEarth (entityID, itemID, itemtype)) return;
1453     }
1454 
1455     WatchCursor ();
1456     handled = GatherProcLaunch (OMPROC_EDIT, FALSE, entityID, itemID,
1457                                 itemtype, 0, 0, itemtype, 0);
1458     ArrowCursor ();
1459     if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
1460       Beep ();
1461     }
1462   }
1463 }
1464 
1465 #ifndef WIN_MAC
1466 static void RemoveUpdateDates (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
1467 
1468 {
1469   BioseqPtr     bsp;
1470   BioseqSetPtr  bssp;
1471   ValNodePtr    nextsdp;
1472   Pointer PNTR  prevsdp;
1473   ValNodePtr    sdp;
1474 
1475   if (sep == NULL || sep->data.ptrvalue == NULL) return;
1476   if (IS_Bioseq (sep)) {
1477     bsp = (BioseqPtr) sep->data.ptrvalue;
1478     sdp = bsp->descr;
1479     prevsdp = (Pointer PNTR) &(bsp->descr);
1480   } else if (IS_Bioseq_set (sep)) {
1481     bssp = (BioseqSetPtr) sep->data.ptrvalue;
1482     sdp = bssp->descr;
1483     prevsdp = (Pointer PNTR) &(bssp->descr);
1484   } else return;
1485   while (sdp != NULL) {
1486     nextsdp = sdp->next;
1487     if (sdp->choice == Seq_descr_update_date) {
1488       *(prevsdp) = sdp->next;
1489       sdp->next = NULL;
1490       SeqDescFree (sdp);
1491     } else {
1492       prevsdp = (Pointer PNTR) &(sdp->next);
1493     }
1494     sdp = nextsdp;
1495   }
1496 }
1497 
1498 static CharPtr stillHasGBMsg =
1499 "Source information in a GenBank block should be in a BioSource.  Should I fixup?";
1500 
1501 #ifdef USE_SMARTNET
1502 static void SmartResetProc (IteM i)
1503 {
1504     BaseFormPtr   bfp;
1505     ForM          f = NULL;
1506     Int4          status;
1507     ObjMgrDataPtr omdp;  
1508     OMUserDataPtr omudp;
1509     SMUserDataPtr sm_usr_data;
1510 
1511     if((bfp = (BaseFormPtr) GetObjectExtra (i)) != NULL) {
1512         f = bfp->form;
1513         
1514         omudp = ObjMgrGetUserData(bfp->input_entityID, 0, 0, SMART_KEY);
1515         omdp = ObjMgrGetData (bfp->input_entityID);
1516         
1517         sm_usr_data = (SMUserDataPtr) omudp->userdata.ptrvalue;
1518         
1519         if(omdp->dirty == FALSE) {
1520             status = sm_usr_data->header->status;
1521             sm_usr_data->header->status = SMStatClosed;
1522             SMSendMsgToClient(sm_usr_data);
1523             sm_usr_data->header->status = (SMStatusCode)status;
1524             return;
1525         }
1526     }
1527     return;
1528 }
1529 #endif
1530 
1531 static void LaunchValidatorForDone (BaseFormPtr bfp, SeqEntryPtr sep, FormActnFunc revalProc, FormActnFunc continueProc);
1532 static Boolean SmallInferenceAccnVer (ForM f);
1533 static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck, FormActnFunc revalProc, FormActnFunc doneProc);
1534 
1535 #ifdef USE_SMARTNET
1536 static Boolean LIBCALLBACK AllGenBankOrRefSeq (BioseqPtr bsp, SeqMgrBioseqContextPtr bcontext)
1537 
1538 {
1539   SeqMgrDescContext  dcontext;
1540   MolInfoPtr         mip;
1541   BoolPtr            resetUpdateDate;
1542   ValNodePtr         sdp;
1543   SeqIdPtr           sip;
1544 
1545   resetUpdateDate = (BoolPtr) bcontext->userdata;
1546   for (sip = bsp->id; sip != NULL; sip = sip->next) {
1547     if (sip->choice == SEQID_EMBL || sip->choice == SEQID_DDBJ) {
1548       *resetUpdateDate = FALSE;
1549     }
1550   }
1551   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &dcontext);
1552   if (sdp != NULL) {
1553     mip = (MolInfoPtr) sdp->data.ptrvalue;
1554     if (mip != NULL) {
1555       if (mip->tech == MI_TECH_htgs_1 || mip->tech == MI_TECH_htgs_2 ||
1556           mip->tech == MI_TECH_htgs_3 || mip->tech == MI_TECH_htgs_0) {
1557         *resetUpdateDate = FALSE;
1558       }
1559     }
1560   }
1561   return TRUE;
1562 }
1563 
1564 static void DoSmartReport (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
1565 
1566 {
1567   BioseqPtr        bsp;
1568   BioseqSetPtr     bssp;
1569   Char             id [42];
1570   ValNodePtr PNTR  vnpp;
1571 
1572   vnpp = (ValNodePtr PNTR) mydata;
1573   if (sep == NULL || sep->data.ptrvalue == NULL) return;
1574   if (IS_Bioseq (sep)) {
1575     bsp = (BioseqPtr) sep->data.ptrvalue;
1576     SeqIdWrite (bsp->id, id, PRINTID_FASTA_LONG, sizeof (id) - 1);
1577     ValNodeCopyStr (vnpp, 0, id);
1578   } else if (IS_Bioseq_set (sep)) {
1579     bssp = (BioseqSetPtr) sep->data.ptrvalue;
1580     ValNodeAddInt (vnpp, bssp->_class, 0);
1581   }
1582 }
1583 
1584 static VoidPtr SmartStructureReport (SeqEntryPtr sep)
1585 
1586 {
1587   ValNodePtr  vnp = NULL;
1588 
1589   SeqEntryExplore (sep, (Pointer) &vnp, DoSmartReport);
1590   return vnp;
1591 }
1592 
1593 static Boolean ValNodeListsDiffer (ValNodePtr vnp1, ValNodePtr vnp2)
1594 
1595 {
1596   while (vnp1 != NULL && vnp2 != NULL) {
1597     if (vnp1->choice != vnp2->choice) return TRUE;
1598     if (vnp1->choice == 0) {
1599       if (StringCmp (vnp1->data.ptrvalue, vnp2->data.ptrvalue) != 0) return TRUE;
1600     }
1601     vnp1 = vnp1->next;
1602     vnp2 = vnp2->next;
1603   }
1604   if (vnp1 != NULL || vnp2 != NULL) return TRUE;
1605   return FALSE;
1606 }
1607 
1608 static void SmartnetDoneFuncEx (BaseFormPtr bfp, Boolean validate);
1609 static void SmartnetDoneNoValidateFunc (ForM f);
1610 
1611 static void SmartnetDoneValidateFunc (ForM f)
1612 {
1613   Boolean  inferenceAccnCheck;
1614 
1615   inferenceAccnCheck = SmallInferenceAccnVer (f);
1616   ValSeqEntryFormExEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck, SmartnetDoneValidateFunc, SmartnetDoneNoValidateFunc);
1617 }
1618 
1619 static void SmartnetDoneNoValidateFunc (ForM f)
1620 {
1621   BaseFormPtr bfp;
1622 
1623   bfp = (BaseFormPtr) GetObjectExtra (f);
1624   if (bfp == NULL) return;
1625   SmartnetDoneFuncEx (bfp, FALSE);
1626 }
1627 
1628 
1629 static void SmartnetDoneFuncEx (BaseFormPtr bfp, Boolean validate)
1630 
1631 {
1632     MsgAnswer     ans;
1633     ForM          f = NULL;
1634     Boolean       hasGBStuff;
1635     ValNodePtr    sdp;
1636     SeqEntryPtr   sep;
1637     Boolean       update;
1638     
1639     ObjMgrDataPtr omdp;  
1640     OMUserDataPtr omudp;
1641     SMUserDataPtr sm_usr_data;
1642 /*    Uint2         entityID; */
1643 
1644     Boolean       resetUpdateDate = TRUE;
1645     ValNodePtr    vnp;
1646     EOkToWriteEntity continue_cancel_validate;
1647 
1648     if(bfp != NULL) {
1649         f = bfp->form;
1650         
1651         omudp = ObjMgrGetUserData(bfp->input_entityID, 0, 0, SMART_KEY);
1652         if (omudp == NULL) return;
1653 
1654         /* for now set dirty flag to force validation in OkayToWriteTheEntity */
1655         ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1656 
1657         omdp = ObjMgrGetData (bfp->input_entityID);
1658 
1659         sm_usr_data = (SMUserDataPtr) omudp->userdata.ptrvalue;
1660 
1661         if(omdp->dirty == FALSE || (sm_usr_data->header->dirty & 0x02)) {
1662             sm_usr_data->header->status = SMStatClosed;
1663             SMSendMsgToClient(sm_usr_data);
1664             
1665             /*
1666             entityID = bfp->input_entityID;
1667             RemoveSeqEntryViewer (bfp->form);
1668             ObjMgrFreeUserData(entityID, 0, 0, SMART_KEY); 
1669             */
1670             
1671             /* ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0); */
1672             ObjMgrFree(omdp->datatype, omdp->dataptr);
1673             
1674             return;
1675         }
1676 
1677         sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1678         if (sep != NULL) {
1679             
1680             if (EntrezASN1Detected (sep)) {
1681                 Message(MSG_OK, 
1682                         "You may not commit entry retrieved from Entrez.\n"
1683                         "Please close this window instead");
1684                 return;
1685             }
1686             
1687             SeqEntryPack (sep);
1688             EntryChangeGBSource (sep);
1689             hasGBStuff = EntryCheckGBBlock (sep);
1690             GetRidOfEmptyFeatsDescStrings (0, sep);
1691             GetRidOfLocusInSeqIds (0, sep);
1692 
1693             if (hasGBStuff) {
1694                 /*  ans = Message (MSG_YNC, stillHasGBMsg);
1695                     if (ans == ANS_CANCEL) return;
1696                     if (ans == ANS_YES) { */
1697                 MySeqEntryToAsn3 (sep, TRUE, FALSE, FALSE);
1698                 /* } */
1699             }
1700             move_cds (sep);
1701             /* now instantiating protein titles */
1702             InstantiateProteinTitles (bfp->input_entityID, NULL);
1703             update = PropagateFromGenBankBioseqSet (sep, FALSE);
1704             NormalizeDescriptorOrder (sep);
1705             update = TRUE; /* because of NormalizeDescriptorOrder */
1706             SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
1707 
1708             if (validate) {
1709               continue_cancel_validate = OkayToWriteTheEntity (bfp->input_entityID, f, TRUE);
1710               if (continue_cancel_validate == eOkToWriteEntity_Cancel) {
1711                   if (update && bfp != NULL) {
1712                       ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1713                   }
1714                   return;
1715               } else if (continue_cancel_validate == eOkToWriteEntity_Validate) {
1716                   /* launch validator */
1717                   LaunchValidatorForDone (bfp, sep, SmartnetDoneValidateFunc, SmartnetDoneNoValidateFunc);
1718                   return;
1719               }
1720             }
1721             /* ans = Message (MSG_YN, "Reset Update Date?"); */
1722             ans = ANS_YES;
1723 
1724             /* reset update date in smart mode if GenBank or RefGene, and not HTGS */
1725 
1726             SeqMgrExploreBioseqs (bfp->input_entityID, 0, (Pointer) &resetUpdateDate, AllGenBankOrRefSeq, TRUE, TRUE, TRUE);
1727             if (/* ans == ANS_YES */ resetUpdateDate) {
1728                 SeqEntryExplore (sep, NULL, RemoveUpdateDates);
1729                 sdp = CreateNewDescriptor (sep, Seq_descr_update_date);
1730                 if (sdp != NULL) {
1731                     sdp->data.ptrvalue = DateCurr ();
1732                 }
1733                 PropagateFromGenBankBioseqSet (sep, FALSE);
1734                 NormalizeDescriptorOrder (sep);
1735             }
1736             CdCheck (sep, NULL);
1737 
1738             omudp = ObjMgrGetUserData(bfp->input_entityID, 0, 0, DUMB_KEY);
1739             if (omudp != NULL) {
1740               vnp = SmartStructureReport (sep);
1741               if (ValNodeListsDiffer (vnp, omudp->userdata.ptrvalue)) {
1742                 sm_usr_data->header->dirty |= 0x04; /* set rearranged signal */
1743               }
1744               ValNodeFreeData (vnp);
1745             }
1746             SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
1747 
1748         }
1749 
1750         if(sm_usr_data->header->format == OBJ_SEQENTRY) {
1751             SMWriteBioseqObj(sep, sm_usr_data, NULL);
1752         } else {
1753             sm_usr_data->header->format = omdp->datatype;
1754             SMWriteBioseqObj(omdp->dataptr, sm_usr_data, NULL); 
1755         }
1756 
1757         /* ObjMgrDelete(omdp->datatype, omdp->dataptr); */
1758 
1759         omdp->dirty = FALSE;
1760         
1761         /*
1762         entityID = bfp->input_entityID;
1763         RemoveSeqEntryViewer (bfp->form);  
1764         ObjMgrFreeUserData(entityID, 0, 0, SMART_KEY); 
1765         */
1766 
1767         /* ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0); */
1768         ObjMgrFree(omdp->datatype, omdp->dataptr);
1769 
1770         subtoolRecordDirty = FALSE;
1771         FileRemove (SEQUIN_EDIT_TEMP_FILE);
1772         FileRemove (SEQUIN_EDIT_PREV_FILE);
1773         /* FileRemove (SEQUIN_EDIT_BACK_FILE); */
1774         FileRemove (SEQUIN_EDIT_ARCH_FILE);
1775         FileRename (SEQUIN_EDIT_BACK_FILE, SEQUIN_EDIT_ARCH_FILE);
1776         return;
1777         
1778     } else {
1779         Message(MSG_ERROR, "NULL pointer for brp ...? BUG!BUG!BUG!");
1780         return;
1781     }
1782 }
1783 
1784 
1785 static void SmartnetDoneFunc (BaseFormPtr bfp)
1786 {
1787   SmartnetDoneFuncEx (bfp, TRUE);
1788 }
1789 
1790 
1791 static void SmartnetDoneProc (IteM i)
1792 
1793 {
1794         BaseFormPtr bfp;
1795 
1796         bfp = (BaseFormPtr) GetObjectExtra (i);
1797         SmartnetDoneFunc (bfp);
1798 }
1799 #endif
1800 
1801 
1802 static void SubtoolDoneFuncEx (ForM f, Boolean validate);
1803 static void SubtoolDoneNoValidateFunc (ForM f);
1804 
1805 static void SubtoolDoneValidateFunc (ForM f)
1806 {
1807   Boolean  inferenceAccnCheck;
1808 
1809   inferenceAccnCheck = SmallInferenceAccnVer (f);
1810   ValSeqEntryFormExEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck, SubtoolDoneValidateFunc, SubtoolDoneNoValidateFunc);
1811 }
1812 
1813 
1814 static void SubtoolDoneNoValidateFunc (ForM f)
1815 {
1816         SubtoolDoneFuncEx (f, FALSE);
1817 }
1818 
1819 
1820 static void SubtoolDoneFuncEx (ForM form, Boolean validate)
1821 {
1822   MsgAnswer    ans;
1823   BaseFormPtr  bfp;
1824   ForM         f;
1825   Boolean      hasGBStuff;
1826   ValNodePtr   sdp;
1827   SeqEntryPtr  sep;
1828   Boolean      update;
1829   EOkToWriteEntity continue_review_cancel;
1830 
1831   if (subtoolEntityID > 0) {
1832     sep = GetTopSeqEntryForEntityID (subtoolEntityID);
1833     if (sep != NULL) {
1834       SeqEntryPack (sep);
1835       EntryChangeGBSource (sep);
1836       hasGBStuff = EntryCheckGBBlock (sep);
1837       GetRidOfEmptyFeatsDescStrings (0, sep);
1838       GetRidOfLocusInSeqIds (0, sep);
1839       if (hasGBStuff) {
1840         ans = Message (MSG_YNC, stillHasGBMsg);
1841         if (ans == ANS_CANCEL) return;
1842         if (ans == ANS_YES) {
1843           MySeqEntryToAsn3 (sep, TRUE, FALSE, FALSE);
1844         }
1845       }
1846       move_cds (sep);
1847       /* now instantiating protein titles */
1848       InstantiateProteinTitles (subtoolEntityID, NULL);
1849       update = PropagateFromGenBankBioseqSet (sep, FALSE);
1850       NormalizeDescriptorOrder (sep);
1851       update = TRUE; /* because of NormalizeDescriptorOrder */
1852       f = NULL;
1853       bfp = (BaseFormPtr) GetObjectExtra (form);
1854       if (bfp != NULL) {
1855         f = bfp->form;
1856       }
1857       SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
1858       if (validate) {
1859         continue_review_cancel = OkayToWriteTheEntity (subtoolEntityID, f, validate);
1860         if (continue_review_cancel == eOkToWriteEntity_Cancel) {
1861           if (update && bfp != NULL) {
1862             ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1863           }
1864           return;
1865         } else if (continue_review_cancel == eOkToWriteEntity_Validate) {
1866           /* launch validator */
1867           LaunchValidatorForDone (bfp, sep, SubtoolDoneValidateFunc, SubtoolDoneNoValidateFunc);
1868           return;
1869         }
1870       }
1871       /* ans = Message (MSG_YN, "Reset Update Date?"); */
1872       ans = ANS_YES;
1873       if (ans == ANS_YES) {
1874         SeqEntryExplore (sep, NULL, RemoveUpdateDates);
1875         sdp = CreateNewDescriptor (sep, Seq_descr_update_date);
1876         if (sdp != NULL) {
1877           sdp->data.ptrvalue = DateCurr ();
1878         }
1879         PropagateFromGenBankBioseqSet (sep, FALSE);
1880         NormalizeDescriptorOrder (sep);
1881       }
1882       CdCheck (sep, NULL);
1883     }
1884     /*SetChecklistValue (checklistForm, 7);*/
1885     SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
1886     if (WriteTheEntityID (subtoolEntityID, "stdout", FALSE)) {
1887       subtoolRecordDirty = FALSE;
1888       FileRemove (SEQUIN_EDIT_TEMP_FILE);
1889       FileRemove (SEQUIN_EDIT_PREV_FILE);
1890       /* FileRemove (SEQUIN_EDIT_BACK_FILE); */
1891       FileRemove (SEQUIN_EDIT_ARCH_FILE);
1892       FileRename (SEQUIN_EDIT_BACK_FILE, SEQUIN_EDIT_ARCH_FILE);
1893     } else {
1894       Message (MSG_POSTERR, "Unable to write ASN.1 file");
1895       return;
1896     }
1897     /*SetChecklistValue (checklistForm, 5);*/
1898   }
1899   QuitProgram ();
1900 }
1901 
1902 
1903 static void SubtoolDoneProc (IteM i)
1904 
1905 {
1906   BaseFormPtr  bfp;
1907 
1908   bfp = (BaseFormPtr) GetObjectExtra (i);
1909   if (bfp != NULL) {
1910     SubtoolDoneFuncEx (bfp->form, TRUE);
1911   }
1912 }
1913 #endif
1914 
1915 static Boolean ReviewErrorsForValidationFailure (void)
1916 {
1917   WindoW w;
1918   GrouP  h, c;
1919   PrompT p;
1920   ButtoN b;
1921   ModalAcceptCancelData acd;
1922   
1923   acd.accepted = FALSE;
1924   acd.cancelled = FALSE;
1925   
1926   w = ModalWindow(-20, -13, -10, -10, NULL);
1927   h = HiddenGroup (w, -1, 0, NULL);
1928   SetGroupSpacing (h, 10, 10);
1929   
1930   p = StaticPrompt (h, "Submission has validation errors.", 0, 0, programFont, 'l');
1931   c = HiddenGroup (h, 3, 0, NULL);
1932   SetGroupSpacing (c, 10, 10);
1933   b = PushButton (c, "Review Errors", ModalAcceptButton);
1934   SetObjectExtra (b, &acd, NULL);
1935   b = PushButton (c, "Continue", ModalCancelButton);
1936   SetObjectExtra (b, &acd, NULL);
1937   AlignObjects (ALIGN_CENTER, (HANDLE) p, (HANDLE) c, NULL);
1938   
1939   Show(w); 
1940   Select (w);
1941   while (!acd.accepted && ! acd.cancelled)
1942   {
1943     ProcessExternalEvent ();
1944     Update ();
1945   }
1946   ProcessAnEvent ();
1947   Remove (w);
1948   if (acd.accepted)
1949   {
1950     return TRUE;
1951   }
1952   else
1953   {
1954     return FALSE;
1955   }
1956 }
1957 
1958 
1959 static void LaunchValidatorForDone (BaseFormPtr bfp, SeqEntryPtr sep, FormActnFunc revalProc, FormActnFunc continueProc)
1960 {
1961   ValidStructPtr  vsp;
1962   Int2            verbosity = 2;
1963   Char            buf [32];
1964   Boolean         allRawOrSeg = TRUE;
1965   ErrHookProc     oldErrHook;
1966   ErrSev          oldErrSev;
1967   Int2            errors;
1968   Int2            j;
1969 
1970   WatchCursor ();
1971   Update ();
1972   vsp = ValidStructNew ();
1973   if (vsp != NULL) {
1974     /*SetChecklistValue (checklistForm, 6);*/
1975 
1976     verbosity = 2;
1977     if (GetSequinAppParam ("SETTINGS", "VALIDATEVERBOSITY", NULL, buf, sizeof (buf))) {
1978       if (! StrToInt (buf, &verbosity)) {
1979         verbosity = 2;
1980       }
1981     }
1982 
1983     CreateValidateWindowExEx (ValidNotify, "Sequin Validation Errors",
1984                             programFont, SEV_INFO, verbosity, bfp, revalProc, continueProc, TRUE);
1985     ClearValidateWindow ();
1986     SeqEntryExplore (sep, (Pointer) (&allRawOrSeg), CheckForCookedBioseqs);
1987     if (allRawOrSeg) {
1988       vsp->useSeqMgrIndexes = TRUE;
1989     }
1990     HideValidateDoc ();
1991     vsp->suppressContext = ShouldSetSuppressContext ();
1992     vsp->justShowAccession = ShouldSetJustShowAccession ();
1993     oldErrHook = ErrSetHandler (ValidErrHook);
1994     oldErrSev = ErrSetMessageLevel (SEV_NONE);
1995     vsp->validateAlignments = TRUE;
1996     vsp->alignFindRemoteBsp = TRUE;
1997     vsp->doSeqHistAssembly = FALSE;
1998     for (j = 0; j < 6; j++) {
1999       vsp->errors [j] = 0;
2000     }
2001     vsp->errfunc = ValidErrCallback;
2002     ValidateSeqEntry (sep, vsp);
2003     if (indexerVersion && useEntrez) {
2004       TaxonValidate (sep, vsp);
2005     }
2006     ErrSetMessageLevel (oldErrSev);
2007     ErrSetHandler (oldErrHook);
2008     ErrClear ();
2009     ShowValidateDoc ();
2010     errors = 0;
2011     for (j = 0; j < 6; j++) {
2012       errors += vsp->errors [j];
2013     }
2014     if (errors == 0) {
2015       ArrowCursor ();
2016       Message (MSG_OK, "Validation test succeeded.");
2017       FreeValidateWindow ();
2018     } else {
2019       RepopulateValidateFilter ();
2020     }
2021     ValidStructFree (vsp);
2022     /*SetChecklistValue (checklistForm, 5);*/
2023   }
2024   ArrowCursor ();
2025   Update ();
2026 }
2027 
2028 
2029 static void ProcessDoneButton (ForM f)
2030 
2031 {
2032   Boolean         allRawOrSeg = TRUE;
2033   BaseFormPtr     bfp;
2034   Int2            errors;
2035   Int2            j;
2036   ErrSev          oldErrSev;
2037   SeqEntryPtr     sep;
2038   CharPtr         str;
2039   ValidStructPtr  vsp;
2040   CharPtr         fmt_no_file = "Submission is now written.  Please e-mail to %s.%s";
2041   CharPtr         missing_annot = "  Please include a brief summary of your submission within your correspondence.";
2042   CharPtr         note = "";
2043   CharPtr         email_address;
2044 
2045   bfp = (BaseFormPtr) GetObjectExtra (f);
2046   if (bfp == NULL) return;
2047   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2048   if (sep == NULL) return;
2049 #ifndef WIN_MAC
2050   if (smartnetMode) {
2051 #ifdef USE_SMARTNET
2052     SmartnetDoneProc ((IteM) f);
2053 #endif
2054     return;
2055   }
2056   if (subtoolMode || stdinMode || binseqentryMode) {
2057     SubtoolDoneProc ((IteM) f);
2058     return;
2059   }
2060 #endif
2061   WatchCursor ();
2062   Update ();
2063   vsp = ValidStructNew ();
2064   if (vsp != NULL) {
2065     SeqEntryExplore (sep, (Pointer) (&allRawOrSeg), CheckForCookedBioseqs);
2066     if (allRawOrSeg) {
2067       vsp->useSeqMgrIndexes = TRUE;
2068     }
2069     if (indexerVersion) {
2070       vsp->alwaysRequireIsoJTA = TRUE;
2071     }
2072     oldErrSev = ErrSetMessageLevel (SEV_MAX);
2073     vsp->validateAlignments = TRUE;
2074     vsp->alignFindRemoteBsp = TRUE;
2075     vsp->doSeqHistAssembly = FALSE;
2076     for (j = 0; j < 6; j++) {
2077       vsp->errors [j] = 0;
2078     }
2079     ValidateSeqEntry (sep, vsp);
2080     if (indexerVersion && useEntrez) {
2081       TaxonValidate (sep, vsp);
2082     }
2083     ErrSetMessageLevel (oldErrSev);
2084     ErrClear ();
2085     ErrShow ();
2086     errors = 0;
2087     for (j = 3; j < 6; j++) {
2088       errors += vsp->errors [j];
2089     }
2090     ValidStructFree (vsp);
2091     if (errors > 0) {
2092       ArrowCursor ();
2093       Update ();
2094       if (ReviewErrorsForValidationFailure ()) {
2095         LaunchValidatorForDone (bfp, sep, ProcessDoneButton, NULL);
2096         return;
2097       }
2098     }
2099     ArrowCursor ();
2100     Update ();
2101     if (Message (MSG_YN, "Are you ready to save the record?") == ANS_YES) {
2102       if (SaveSeqSubmitProc (bfp, TRUE)) {
2103         if (IsAnySequenceMissingAnnotation (sep)) {
2104           note = missing_annot;
2105         }
2106         email_address = ReturnSubmissionEmailAddress (bfp->input_entityID);
2107         str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt_no_file) + StringLen (email_address) + StringLen (note)));
2108         if (str != NULL) {
2109           sprintf (str, fmt_no_file, email_address, note);
2110           UseWindow ((WindoW) bfp->form);
2111           Message (MSG_OK, str);
2112           MemFree (str);
2113         }
2114       }
2115     }
2116   }
2117   ArrowCursor ();
2118   Update ();
2119 }
2120 
2121 static void CloseAboutWindowProc (WindoW w)
2122 
2123 {
2124   Remove (w);
2125 }
2126 
2127 static void CloseAboutPanelProc (PaneL p, PoinT pt)
2128 
2129 {
2130   WindoW  w;
2131 
2132   w = ParentWindow (p);
2133   Remove (w);
2134 }
2135 
2136 static void AboutProc (IteM i)
2137 
2138 {
2139   PaneL   p;
2140   WindoW  w;
2141 
2142   w = ModalWindow (-50, -33, -1, -1, CloseAboutWindowProc);
2143   p = SimplePanel (w, AboutBoxWidth (), AboutBoxHeight (), DrawAbout);
2144   SetPanelClick (p, NULL, NULL, NULL, CloseAboutPanelProc);
2145   Show (w);
2146   Select (w);
2147 }
2148 
2149 static void StyleManagerProc (IteM i)
2150 
2151 {
2152   MuskStyleManager ();
2153 }
2154 
2155 extern Boolean SequinEntrezInit (CharPtr appl_id, Boolean no_warnings, BoolPtr is_network)
2156 
2157 {
2158   /*
2159   MonitorPtr  mon;
2160   Boolean     rsult;
2161 
2162   mon = MonitorStrNewEx ("Sequin", 30, FALSE);
2163   MonitorStrValue (mon, "Connecting to Entrez service");
2164   Update ();
2165   rsult = EntrezInit (appl_id, no_warnings, is_network);
2166   MonitorFree (mon);
2167   Update ();
2168   return rsult;
2169   */
2170   return FALSE;
2171 }
2172 
2173 /*
2174 #ifndef WIN16
2175 static void Cn3DWinShowProc (IteM i)
2176 {
2177   WindoW  w;
2178 
2179   if (! BiostrucAvail ()) return;
2180   if (! EntrezIsInited ()) {
2181     SequinEntrezInit ("Sequin", FALSE, NULL);
2182   }
2183   w = Cn3DWin_Entrez(NULL, useEntrez);
2184   if (w == NULL) return;
2185   Show (w);
2186   Select (w);
2187 }
2188 #endif
2189 */
2190 
2191 typedef struct tax3val {
2192   Uint2       entityID;
2193   Uint4       itemID;
2194   Uint2       itemtype;
2195   Uint1       organelle;
2196   OrgRefPtr   orp;
2197   BioseqPtr   bsp;
2198   SeqFeatPtr  sfp;
2199 } TaxVal, PNTR TaxValPtr;
2200 
2201 typedef struct tax3lst {
2202   ValNodePtr  head;
2203   ValNodePtr  tail;
2204 } TaxLst, PNTR TaxLstPtr;
2205 
2206 static void RecordSrc (Uint2 entityID, Uint4 itemID, Uint2 itemtype, OrgRefPtr orp,
2207                        Uint1 organelle, TaxLstPtr tlp, SeqDescrPtr sdp, SeqFeatPtr sfp)
2208 
2209 {
2210   BioseqPtr      bsp;
2211   BioseqSetPtr   bssp;
2212   ObjValNodePtr  ovp;
2213   SeqEntryPtr    sep;
2214   TaxValPtr      tvp;
2215   ValNodePtr     vnp;
2216 
2217   if (orp == NULL || tlp == NULL) return;
2218 
2219   tvp = (TaxValPtr) MemNew (sizeof (TaxVal));
2220   if (tvp == NULL) return;
2221 
2222   vnp = ValNodeNew (tlp->tail);
2223   if (vnp == NULL) return;
2224 
2225   if (tlp->head == NULL) {
2226     tlp->head = vnp;
2227   }
2228   tlp->tail = vnp;
2229 
2230   tvp->entityID = entityID;
2231   tvp->itemID = itemID;
2232   tvp->itemtype = itemtype;
2233   tvp->organelle = organelle;
2234   tvp->orp = orp;
2235   if (sdp != NULL && sdp->extended != 0) {
2236     ovp = (ObjValNodePtr) sdp;
2237     if (ovp->idx.parenttype == OBJ_BIOSEQ) {
2238       bsp = (BioseqPtr) ovp->idx.parentptr;
2239       if (bsp != NULL) {
2240         tvp->bsp = bsp;
2241       }
2242     } else if (ovp->idx.parenttype == OBJ_BIOSEQSET) {
2243       bssp = (BioseqSetPtr) ovp->idx.parentptr;
2244       if (bssp != NULL) {
2245         sep = bssp->seqentry;
2246         if (sep != NULL) {
2247           sep = FindNthBioseq (sep, 1);
2248           if (sep != NULL) {
2249             bsp = (BioseqPtr) sep->data.ptrvalue;
2250             if (bsp != NULL) {
2251               tvp->bsp = bsp;
2252             }
2253           }
2254         }
2255       }
2256     }
2257   } else if (sfp != NULL) {
2258     tvp->sfp = sfp;
2259   }
2260 
2261   vnp->data.ptrvalue = tvp;
2262 }
2263 
2264 static void GetSrcDesc (SeqDescrPtr sdp, Pointer userdata)
2265 
2266 {
2267   BioSourcePtr   biop;
2268   ObjValNodePtr  ovp;
2269   TaxLstPtr      tlp;
2270 
2271   if (sdp == NULL || sdp->choice != Seq_descr_source) return;
2272   tlp = (TaxLstPtr) userdata;
2273 
2274   biop = (BioSourcePtr) sdp->data.ptrvalue;
2275   if (biop == NULL) return;
2276 
2277   if (sdp->extended != 0) {
2278     ovp = (ObjValNodePtr) sdp;
2279     RecordSrc (ovp->idx.entityID, ovp->idx.itemID, OBJ_SEQDESC, biop->org, biop->genome, tlp, sdp, NULL);
2280   }
2281 }
2282 
2283 static void GetSrcFeat (SeqFeatPtr sfp, Pointer userdata)
2284 
2285 {
2286   BioSourcePtr  biop;
2287   TaxLstPtr     tlp;
2288 
2289   if (sfp == NULL || sfp->data.choice != SEQFEAT_BIOSRC) return;
2290   tlp = (TaxLstPtr) userdata;
2291 
2292   biop = (BioSourcePtr) sfp->data.value.ptrvalue;
2293   if (biop == NULL) return;
2294 
2295   RecordSrc (sfp->idx.entityID, sfp->idx.itemID, OBJ_SEQFEAT, biop->org, biop->genome, tlp, NULL, sfp);
2296 }
2297 
2298 NLM_EXTERN void CDECL  ValidErr VPROTO((ValidStructPtr vsp, int severity, int code1, int code2, const char *fmt, ...));
2299 
2300 
2301 static void ReportOneBadSpecificHost (ValNodePtr vnp, ValidStructPtr vsp, CharPtr msg_fmt)
2302 {
2303   ObjValNodePtr ovp;
2304   BioSourcePtr  biop;
2305   OrgModPtr     mod;
2306 
2307   if (vnp == NULL || vsp == NULL || StringHasNoText (msg_fmt)) return;
2308 
2309   vsp->sfp = NULL;
2310   vsp->descr = NULL;
2311   vsp->bsp = NULL;
2312   vsp->bssp = NULL;
2313   biop = NULL;
2314   mod = NULL;
2315 
2316   if (vnp->choice == OBJ_SEQFEAT)
2317   {
2318     vsp->sfp = (SeqFeatPtr) vnp->data.ptrvalue;
2319     vsp->gcp->entityID = vsp->sfp->idx.entityID;
2320     vsp->gcp->itemID = vsp->sfp->idx.itemID;
2321     vsp->gcp->thistype = OBJ_SEQFEAT;
2322     if (vsp->sfp->idx.parenttype == OBJ_BIOSEQ)
2323     {
2324       vsp->bsp = vsp->sfp->idx.parentptr;        
2325     }
2326     else if (vsp->sfp->idx.parenttype == OBJ_BIOSEQSET)
2327     {
2328       vsp->bssp = vsp->sfp->idx.parentptr;        
2329     }
2330     biop = (BioSourcePtr) vsp->sfp->data.value.ptrvalue;
2331   } 
2332   else if (vnp->choice == OBJ_SEQDESC)
2333   {
2334     vsp->descr = (SeqDescrPtr) vnp->data.ptrvalue;
2335     if (vsp->descr != NULL && vsp->descr->extended != 0) 
2336     {
2337       ovp = (ObjValNodePtr) vsp->descr;
2338       vsp->gcp->entityID = ovp->idx.entityID;
2339       vsp->gcp->itemID = ovp->idx.itemID;
2340       vsp->gcp->thistype = OBJ_SEQDESC;
2341 
2342       if (ovp->idx.parenttype == OBJ_BIOSEQ)
2343       {
2344         vsp->bsp = ovp->idx.parentptr;        
2345       }
2346       else if (ovp->idx.parenttype == OBJ_BIOSEQSET)
2347       {
2348         vsp->bssp = ovp->idx.parentptr;        
2349       }
2350     }
2351     biop = vsp->descr->data.ptrvalue;
2352   }
2353   
2354   if (biop != NULL && biop->org != NULL && biop->org->orgname != NULL)
2355   {
2356     mod = biop->org->orgname->mod;
2357     while (mod != NULL && mod->subtype != ORGMOD_nat_host)
2358     {
2359       mod = mod->next;
2360     }
2361     if (mod != NULL)
2362     {      
2363       ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BadSpecificHost, msg_fmt, mod->subname);
2364     }
2365   }
2366 }
2367 
2368 
2369 static void ReportBadSpecificHostValues (SeqEntryPtr sep, ValidStructPtr vsp)
2370 {
2371   ValNodePtr    misspelled = NULL, bad_caps = NULL, ambiguous = NULL, unrecognized = NULL, vnp;
2372 
2373   Taxon3ValidateSpecificHostsInSeqEntry (sep, &misspelled, &bad_caps, &ambiguous, &unrecognized);
2374 
2375   for (vnp = misspelled; vnp != NULL; vnp = vnp->next) {
2376     ReportOneBadSpecificHost (vnp, vsp, "Specific host value is misspelled: %s");
2377   }
2378   for (vnp = bad_caps; vnp != NULL; vnp = vnp->next) {
2379     ReportOneBadSpecificHost (vnp, vsp, "Specific host value is incorrectly capitalized: %s");
2380   } 
2381   for (vnp = ambiguous; vnp != NULL; vnp = vnp->next) {
2382     ReportOneBadSpecificHost (vnp, vsp, "Specific host value is ambiguous: %s");
2383   } 
2384   for (vnp = unrecognized; vnp != NULL; vnp = vnp->next) {
2385     ReportOneBadSpecificHost (vnp, vsp, "Invalid value for specific host: %s");
2386   } 
2387 
2388   misspelled = ValNodeFree (misspelled);
2389   bad_caps = ValNodeFree (bad_caps);
2390   unrecognized = ValNodeFree (unrecognized);
2391 }
2392 
2393 static Boolean log_tax_asn = FALSE;
2394 static Boolean log_tax_set = FALSE;
2395 
2396 static void TaxonValidate (SeqEntryPtr sep, ValidStructPtr vsp)
2397 
2398 {
2399   GatherContext     gc;
2400   Boolean           has_nucleomorphs;
2401   Boolean           is_nucleomorph;
2402   Boolean           is_species_level;
2403   Boolean           force_tax_consult;
2404   ValNodePtr        last = NULL;
2405   OrgRefPtr         orp;
2406   ErrSev            sev;
2407   TaxLst            srclist;
2408   CharPtr           str;
2409   T3ErrorPtr        t3ep;
2410   Taxon3RequestPtr  t3rq;
2411   Taxon3ReplyPtr    t3ry;
2412   T3DataPtr         tdp;
2413   T3StatusFlagsPtr  tfp;
2414   T3ReplyPtr        trp;
2415   TaxValPtr         tvp;
2416   ValNodePtr        val;
2417   ValNodePtr        vnp;
2418   ValNodePtr        vnp2;
2419 
2420   if (sep == NULL || vsp == NULL) return;
2421   MemSet ((Pointer) &gc, 0, sizeof (GatherContext));
2422   vsp->gcp = &gc;
2423 
2424   srclist.head = NULL;
2425   srclist.tail = NULL;
2426   VisitDescriptorsInSep (sep, (Pointer) &srclist, GetSrcDesc);
2427   VisitFeaturesInSep (sep, (Pointer) &srclist, GetSrcFeat);
2428   if (srclist.head == NULL) return;
2429 
2430   t3rq = Taxon3RequestNew ();
2431   if (t3rq == NULL) return;
2432 
2433   for (vnp = srclist.head; vnp != NULL; vnp = vnp->next) {
2434     tvp = (TaxValPtr) vnp->data.ptrvalue;
2435     if (tvp == NULL) continue;
2436     orp = AsnIoMemCopy (tvp->orp,
2437                         (AsnReadFunc) OrgRefAsnRead,
2438                         (AsnWriteFunc) OrgRefAsnWrite);
2439     vnp2 = ValNodeAddPointer (&last, 3, (Pointer) orp);
2440     if (t3rq->request == NULL) {
2441       t3rq->request = vnp2;
2442     }
2443     last = vnp2;
2444   }
2445 
2446 #ifdef OS_UNIX
2447   if (! log_tax_set) {
2448     str = (CharPtr) getenv ("LOG_TAX_ASN");
2449     if (StringDoesHaveText (str)) {
2450       if (StringICmp (str, "TRUE") == 0) {
2451         log_tax_asn = TRUE;
2452       }
2453     }
2454     log_tax_set = TRUE;
2455   }
2456 #endif
2457 
2458   sev = ErrSetMessageLevel (SEV_WARNING);
2459   if (log_tax_asn) {
2460     LaunchAsnTextViewer ((Pointer) t3rq, (AsnWriteFunc) Taxon3RequestAsnWrite, "tax3 request");
2461   }
2462   t3ry = Tax3SynchronousQuery (t3rq);
2463   ErrSetMessageLevel (sev);
2464   Taxon3RequestFree (t3rq);
2465   if (t3ry == NULL) return;
2466   if (log_tax_asn) {
2467     LaunchAsnTextViewer ((Pointer) t3ry, (AsnWriteFunc) Taxon3ReplyAsnWrite, "tax3 result");
2468   }
2469 
2470   for (trp = t3ry->reply, vnp = srclist.head;
2471        trp != NULL && vnp != NULL;
2472        trp = trp->next, vnp = vnp->next) {
2473     tvp = (TaxValPtr) vnp->data.ptrvalue;
2474     if (tvp == NULL) continue;
2475     if (trp->choice == T3Reply_error) {
2476       t3ep = (T3ErrorPtr) trp->data.ptrvalue;
2477       if (t3ep != NULL) {
2478         str = t3ep->message;
2479         if (str == NULL) {
2480           str = "?";
2481         }
2482 
2483         vsp->bssp = NULL;
2484         vsp->bsp = tvp->bsp;
2485         vsp->sfp = tvp->sfp;
2486         vsp->descr = NULL;
2487 
2488         gc.entityID = tvp->entityID;
2489         gc.itemID = tvp->itemID;
2490         gc.thistype = tvp->itemtype;
2491 
2492         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_TaxonomyLookupProblem, "Taxonomy lookup failed with message '%s'", str);
2493       }
2494     }
2495     if (trp->choice != T3Reply_data) continue;
2496     tdp = (T3DataPtr) trp->data.ptrvalue;
2497     if (tdp == NULL) continue;
2498 
2499     vsp->bssp = NULL;
2500     vsp->bsp = tvp->bsp;
2501     vsp->sfp = tvp->sfp;
2502     vsp->descr = NULL;
2503 
2504     is_species_level = FALSE;
2505     has_nucleomorphs = FALSE;
2506     is_nucleomorph = FALSE;
2507 
2508     for (tfp = tdp->status; tfp != NULL; tfp = tfp->next) {
2509 
2510       /*
2511       val = tfp->Value_value;
2512       if (val != NULL && val->choice == Value_value_bool) {
2513         str = tfp->property;
2514         if (str == NULL) {
2515           str = "?";
2516         }
2517         if (val->data.intvalue != 0) {
2518           ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_TaxonomyLookupProblem, "'%s' TRUE", str);
2519         } else {
2520           ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_TaxonomyLookupProblem, "'%s' FALSE", str);
2521         }
2522       }
2523       */
2524 
2525       if (StringICmp (tfp->property, "is_species_level") == 0) {
2526         val = tfp->Value_value;
2527         if (val != NULL && val->choice == Value_value_bool) {
2528           is_species_level = (Boolean) (val->data.intvalue != 0);
2529           if (! is_species_level) {
2530             gc.entityID = tvp->entityID;
2531             gc.itemID = tvp->itemID;
2532             gc.thistype = tvp->itemtype;
2533 
2534             ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_TaxonomyLookupProblem, "Taxonomy lookup reports is_species_level FALSE");
2535           }
2536         }
2537       } else if (StringICmp (tfp->property, "force_consult") == 0) {
2538         val = tfp->Value_value;
2539         if (val != NULL && val->choice == Value_value_bool) {
2540           force_tax_consult = (Boolean) (val->data.intvalue != 0);
2541           if (force_tax_consult) {
2542             gc.entityID = tvp->entityID;
2543             gc.itemID = tvp->itemID;
2544             gc.thistype = tvp->itemtype;
2545 
2546             ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_TaxonomyLookupProblem, "Taxonomy lookup reports taxonomy consultation needed");
2547           }
2548         }
2549       } else if (StringICmp (tfp->property, "has_nucleomorphs") == 0) {
2550         val = tfp->Value_value;
2551         if (val != NULL && val->choice == Value_value_bool) {
2552           has_nucleomorphs = (Boolean) (val->data.intvalue != 0);
2553           if (has_nucleomorphs) {
2554             is_nucleomorph = TRUE;
2555           }
2556         }
2557       }
2558     }
2559     if (tvp->organelle == GENOME_nucleomorph && (! is_nucleomorph)) {
2560       ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_TaxonomyLookupProblem, "Taxonomy lookup does not have expected nucleomorph flag");
2561     }
2562   }
2563 
2564   Taxon3ReplyFree (t3ry);
2565   ValNodeFreeData (srclist.head);
2566 
2567   /* also validate specific-host values */
2568 
2569   ReportBadSpecificHostValues (sep, vsp);
2570 }
2571 
2572 static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck, FormActnFunc revalProc, FormActnFunc doneProc)
2573 
2574 {
2575   Boolean         allRawOrSeg = TRUE;
2576   BaseFormPtr     bfp;
2577   Char            buf [32];
2578   Int2            errors;
2579   Int2            j;
2580   ErrHookProc     oldErrHook;
2581   ErrSev          oldErrSev;
2582   SeqEntryPtr     sep;
2583   Char            str [32];
2584   WindoW          validatorWindow = NULL;
2585   Int2            verbosity;
2586   ValidStructPtr  vsp;
2587 
2588   bfp = (BaseFormPtr) GetObjectExtra (f);
2589   if (bfp != NULL) {
2590     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2591     if (sep != NULL) {
2592       /*
2593       if (! EntrezIsInited ()) {
2594         SequinEntrezInit ("Sequin", FALSE, NULL);
2595       }
2596       */
2597       vsp = ValidStructNew ();
2598       if (vsp != NULL) {
2599         WatchCursor ();
2600         Update ();
2601         /*SetChecklistValue (checklistForm, 6);*/
2602 
2603        verbosity = 1;
2604        if (GetSequinAppParam ("SETTINGS", "VALIDATEVERBOSITY", NULL, buf, sizeof (buf))) {
2605           if (! StrToInt (buf, &verbosity)) {
2606             verbosity = 1;
2607           }
2608         }
2609 
2610         validatorWindow = CreateValidateWindowExExEx (ValidNotify, "Sequin Validation Errors",
2611                                                   programFont, SEV_INFO, verbosity, bfp,
2612                                                   revalProc, doneProc, 
2613                                                   doneProc == NULL && OkToSequester () ? SequesterSequenceList : NULL,
2614                                                   TRUE);
2615         ClearValidateWindow ();
2616         SeqEntryExplore (sep, (Pointer) (&allRawOrSeg), CheckForCookedBioseqs);
2617         if (allRawOrSeg) {
2618           vsp->useSeqMgrIndexes = TRUE;
2619         }
2620         if (indexerVersion) {
2621           vsp->alwaysRequireIsoJTA = TRUE;
2622           vsp->farFetchCDSproducts = TRUE;
2623           vsp->farFetchMRNAproducts = TRUE;
2624         }
2625         vsp->validationLimit = limit;
2626         HideValidateDoc ();
2627         vsp->suppressContext = ShouldSetSuppressContext ();
2628         vsp->justShowAccession = ShouldSetJustShowAccession ();
2629         if (doAligns) {
2630           vsp->validateAlignments = TRUE;
2631           vsp->alignFindRemoteBsp = TRUE;
2632           vsp->doSeqHistAssembly = TRUE;
2633           vsp->farIDsInAlignments = (Boolean) (subtoolMode || smartnetMode || dirsubMode);
2634           if (GetSequinAppParam ("SETTINGS", "VALIDATEFARALIGNIDS", NULL, str, sizeof (str))) {
2635             if (StringICmp (str, "TRUE") == 0) {
2636               vsp->farIDsInAlignments = TRUE;
2637             }
2638           }
2639         }
2640         if (useEntrez && inferenceAccnCheck) {
2641           LookupFarSeqIDs (sep, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2642           vsp->inferenceAccnCheck = TRUE;
2643         }
2644         vsp->testLatLonSubregion = testLatLonSubregion;
2645         vsp->strictLatLonCountry = strictLatLonCountry;
2646         vsp->indexerVersion = indexerVersion;
2647         oldErrHook = ErrSetHandler (ValidErrHook);
2648         oldErrSev = ErrSetMessageLevel (SEV_NONE);
2649         for (j = 0; j < 6; j++) {
2650           vsp->errors [j] = 0;
2651         }
2652         vsp->errfunc = ValidErrCallback;
2653         ValidateSeqEntry (sep, vsp);
2654         if (indexerVersion && useEntrez) {
2655           SetTitle (validatorWindow, "Validating Taxonomy");
2656           Update ();
2657           TaxonValidate (sep, vsp);
2658           SetTitle (validatorWindow, "Sequin Validation Errors");
2659           Update ();
2660         }
2661         ErrSetMessageLevel (oldErrSev);
2662         ErrSetHandler (oldErrHook);
2663         ErrClear ();
2664         ShowValidateDoc ();
2665         errors = 0;
2666         for (j = 0; j < 6; j++) {
2667           errors += vsp->errors [j];
2668         }
2669         if (errors == 0) {
2670           ArrowCursor ();
2671           Message (MSG_OK, "Validation test succeeded.");
2672           FreeValidateWindow ();
2673         } else {
2674           RepopulateValidateFilter ();
2675         }
2676         ValidStructFree (vsp);
2677         /*SetChecklistValue (checklistForm, 5);*/
2678         ArrowCursor ();
2679         Update ();
2680       }
2681     }
2682   }
2683 }
2684 
2685 
2686 static void ValSeqEntryFormEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck)
2687 
2688 {
2689   ValSeqEntryFormExEx (f, doAligns, limit, inferenceAccnCheck, ValSeqEntryForm, NULL);
2690 }
2691 
2692 static void CountInfAccnVer (SeqFeatPtr sfp, Pointer userdata)
2693 
2694 {
2695   Int4Ptr    countP;
2696   GBQualPtr  gbq;
2697 
2698   if (sfp == NULL || userdata == NULL) return;
2699   countP = (Int4Ptr) userdata;
2700 
2701   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
2702     if (StringICmp (gbq->qual, "inference") == 0) {
2703       (*countP)++;
2704     }
2705   }
2706 }
2707 
2708 static Boolean SmallInferenceAccnVer (ForM f)
2709 
2710 {
2711   BaseFormPtr  bfp;
2712   Int4         count = 0;
2713   SeqEntryPtr  sep;
2714 
2715   bfp = (BaseFormPtr) GetObjectExtra (f);
2716   if (bfp == NULL) return FALSE;
2717 
2718   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2719   if (sep == NULL) return FALSE;
2720 
2721   VisitFeaturesInSep (sep, (Pointer) &count, CountInfAccnVer);
2722 
2723   if (count < 100) return TRUE;
2724 
2725   if (indexerVersion) {
2726     Message (MSG_POST, "Validation skipping %ld inference accession.version tests",
2727              (long) count);
2728   }
2729 
2730   return FALSE;
2731 }
2732 
2733 extern void ValSeqEntryForm (ForM f)
2734 
2735 {
2736   Boolean  inferenceAccnCheck;
2737 
2738   inferenceAccnCheck = SmallInferenceAccnVer (f);
2739   ValSeqEntryFormEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck);
2740 }
2741 
2742 static void ValSeqEntryProc (IteM i)
2743 
2744 {
2745   BaseFormPtr  bfp;
2746   Boolean      inferenceAccnCheck;
2747 
2748 #ifdef WIN_MAC
2749   bfp = (BaseFormPtr) currentFormDataPtr;
2750 #else
2751   bfp = (BaseFormPtr) GetObjectExtra (i);
2752 #endif
2753   if (bfp != NULL) {
2754     inferenceAccnCheck = SmallInferenceAccnVer (bfp->form);
2755     ValSeqEntryFormEx (bfp->form, TRUE, VALIDATE_ALL, inferenceAccnCheck);
2756   }
2757 }
2758 
2759 static void ValSeqEntryProcNoAln (IteM i)
2760 
2761 {
2762   BaseFormPtr  bfp;
2763 
2764 #ifdef WIN_MAC
2765   bfp = (BaseFormPtr) currentFormDataPtr;
2766 #else
2767   bfp = (BaseFormPtr) GetObjectExtra (i);
2768 #endif
2769   if (bfp != NULL) {
2770     ValSeqEntryFormEx (bfp->form, FALSE, VALIDATE_ALL, FALSE);
2771   }
2772 }
2773 
2774 static void ValSeqEntryProcInfAccn (IteM i)
2775 
2776 {
2777   BaseFormPtr  bfp;
2778 
2779 #ifdef WIN_MAC
2780   bfp = (BaseFormPtr) currentFormDataPtr;
2781 #else
2782   bfp = (BaseFormPtr) GetObjectExtra (i);
2783 #endif
2784   if (bfp != NULL) {
2785     ValSeqEntryFormEx (bfp->form, FALSE, VALIDATE_ALL, TRUE);
2786   }
2787 }
2788 
2789 static void ValSeqEntryProcSpec (IteM i, Int2 limit)
2790 
2791 {
2792   BaseFormPtr  bfp;
2793 
2794 #ifdef WIN_MAC
2795   bfp = (BaseFormPtr) currentFormDataPtr;
2796 #else
2797   bfp = (BaseFormPtr) GetObjectExtra (i);
2798 #endif
2799   if (bfp != NULL) {
2800     ValSeqEntryFormEx (bfp->form, FALSE, limit, FALSE);
2801   }
2802 }
2803 
2804 static void ValSeqEntryProcInst (IteM i)
2805 
2806 {
2807   ValSeqEntryProcSpec (i, VALIDATE_INST);
2808 }
2809 
2810 static void ValSeqEntryProcHist (IteM i)
2811 
2812 {
2813   ValSeqEntryProcSpec (i, VALIDATE_HIST);
2814 }
2815 
2816 static void ValSeqEntryProcContext (IteM i)
2817 
2818 {
2819   ValSeqEntryProcSpec (i, VALIDATE_CONTEXT);
2820 }
2821 
2822 static void ValSeqEntryProcGraph (IteM i)
2823 
2824 {
2825   ValSeqEntryProcSpec (i, VALIDATE_GRAPH);
2826 }
2827 
2828 static void ValSeqEntryProcSet (IteM i)
2829 
2830 {
2831   ValSeqEntryProcSpec (i, VALIDATE_SET);
2832 }
2833 
2834 static void ValSeqEntryProcFeat (IteM i)
2835 
2836 {
2837   ValSeqEntryProcSpec (i, VALIDATE_FEAT);
2838 }
2839 
2840 static void ValSeqEntryProcDesc (IteM i)
2841 
2842 {
2843   ValSeqEntryProcSpec (i, VALIDATE_DESC);
2844 }
2845 
2846 #ifdef USE_SPELL
2847 static void SpellCheckTheForm (ForM f)
2848 
2849 {
2850   Boolean         allRawOrSeg = TRUE;
2851   BaseFormPtr     bfp;
2852   Char            buf [32];
2853   Int2            errors;
2854   Int2            j;
2855   MonitorPtr      mon;
2856   ErrHookProc     oldErrHook;
2857   ErrSev          oldErrSev;
2858   SeqEntryPtr     sep;
2859   Int2            verbosity;
2860   ValidStructPtr  vsp;
2861 
2862   bfp = (BaseFormPtr) GetObjectExtra (f);
2863   if (bfp != NULL) {
2864     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2865     if (sep != NULL) {
2866       WatchCursor ();
2867       Update ();
2868       vsp = ValidStructNew ();
2869       if (vsp != NULL) {
2870         /*SetChecklistValue (checklistForm, 6);*/
2871         mon = MonitorStrNewEx ("SpellCheck", 40, FALSE);
2872         MonitorStrValue (mon, "Connecting to Spell");
2873         Update ();
2874         if (! SpellInit ()) {
2875           /*SetChecklistValue (checklistForm, 5);*/
2876           ArrowCursor ();
2877           MonitorFree (mon);
2878           Update ();
2879           Message (MSG_ERROR, "Unable to initialize Spell service.");
2880           Update ();
2881           return;
2882         }
2883         MonitorStrValue (mon, "Performing Spell Check");
2884         Update ();
2885         vsp->spellfunc = SpellCheck;
2886         vsp->spellcallback = SpellCallBack;
2887         vsp->onlyspell = TRUE;
2888         vsp->justwarnonspell = TRUE;
2889 
2890        verbosity = 1;
2891        if (GetSequinAppParam ("SETTINGS", "VALIDATEVERBOSITY", NULL, buf, sizeof (buf))) {
2892           if (! StrToInt (buf, &verbosity)) {
2893             verbosity = 1;
2894           }
2895         }
2896 
2897         CreateValidateWindowEx (ValidNotify, "Sequin Spell Check Errors",
2898                                 programFont, SEV_INFO, verbosity, bfp, SpellCheckTheForm, TRUE);
2899         ClearValidateWindow ();
2900         SeqEntryExplore (sep, (Pointer) (&allRawOrSeg), CheckForCookedBioseqs);
2901         if (allRawOrSeg) {
2902           vsp->useSeqMgrIndexes = TRUE;
2903         }
2904         HideValidateDoc ();
2905         vsp->suppressContext = ShouldSetSuppressContext ();
2906         vsp->justShowAccession = ShouldSetJustShowAccession ();
2907         oldErrHook = ErrSetHandler (ValidErrHook);
2908         oldErrSev = ErrSetMessageLevel (SEV_NONE);
2909         for (j = 0; j < 6; j++) {
2910           vsp->errors [j] = 0;
2911         }
2912         vsp->errfunc = ValidErrCallback;
2913         ValidateSeqEntry (sep, vsp);
2914         ErrSetMessageLevel (oldErrSev);
2915         ErrSetHandler (oldErrHook);
2916         ErrClear ();
2917         ShowValidateDoc ();
2918         errors = 0;
2919         for (j = 0; j < 6; j++) {
2920           errors += vsp->errors [j];
2921         }
2922         if (errors == 0) {
2923           ArrowCursor ();
2924           Message (MSG_OK, "Spelling check succeeded.");
2925           FreeValidateWindow ();
2926         } else {
2927           RepopulateValidateFilter ();
2928         }
2929         ValidStructFree (vsp);
2930         MonitorStrValue (mon, "Closing Spell Check");
2931         Update ();
2932         SpellFini ();
2933         /*SetChecklistValue (checklistForm, 5);*/
2934         MonitorFree (mon);
2935       }
2936       ArrowCursor ();
2937       Update ();
2938     }
2939   }
2940 }
2941 
2942 static void SpellCheckSeqEntryProc (IteM i)
2943 
2944 {
2945   BaseFormPtr  bfp;
2946 
2947 #ifdef WIN_MAC
2948   bfp = (BaseFormPtr) currentFormDataPtr;
2949 #else
2950   bfp = (BaseFormPtr) GetObjectExtra (i);
2951 #endif
2952   if (bfp != NULL) {
2953     SpellCheckTheForm (bfp->form);
2954   }
2955 }
2956 #endif
2957 
2958 extern Int4 MySeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip, Boolean correct, Boolean force, Boolean dotaxon);
2959 extern Int4 MySeqEntryToAsn3 (SeqEntryPtr sep, Boolean strip, Boolean correct, Boolean force)
2960 
2961 {
2962   Boolean  dotaxon;
2963 
2964   dotaxon = FALSE;
2965 /*#ifdef INTERNAL_NCBI_SEQUIN*/
2966   if (indexerVersion) {
2967     if (subtoolMode || smartnetMode) {
2968       dotaxon = TRUE;
2969     }
2970   }
2971 /*#endif*/
2972   return MySeqEntryToAsn3Ex (sep, strip, correct, force, dotaxon);
2973 }
2974 
2975 static Int2  onthisline;
2976 static Int2  remaining;
2977 
2978 static void AddMessageToString (CharPtr str, ValNodePtr vnp)
2979 
2980 {
2981   if (str != NULL && vnp != NULL) {
2982     StringCat (str, (CharPtr) vnp->data.ptrvalue);
2983     onthisline++;
2984     remaining--;
2985     if (remaining == 0) {
2986       StringCat (str, "\n\n");
2987     } else if (onthisline < 3) {
2988       StringCat (str, ", ");
2989     } else {
2990       StringCat (str, ",\n");
2991       onthisline = 0;
2992     }
2993   }
2994 }
2995 
2996 static Boolean DisplayTestResults (ValNodePtr head)
2997 
2998 {
2999   MsgAnswer    ans;
3000   Int2         errors;
3001   size_t       len;
3002   CharPtr      str;
3003   ValNodePtr   vnp;
3004   Int2         warnings;
3005 
3006   if (head != NULL) {
3007 
3008     vnp = head;
3009     len = 200;
3010     while (vnp != NULL) {
3011       len += StringLen ((CharPtr) vnp->data.ptrvalue) + 2;
3012       vnp = vnp->next;
3013     }
3014 
3015     errors = 0;
3016     warnings = 0;
3017     vnp = head;
3018     while (vnp != NULL) {
3019       if (vnp->choice == 0) {
3020         warnings++;
3021       } else {
3022         errors++;
3023       }
3024       vnp = vnp->next;
3025     }
3026 
3027     str = MemNew (len + 2);
3028     if (str == NULL) return TRUE;
3029     str [0] = '\0';
3030 
3031     if (errors > 0) {
3032       StringCat (str, "The following essential information is missing:\n\n");
3033       onthisline = 0;
3034       remaining = errors;
3035       vnp = head;
3036       while (vnp != NULL) {
3037         if (vnp->choice != 0) {
3038           AddMessageToString (str, vnp);
3039         }
3040         vnp = vnp->next;
3041       }
3042       StringCat (str, "Please fill in the essential information.");
3043       ans = Message (MSG_OK, str);
3044       str = MemFree (str);
3045       return FALSE;
3046     }
3047 
3048     if (warnings > 0 && (! indexerVersion)) {
3049       StringCat (str, "The following desired information is missing:\n\n");
3050       onthisline = 0;
3051       remaining = warnings;
3052       vnp = head;
3053       while (vnp != NULL) {
3054         if (vnp->choice == 0) {
3055           AddMessageToString (str, vnp);
3056         }
3057         vnp = vnp->next;
3058       }
3059       StringCat (str, "Do you wish to proceed anyway?");
3060       ans = Message (MSG_YN, str);
3061       str = MemFree (str);
3062       if (ans == ANS_NO) return FALSE;
3063       return TRUE;
3064     }
3065 
3066     str = MemFree (str);
3067   }
3068   return TRUE;
3069 }
3070 
3071 extern void JustRegisterSeqEntry (BaseFormPtr bfp, Boolean freeit)
3072 
3073 {
3074   Int2  handled;
3075 
3076   if (bfp != NULL) {
3077     Hide (bfp->form);
3078   }
3079   seqviewprocs.filepath = globalPath;
3080   seqviewprocs.forceSeparateViewer = TRUE;
3081   SeqEntrySetScope (NULL);
3082   handled = GatherProcLaunch (OMPROC_VIEW, FALSE, globalEntityID, 1,
3083                               OBJ_BIOSEQ, 0, 0, OBJ_BIOSEQ, 0);
3084   seqviewprocs.filepath = NULL;
3085   ArrowCursor ();
3086   if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
3087     Message (MSG_FATAL, "Unable to launch viewer.");
3088   } else {
3089     SendHelpScrollMessage (helpForm, "Editing the Record", NULL);
3090   }
3091   ObjMgrSetOptions (OM_OPT_FREE_IF_NO_VIEW, globalEntityID);
3092   ObjMgrSetDirtyFlag (globalEntityID, TRUE);
3093   if (bfp != NULL && freeit) {
3094     Remove (bfp->form);
3095   }
3096 }
3097 
3098 extern void JustRegisterSeqEntryBtn (ButtoN b)
3099 
3100 {
3101   BaseFormPtr  bfp;
3102 
3103   bfp = (BaseFormPtr) GetObjectExtra (b);
3104   JustRegisterSeqEntry (bfp, TRUE);
3105 }
3106 
3107 static void JustRegisterSeqEntryForm (ForM f)
3108 
3109 {
3110   BaseFormPtr  bfp;
3111 
3112   bfp = (BaseFormPtr) GetObjectExtra (f);
3113   JustRegisterSeqEntry (bfp, FALSE);
3114 }
3115 
3116 extern void AddSubmitBlockToSeqEntry (ForM f)
3117 
3118 {
3119   AffilPtr        affil;
3120   AuthListPtr     authors;
3121   BaseFormPtr     bfp;
3122   CitSubPtr       csp;
3123   ValNodePtr      head;
3124   SubmitBlockPtr  sbp;
3125   SeqSubmitPtr    ssp;
3126   CitSubPtr       tmp;
3127 
3128   bfp = (BaseFormPtr) GetObjectExtra (f);
3129   if (bfp != NULL) {
3130     head = TestForm (bfp->form);
3131     if (head != NULL) {
3132       if (! DisplayTestResults (head)) {
3133         ValNodeFreeData (head);
3134         return;
3135       }
3136       ValNodeFreeData (head);
3137     }
3138     Hide (bfp->form);
3139     /*
3140     globalsbp = (SequinBlockPtr) FormToPointer (bfp->form);
3141     if (globalsbp == NULL) {
3142       Message (MSG_OK, "Record will be a Seq-entry instead of a Seq-submit.");
3143     }
3144     */
3145     sbp = (SubmitBlockPtr) FormToPointer (bfp->form);
3146     if (sbp == NULL) {
3147       Message (MSG_OK, "Record will be a Seq-entry instead of a Seq-submit.");
3148     }
3149     Update ();
3150     /*
3151     globalEntityID = PackageFormResults (globalsbp, globalsep, FALSE);
3152     */
3153     globalEntityID = 0;
3154     if (globalsep != NULL) {
3155       if (sbp != NULL) {
3156         if (sbp->contact != NULL && sbp->cit != NULL) {
3157           tmp = CitSubFromContactInfo (sbp->contact);
3158           csp = sbp->cit;
3159           if (csp->authors != NULL) {
3160             authors = csp->authors;
3161             if (authors->affil == NULL) {
3162               if (tmp != NULL && tmp->authors != NULL) {
3163                 authors = tmp->authors;
3164                 affil = authors->affil;
3165                 authors->affil = NULL;
3166                 authors = csp->authors;
3167                 authors->affil = affil;
3168                 if (affil != NULL) {
3169                   affil->phone = MemFree (affil->phone);
3170                   affil->fax = MemFree (affil->fax);
3171                   affil->email = MemFree (affil->email);
3172                 }
3173               }
3174             }
3175           }
3176           CitSubFree (tmp);
3177         }
3178         ssp = SeqSubmitNew ();
3179         if (ssp != NULL) {
3180           ssp->datatype = 1;
3181           ssp->sub = sbp;
3182           ssp->data = (Pointer) globalsep;
3183           ObjMgrConnect (OBJ_SEQENTRY, globalsep->data.ptrvalue, OBJ_SEQSUB, (Pointer) ssp);
3184           if (! ObjMgrRegister (OBJ_SEQSUB, (Pointer) ssp)) {
3185             ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrRegister failed.");
3186           }
3187         } else {
3188           if (! ObjMgrRegister (OBJ_SEQENTRY, (Pointer) globalsep)) {
3189             ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrRegister failed.");
3190           }
3191         }
3192       } else {
3193         if (! ObjMgrRegister (OBJ_SEQENTRY, (Pointer) globalsep)) {
3194           ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrRegister failed.");
3195         }
3196       }
3197       if (EntrezASN1Detected (globalsep)) {
3198         ErrPostEx (SEV_WARNING, 0, 0, "This record was retrieved from Entrez.");
3199       }
3200       globalEntityID = ObjMgrGetEntityIDForChoice (globalsep);
3201     }
3202     globalsbp = NULL;
3203     globalsep = NULL;
3204     JustRegisterSeqEntryForm (f);
3205   }
3206 }
3207 
3208 #ifdef WIN_MAC
3209 static void SubmitBlockActivateProc (WindoW w);
3210 static void GenomeFormActivateProc (WindoW w);
3211 #else
3212 #define SubmitBlockActivateProc NULL
3213 #define GenomeFormActivateProc NULL
3214 #endif
3215 
3216 CharPtr repackageMsg =
3217 "Do you plan to submit this as an update to one of the databases?";
3218 
3219 extern Boolean ProcessOneNucleotideTitle (Int2 seqPackage,
3220                                           SeqEntryPtr nsep, SeqEntryPtr top);
3221 
3222 static void LookForTaxonID (BioSourcePtr biop, Pointer userdata)
3223 
3224 {
3225   DbtagPtr     dbt;
3226   BoolPtr      notaxid;
3227   ObjectIdPtr  oip;
3228   OrgRefPtr    orp;
3229   ValNodePtr   vnp;
3230 
3231   notaxid = (BoolPtr) userdata;
3232   if (biop == NULL) return;
3233   orp = biop->org;
3234   if (orp == NULL) return;
3235   for (vnp = orp->db; vnp != NULL; vnp = vnp->next) {
3236     dbt = (DbtagPtr) vnp->data.ptrvalue;
3237     if (dbt == NULL) continue;
3238     if (StringICmp (dbt->db, "taxon") != 0) continue;
3239     oip = dbt->tag;
3240     if (oip == NULL) continue;
3241     if (oip->id != 0) return;
3242   }
3243   *notaxid = TRUE;
3244 }
3245 
3246 static void RnaProtTrailingCommaFix (SeqFeatPtr sfp, Pointer userdata)
3247 
3248 {
3249   Char        ch;
3250   size_t      len;
3251   ProtRefPtr  prp;
3252   RnaRefPtr   rrp;
3253   CharPtr     str;
3254   ValNodePtr  vnp;
3255 
3256   if (sfp == NULL) return;
3257 
3258   if (sfp->data.choice == SEQFEAT_PROT) {
3259     prp = (ProtRefPtr) sfp->data.value.ptrvalue;
3260     /* turn trailing space into trailing underscore for validator */
3261     for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
3262       str = (CharPtr) vnp->data.ptrvalue;
3263       if (StringHasNoText (str)) continue;
3264       len = StringLen (str);
3265       if (len < 1) continue;
3266       ch = str [len - 1];
3267       while (ch == ' ' && len > 2) {
3268         len--;
3269         ch = str [len - 1];
3270       }
3271       if (ch == ',') {
3272         str [len - 1] = '_';
3273         str [len] = '\0';
3274       }
3275     }
3276   } else if (sfp->data.choice == SEQFEAT_RNA) {
3277     rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
3278     /* turn trailing space into trailing underscore for validator */
3279     if (rrp->ext.choice == 1) {
3280       str = rrp->ext.value.ptrvalue;
3281       if (StringDoesHaveText (str)) {
3282         len = StringLen (str);
3283         if (len > 0) {
3284           ch = str [len - 1];
3285           while (ch == ' ' && len > 2) {
3286             len--;
3287             ch = str [len - 1];
3288           }
3289           if (ch == ',') {
3290             str [len - 1] = '_';
3291             str [len] = '\0';
3292           }
3293         }
3294       }
3295     }
3296   }
3297 }
3298 
3299 static Boolean HandleOneNewAsnProcEx (BaseFormPtr bfp, Boolean removeold, Boolean askForSubmit,
3300                                     CharPtr path, Pointer dataptr, Uint2 datatype, Uint2 entityID,
3301                                     Uint2Ptr updateEntityIDPtr, ValNodePtr PNTR err_list)
3302 
3303 {
3304   BioseqPtr     bsp;
3305   BioseqSetPtr  bssp;
3306   Int2          handled;
3307   Boolean       notaxid;
3308   SeqEntryPtr   nsep;
3309   Boolean       processonenuc;
3310   SeqEntryPtr   sep;
3311   ForM          w;
3312 
3313   if (dataptr != NULL && entityID > 0) {
3314     if (datatype == OBJ_SEQSUB || datatype == OBJ_SEQENTRY ||
3315         datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET) {
3316       WatchCursor ();
3317       sep = GetTopSeqEntryForEntityID (entityID);
3318       if (sep == NULL) {
3319         sep = SeqEntryNew ();
3320         if (sep != NULL) {
3321           if (datatype == OBJ_BIOSEQ) {
3322             bsp = (BioseqPtr) dataptr;
3323             sep->choice = 1;
3324             sep->data.ptrvalue = bsp;
3325             SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, sep);
3326           } else if (datatype == OBJ_BIOSEQSET) {
3327             bssp = (BioseqSetPtr) dataptr;
3328             sep->choice = 2;
3329             sep->data.ptrvalue = bssp;
3330             SeqMgrSeqEntry (SM_BIOSEQSET, (Pointer) bssp, sep);
3331           } else {
3332             sep = SeqEntryFree (sep);
3333           }
3334         }
3335         sep = GetTopSeqEntryForEntityID (entityID);
3336       }
3337       if (sep != NULL) {
3338         VisitFeaturesInSep (sep, NULL, RnaProtTrailingCommaFix);
3339         /*
3340         if (seqviewprocs.lockFarComponents) {
3341           bsplist = LockFarComponents (sep);
3342         }
3343         */
3344         nsep = FindNucSeqEntry (sep);
3345         processonenuc = TRUE;
3346         if (IS_Bioseq_set (sep)) {
3347           bssp = (BioseqSetPtr) sep->data.ptrvalue;
3348           if (bssp != NULL) {
3349             if (IsPopPhyEtcSet (bssp->_class)) {
3350               processonenuc = FALSE;
3351             } else if (bssp->_class == 7) {
3352               processonenuc = FALSE;
3353             } else if (bssp->_class == 1 || bssp->_class == 2) {
3354               processonenuc = FALSE;
3355             } else if (bssp->_class == BioseqseqSet_class_gen_prod_set) {
3356               processonenuc = FALSE;
3357             } else if (bssp->_class == 0) {
3358               processonenuc = FALSE;
3359             } else if (bssp->_class == 255) {
3360               processonenuc = FALSE;
3361             }
3362           }
3363         }
3364         if (processonenuc) {
3365           ProcessOneNucleotideTitle (SEQ_PKG_SINGLE, nsep, sep);
3366         }
3367         if (! leaveAsOldAsn) {
3368           notaxid = FALSE;
3369           VisitBioSourcesInSep (sep, (Pointer) &notaxid, LookForTaxonID);
3370           if (notaxid) {
3371             MySeqEntryToAsn3 (sep, TRUE, FALSE, FALSE);
3372           }
3373         }
3374       }
3375       if (sep != NULL) {
3376         if (EntrezASN1Detected (sep)) {
3377           ErrPostEx (SEV_WARNING, 0, 0, "This record was retrieved from Entrez");
3378         }
3379       }
3380       if ((! indexerVersion) && askForSubmit && datatype != OBJ_SEQSUB) {
3381         ArrowCursor ();
3382         Update ();
3383         if (Message (MSG_YN, repackageMsg) == ANS_YES) {
3384           /*
3385           UnlockFarComponents (bsplist);
3386           */
3387           globalEntityID = entityID;
3388           globalsep = sep;
3389           StringNCpy_0 (globalPath, path, sizeof (globalPath));
3390           WatchCursor ();
3391           Update ();
3392           w = CreateSubmitBlockForm (-50, -33, "Submitting Authors",
3393                                      FALSE, TRUE, NULL, JustRegisterSeqEntryBtn,
3394                                      AddSubmitBlockToSeqEntry);
3395           ArrowCursor ();
3396           if (w != NULL) {
3397             Show (w);
3398             Select (w);
3399             SendHelpScrollMessage (helpForm, "Submitting Authors Form", NULL);
3400             return TRUE;
3401           } else {
3402             Message (MSG_FATAL, "Unable to create window.");
3403             return FALSE;
3404           }
3405         }
3406       }
3407       seqviewprocs.filepath = path;
3408       seqviewprocs.forceSeparateViewer = TRUE;
3409       SeqEntrySetScope (NULL);
3410       handled = GatherProcLaunch (OMPROC_VIEW, FALSE, entityID, 1,
3411                                   OBJ_BIOSEQ, 0, 0, OBJ_BIOSEQ, 0);
3412       seqviewprocs.filepath = NULL;
3413       /*
3414       UnlockFarComponents (bsplist);
3415       */
3416       ArrowCursor ();
3417       if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
3418         Message (MSG_FATAL, "Unable to launch viewer.");
3419         return FALSE;
3420       } else {
3421         SendHelpScrollMessage (helpForm, "Editing the Record", NULL);
3422       }
3423       ObjMgrSetOptions (OM_OPT_FREE_IF_NO_VIEW, entityID);
3424       ObjMgrSetDirtyFlag (entityID, TRUE);
3425       if (bfp != NULL && removeold) {
3426         Remove (bfp->form);
3427       }
3428       return TRUE;
3429     } else if (datatype == OBJ_SEQANNOT && dataptr != NULL) {
3430       entityID = 0;
3431       if (bfp != NULL) {
3432         entityID = bfp->input_entityID;
3433       }
3434       SeqEntrySetScope (NULL);
3435       entityID = SmartAttachSeqAnnotToSeqEntry (entityID, (SeqAnnotPtr) dataptr, err_list);
3436       ArrowCursor ();
3437       if (entityID != 0) {
3438         /* code to inhibit multiple updates when attaching multiple feature tables to the same entity */
3439         if (updateEntityIDPtr != NULL) {
3440           if (*updateEntityIDPtr == 0) {
3441             *updateEntityIDPtr = entityID;
3442             return TRUE;
3443           } else if (*updateEntityIDPtr == entityID) {
3444             return TRUE;
3445           }
3446         }
3447         ObjMgrSetDirtyFlag (entityID, TRUE);
3448         ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
3449         return TRUE;
3450       }
3451     } else if (datatype == OBJ_PROJECT && dataptr != NULL) {
3452       SeqEntrySetScope (NULL);
3453       HandleProjectAsn ((ProjectPtr) dataptr, entityID);
3454       ArrowCursor ();
3455       return TRUE;
3456     } else {
3457       Message (MSG_ERROR, "Unable to process object type %d.", (int) datatype);
3458       ObjMgrDelete (datatype, dataptr);
3459     }
3460   }
3461   return FALSE;
3462 }
3463 
3464 static Boolean HandleOneNewAsnProc (BaseFormPtr bfp, Boolean removeold, Boolean askForSubmit,
3465                                     CharPtr path, Pointer dataptr, Uint2 datatype, Uint2 entityID,
3466                                     Uint2Ptr updateEntityIDPtr)
3467 {
3468   return HandleOneNewAsnProcEx (bfp, removeold, askForSubmit, path, dataptr, datatype, entityID,
3469                                 updateEntityIDPtr, NULL);
3470 }
3471 
3472 typedef struct multbioseqform {
3473   FORM_MESSAGE_BLOCK
3474 
3475   BaseFormPtr  bfp;
3476   Char         filename [PATH_MAX];
3477   Boolean      removeold;
3478   Boolean      askForSubmit;
3479   ValNodePtr   sephead;
3480 } MultBioseqForm, PNTR MultBioseqFormPtr;
3481 
3482 static void CommonHandleMultBioseqs (ButtoN b, Int2 whichbutton)
3483 
3484 {
3485   BioseqPtr          bsp;
3486   BioseqSetPtr       bssp;
3487   Uint1              choice = 0;
3488   Uint2              datatype = 0;
3489   Uint2              entityID = 0;
3490   Boolean            is_na = TRUE;
3491   SeqEntryPtr        list;
3492   MultBioseqFormPtr  mfp;
3493   SeqEntryPtr        next;
3494   ValNodePtr         pip;
3495   ProjectPtr         proj;
3496   SeqEntryPtr        sep;
3497 
3498   mfp = (MultBioseqFormPtr) GetObjectExtra (b);
3499   if (mfp == NULL || mfp->sephead == NULL) return;
3500   Hide (mfp->form);
3501   Update ();
3502   switch (whichbutton) {
3503     case 1 :
3504       proj = ProjectNew ();
3505       if (proj != NULL) {
3506         pip = ValNodeNew (NULL);
3507         if (pip != NULL) {
3508           bsp = (BioseqPtr) mfp->sephead->data.ptrvalue;
3509           if (bsp != NULL) {
3510             is_na = (Boolean) ISA_na (bsp->mol);
3511           }
3512           if (is_na) {
3513             choice = ProjectItem_nucent;
3514           } else {
3515             choice = ProjectItem_protent;
3516           }
3517           pip->choice = choice;
3518           proj->data = pip;
3519           pip->data.ptrvalue = (Pointer) mfp->sephead;
3520           mfp->sephead = NULL;
3521           HandleProjectAsn (proj, 0);
3522         }
3523       }
3524       break;
3525     case 2 :
3526       list = mfp->sephead;
3527       sep = NULL;
3528       mfp->sephead = NULL;
3529       while (list != NULL) {
3530         next = list->next;
3531         list->next = NULL;
3532         if (sep != NULL) {
3533           AddSeqEntryToSeqEntry (sep, list, TRUE);
3534         } else {
3535           sep = list;
3536         }
3537         list = next;
3538       }
3539       if (sep != NULL) {
3540         if (sep->choice == 1) {
3541           datatype = OBJ_BIOSEQ;
3542         } else if (sep->choice == 2) {
3543           datatype = OBJ_BIOSEQSET;
3544         }
3545         entityID = ObjMgrRegister (datatype, (Pointer) sep->data.ptrvalue);
3546         HandleOneNewAsnProc (mfp->bfp, mfp->removeold, mfp->askForSubmit,
3547                              mfp->filename, (Pointer) sep, OBJ_SEQENTRY,
3548                              entityID, NULL);
3549       }
3550       break;
3551     case 3 :
3552       sep = ValNodeNew (NULL);
3553       if (sep != NULL) {
3554         bssp = BioseqSetNew ();
3555         if (bssp != NULL) {
3556           sep->choice = 2;
3557           sep->data.ptrvalue = (Pointer) bssp;
3558           bssp->_class = 14;
3559           bssp->seq_set = mfp->sephead;
3560           mfp->sephead = NULL;
3561           SeqMgrSeqEntry (SM_BIOSEQSET, (Pointer) bssp, sep);
3562           SeqMgrLinkSeqEntry (sep, 0, NULL);
3563           entityID = ObjMgrRegister (OBJ_SEQENTRY, (Pointer) sep);
3564           HandleOneNewAsnProc (mfp->bfp, mfp->removeold, mfp->askForSubmit,
3565                                mfp->filename, (Pointer) sep, OBJ_SEQENTRY,
3566                                entityID, NULL);
3567         }
3568       }
3569       break;
3570     default :
3571       break;
3572   }
3573   ArrowCursor ();
3574   Remove (mfp->form);
3575   Update ();
3576 }
3577 
3578 static void MultToDocSum (ButtoN b)
3579 
3580 {
3581   CommonHandleMultBioseqs (b, 1);
3582 }
3583 
3584 static void MultToSegSeq (ButtoN b)
3585 
3586 {
3587   CommonHandleMultBioseqs (b, 2);
3588 }
3589 
3590 static void MultToPopSet (ButtoN b)
3591 
3592 {
3593   CommonHandleMultBioseqs (b, 3);
3594 }
3595 
3596 static void MultToSingleSeq (ButtoN b)
3597 
3598 {
3599   CommonHandleMultBioseqs (b, 2);
3600 }
3601 
3602 static void MultBioseqFormMessage (ForM f, Int2 mssg)
3603 
3604 {
3605   MultBioseqFormPtr  mfp;
3606 
3607   mfp = (MultBioseqFormPtr) GetObjectExtra (f);
3608   if (mfp != NULL) {
3609     switch (mssg) {
3610       case VIB_MSG_CLOSE :
3611         Remove (f);
3612         break;
3613       default :
3614         if (mfp->appmessage != NULL) {
3615           mfp->appmessage (f, mssg);
3616         }
3617         break;
3618     }
3619   }
3620 }
3621 
3622 static Boolean ProcessMultipleBioseqs (BaseFormPtr bfp, CharPtr filename, Boolean removeold,
3623                                     Boolean askForSubmit, ValNodePtr sephead)
3624 
3625 {
3626   ButtoN             b;
3627   GrouP              c;
3628   MultBioseqFormPtr  mfp;
3629   StdEditorProcsPtr  sepp;
3630   WindoW             w;
3631 #ifndef WIN_MAC
3632   MenU               m;
3633 #endif
3634 
3635   mfp = (MultBioseqFormPtr) MemNew (sizeof (MultBioseqForm));
3636   if (mfp == NULL) return FALSE;
3637 
3638   if (!FixIDsAndTitles (sephead, NULL, TRUE)) {
3639     return FALSE;
3640   }
3641 
3642   w = FixedWindow (-50, -33, -10, -10, "Sequence Input", NULL);
3643   SetObjectExtra (w, mfp, StdCleanupFormProc);
3644   mfp->form = (ForM) w;
3645   mfp->formmessage = MultBioseqFormMessage;
3646 
3647   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3648   if (sepp != NULL) {
3649     SetActivate (w, sepp->activateForm);
3650     mfp->appmessage = sepp->handleMessages;
3651   }
3652 
3653   mfp->bfp = bfp;
3654   mfp->removeold = removeold;
3655   mfp->askForSubmit = askForSubmit;
3656   mfp->sephead = sephead;
3657   StringNCpy_0 (mfp->filename, filename, sizeof (mfp->filename));
3658 
3659 #ifndef WIN_MAC
3660   m = PulldownMenu (w, "File");
3661   FormCommandItem (m, "Close", (BaseFormPtr) mfp, VIB_MSG_CLOSE);
3662 #endif
3663 
3664   c = HiddenGroup (w, 0, 3, NULL);
3665   SetGroupSpacing (c, 10, 10);
3666   b = PushButton (c, "Load into Document Window", MultToDocSum);
3667   SetObjectExtra (b, mfp, NULL);
3668   if (sephead->next != NULL) {
3669     b = PushButton (c, "Load as Segmented Sequence", MultToSegSeq);
3670     SetObjectExtra (b, mfp, NULL);
3671     b = PushButton (c, "Load as Population Study", MultToPopSet);
3672     SetObjectExtra (b, mfp, NULL);
3673   } else {
3674     b = PushButton (c, "Load as Single Sequence", MultToSingleSeq);
3675     SetObjectExtra (b, mfp, NULL);
3676   }
3677 
3678   RealizeWindow (w);
3679   Show (w);
3680   Select (w);
3681   ArrowCursor ();
3682   Update ();
3683   return TRUE;
3684 }
3685 
3686 static void ProcessMultipleSimpleSeqs (BaseFormPtr bfp, CharPtr filename, Boolean removeold,
3687                                        Boolean askForSubmit, ValNodePtr simples)
3688 
3689 {
3690   EntrezGlobalsPtr  egp;
3691 
3692   egp = (EntrezGlobalsPtr) GetAppProperty ("EntrezGlobals");
3693   if (egp == NULL || egp->retrieveSimpleProc == NULL) return;
3694   egp->retrieveSimpleProc (NULL, simples);
3695 }
3696 
3697 static Boolean HandledAnnotatedProteins (BaseFormPtr bfp, ValNodePtr bioseqs)
3698 
3699 {
3700   BioseqPtr    bsp;
3701   Int2         code;
3702   ValNodePtr   descr;
3703   MolInfoPtr   mip;
3704   BioseqPtr    nucbsp;
3705   ValNodePtr   sdp;
3706   SeqEntryPtr  sep;
3707   SeqLocPtr    slp;
3708   CharPtr      title;
3709   SeqEntryPtr  top = NULL;
3710   ValNode      vn;
3711   ValNodePtr   vnp;
3712 
3713   if (bfp == NULL || bioseqs == NULL) return FALSE;
3714   nucbsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
3715   if (nucbsp == NULL) return FALSE;
3716   if (! ISA_na (nucbsp->mol)) return FALSE;
3717   /* top = GetBestTopParentForData (bfp->input_entityID, nucbsp); */
3718   top = GetTopSeqEntryForEntityID (bfp->input_entityID);
3719   if (top == NULL) return FALSE;
3720   for (vnp = bioseqs; vnp != NULL; vnp = vnp->next) {
3721     bsp = (BioseqPtr) vnp->data.ptrvalue;
3722     if (bsp == NULL) return FALSE;
3723     if (! ISA_aa (bsp->mol)) return FALSE;
3724     title = BioseqGetTitle (bsp);
3725     if (title == NULL) return FALSE;
3726     if (StringChr (title, '[') == NULL) return FALSE;
3727   }
3728   code = SeqEntryToGeneticCode (top, NULL, NULL, 0);
3729   SetBatchSuggestNucleotide (nucbsp, code);
3730   descr = ExtractBioSourceAndPubs (top);
3731   vn.choice = SEQLOC_WHOLE;
3732   vn.data.ptrvalue = (Pointer) nucbsp->id;
3733   slp = &vn;
3734   for (vnp = bioseqs; vnp != NULL; vnp = vnp->next) {
3735     bsp = (BioseqPtr) vnp->data.ptrvalue;
3736     bsp->id = SeqIdFree (bsp->id);
3737     bsp->id = MakeNewProteinSeqId (slp, NULL);
3738     SeqMgrReplaceInBioseqIndex (bsp);
3739     sep = SeqMgrGetSeqEntryForData (bsp);
3740     if (sep != NULL) {
3741       mip = MolInfoNew ();
3742       if (mip != NULL) {
3743         mip->biomol = 8;
3744         mip->tech = 13;
3745         sdp = CreateNewDescriptor (sep, Seq_descr_molinfo);
3746         if (sdp != NULL) {
3747           sdp->data.ptrvalue = (Pointer) mip;
3748         }
3749       }
3750       AddSeqEntryToSeqEntry (top, sep, TRUE);
3751       AutomaticProteinProcess (top, sep, code, FALSE, NULL);
3752       ValNodeExtract (&(bsp->descr), Seq_descr_title);
3753     }
3754   }
3755   ClearBatchSuggestNucleotide ();
3756   ReplaceBioSourceAndPubs (top, descr);
3757   return TRUE;
3758 }
3759 
3760 static Boolean DoReadAnythingLoop (BaseFormPtr bfp, CharPtr filename, CharPtr path,
3761                                    Boolean removeold, Boolean askForSubmit, Boolean alwaysMult,
3762                                    Boolean parseFastaSeqId, Boolean fastaAsSimpleSeq)
3763 
3764 {
3765   ValNodePtr     bioseqs;
3766   BioseqPtr      bsp;
3767   Pointer        dataptr;
3768   Uint2          datatype;
3769   Boolean        each;
3770   Uint2          entityID;
3771   FILE           *fp;
3772   ValNodePtr     head = NULL;
3773   ValNodePtr     last = NULL;
3774   OMUserDataPtr  omudp;
3775   ValNodePtr     projects;
3776   Boolean        rsult;
3777   SeqEntryPtr    sep;
3778   SeqEntryPtr    sephead = NULL;
3779   ValNodePtr     simples;
3780   Uint2          updateEntityID;
3781   ValNodePtr     vnp, err_list, vnp_err;
3782   LogInfoPtr     lip;
3783 
3784   if (filename == NULL) return FALSE;
3785   fp = FileOpen (filename, "r");
3786   if (fp != NULL) {
3787     rsult = FALSE;
3788     while ((dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, NULL, FALSE, FALSE,
3789                                               parseFastaSeqId, fastaAsSimpleSeq)) != NULL) {
3790       vnp = ValNodeAddPointer (&last, datatype, dataptr);
3791       if (head == NULL) {
3792         head = vnp;
3793       }
3794       last = vnp;
3795     }
3796     FileClose (fp);
3797     bioseqs = ValNodeExtractList (&head, OBJ_BIOSEQ);
3798     projects = ValNodeExtractList (&head, OBJ_PROJECT);
3799     simples = ValNodeExtractList (&head, OBJ_FASTA);
3800     updateEntityID = 0;
3801     lip = OpenLog ("Errors");
3802     for (vnp = head; vnp != NULL; vnp = vnp->next) {
3803       datatype = vnp->choice;
3804       dataptr = vnp->data.ptrvalue;
3805       entityID = ObjMgrRegister (datatype, dataptr);
3806       
3807       err_list = NULL;
3808       each = HandleOneNewAsnProcEx (bfp, removeold, askForSubmit, path, dataptr, datatype, entityID, &updateEntityID, &err_list);
3809       if (err_list != NULL) {
3810         for (vnp_err = err_list; vnp_err != NULL; vnp_err = vnp_err->next) {
3811           fprintf (lip->fp, "%s\n", vnp_err->data.ptrvalue);
3812           lip->data_in_log = TRUE;
3813         }
3814         err_list = ValNodeFreeData (err_list);
3815         if (datatype == OBJ_SEQANNOT) {
3816           ExportSeqAnnotFeatureTable (lip->fp, dataptr);
3817         }
3818       }
3819       removeold = FALSE;
3820       rsult = (Boolean) (rsult || each);
3821       if (backupMode) {
3822         subtoolEntityID = entityID;
3823         omudp = ObjMgrAddUserData (subtoolEntityID, 0, 0, 0);
3824         if (omudp != NULL) {
3825           omudp->messagefunc = BackupModeMsgFunc;
3826         }
3827         subtoolRecordDirty = TRUE;
3828       }      
3829     }
3830     CloseLog (lip);
3831     lip = FreeLog (lip);
3832     ValNodeFree (head);
3833     if (updateEntityID != 0) {
3834       ObjMgrSetDirtyFlag (updateEntityID, TRUE);
3835       ObjMgrSendMsg (OM_MSG_UPDATE, updateEntityID, 0, 0);
3836     }
3837     for (vnp = projects; vnp != NULL; vnp = vnp->next) {
3838       HandleProjectAsn ((ProjectPtr) vnp->data.ptrvalue, 0);
3839     }
3840     ValNodeFree (projects);
3841     if (bioseqs != NULL) {
3842       if (HandledAnnotatedProteins (bfp, bioseqs)) {
3843         rsult = TRUE;
3844         ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3845         ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3846       } else if (bioseqs->next == NULL && (! alwaysMult)) {
3847         bsp = (BioseqPtr) bioseqs->data.ptrvalue;
3848         bioseqs->data.ptrvalue = NULL;
3849         if (bsp != NULL) {
3850           sep = SeqMgrGetSeqEntryForData (bsp);
3851           if (sep == NULL) {
3852             sep = SeqEntryNew ();
3853             if (sep != NULL) {
3854               sep->choice = 1;
3855               sep->data.ptrvalue = bsp;
3856               SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, sep);
3857             }
3858           }
3859         }
3860         entityID = ObjMgrRegister (OBJ_BIOSEQ, (Pointer) bsp);
3861         each = HandleOneNewAsnProc (bfp, FALSE, FALSE, path, (Pointer) bsp, OBJ_BIOSEQ, entityID, NULL);
3862         removeold = FALSE;
3863         rsult = (Boolean) (rsult || each);
3864       } else {
3865         sephead = NULL;
3866         for (vnp = bioseqs; vnp != NULL; vnp = vnp->next) {
3867           bsp = (BioseqPtr) vnp->data.ptrvalue;
3868           if (bsp != NULL) {
3869             sep = SeqMgrGetSeqEntryForData (bsp);
3870             if (sep == NULL) {
3871               sep = SeqEntryNew ();
3872               if (sep != NULL) {
3873                 sep->choice = 1;
3874                 sep->data.ptrvalue = bsp;
3875                 SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, sep);
3876               }
3877             }
3878             if (sep != NULL) {
3879               ValNodeLink (&sephead, sep);
3880             }
3881           }
3882         }
3883         if (ProcessMultipleBioseqs (bfp, filename, removeold, askForSubmit, sephead)) {
3884           bioseqs = NULL;
3885           rsult = TRUE;
3886         } else {
3887           for (vnp = bioseqs; vnp != NULL; vnp = vnp->next) {
3888             bsp = (BioseqPtr) vnp->data.ptrvalue;
3889             if (bsp != NULL) {
3890               bsp->idx.deleteme = TRUE;
3891             }
3892           }
3893           DeleteMarkedObjects (0, OBJ_SEQENTRY, sephead);
3894         }
3895       }
3896     }
3897     ValNodeFree (bioseqs);
3898     if (simples != NULL) {
3899       ProcessMultipleSimpleSeqs (bfp, filename, removeold, askForSubmit, simples);
3900       rsult = TRUE;
3901     }
3902     ValNodeFree (simples);
3903     return rsult;
3904   }
3905   return FALSE;
3906 }
3907 
3908 /* Sarah's stuff */
3909 
3910 #define SQACT_TXTALN 1
3911 #define SQACT_NOTTXTALN 2
3912 #define SQACT_UNPRINTABLECHARS 3
3913 
3914 static Int4 SQACT_GuessWhatIAm (FILE *fp)
3915 {
3916    Boolean  found;
3917    Int4     len;
3918    CharPtr  line;
3919    Int4     prevlen;
3920    Int4     seq;
3921    CharPtr  tmp;
3922    ValNodePtr current_data = NULL;
3923    CharPtr    cp;
3924 
3925    if (fp == NULL) return SQACT_NOTTXTALN;
3926    line = MyFGetLine (fp, &current_data);
3927    found = FALSE;
3928    while (line != NULL && !found) /* find first non-empty line */
3929    {
3930       if (!StringHasNoText(line))
3931       {
3932          if (StringLen(line) > 0)
3933             found = TRUE;
3934       } 
3935       else
3936       {
3937          MemFree(line);
3938          line = MyFGetLine (fp, &current_data);
3939       }
3940    }
3941    if (!found) 
3942    {
3943      FreeBufferedReadList (current_data);
3944      return -1;
3945    }
3946 
3947    /* look for unprintable characters */      
3948    for (cp = line; *cp != 0; cp++)
3949    {
3950       if ((Int4)(*cp) < 0 || (Int4)(*cp) >= 256 || ! isprint ((Int4)(*cp)) && ! isspace ((Int4)(*cp)))
3951       {
3952          FreeBufferedReadList (current_data);
3953          return SQACT_UNPRINTABLECHARS;
3954       }
3955    }
3956 
3957    tmp = StringStr(line, "::="); /* ASN.1 */
3958    if (tmp != NULL)
3959    {
3960       MemFree(line);
3961       line = NULL;
3962       FreeBufferedReadList (current_data);
3963       return SQACT_NOTTXTALN;
3964    }
3965    tmp = StringStr(line, "LOCUS");  /* GenBank flat file */
3966    if (tmp != NULL)
3967    {
3968       MemFree(line);
3969       line = NULL;
3970       FreeBufferedReadList (current_data);
3971       return SQACT_NOTTXTALN;
3972    }
3973    if (line[0] == '>')  /* FASTA sequences or FASTA alignment */
3974    {
3975       if (StringNCmp (line, ">PubMed", 7) == 0 ||
3976           StringNCmp (line, ">Protein", 8) == 0 ||
3977           StringNCmp (line, ">Nucleotide", 11) == 0 ||
3978           StringNCmp (line, ">Structure", 10) == 0 ||
3979           StringNCmp (line, ">Genome", 7) == 0 ||
3980           StringNCmp (line, ">Feature", 8) == 0 ||
3981           StringNCmp (line, ">Vector", 7) == 0 ||
3982           StringNCmp (line, ">Restriction", 12) == 0 ||
3983           StringNCmp (line, ">Contig", 7) == 0 ||
3984           StringNCmp (line, ">Virtual", 8) == 0 ||
3985           StringNCmp (line, ">Message", 8) == 0) {
3986         MemFree(line);
3987         line = NULL;
3988         FreeBufferedReadList (current_data);
3989         return SQACT_NOTTXTALN;
3990       }
3991       MemFree(line);
3992       line = MyFGetLine (fp, &current_data);
3993       prevlen = -1;
3994       len = 0;
3995       seq = 0;
3996       while (line != NULL)
3997       {
3998          seq++;
3999          while (line != NULL && line[0] != '>')
4000          {
4001             tmp = StringStr(line, "-");
4002             if (tmp != NULL)  /* found a gap -> alignment */
4003             {
4004                MemFree(line);
4005                line = NULL;
4006                FreeBufferedReadList (current_data);
4007                return SQACT_TXTALN;
4008             }
4009             len += StringLen(line);
4010             MemFree(line);
4011             line = MyFGetLine (fp, &current_data);
4012          }
4013          if (line != NULL)
4014          {
4015             MemFree(line);
4016             line = MyFGetLine (fp, &current_data);
4017          }
4018          if (prevlen == -1)
4019             prevlen = len;
4020          if (len != prevlen)  /* sequences of different length -> FASTA seq */
4021          {
4022             MemFree(line);
4023             line = NULL;
4024             FreeBufferedReadList (current_data);
4025             return SQACT_NOTTXTALN;
4026          }
4027       }
4028       MemFree (line);
4029       line = NULL;
4030       FreeBufferedReadList (current_data);
4031       current_data = NULL;
4032       if (seq > 1) 
4033          return SQACT_TXTALN;
4034       else
4035          return SQACT_NOTTXTALN;
4036    } else
4037    {
4038       MemFree(line);
4039       line = NULL;
4040       FreeBufferedReadList (current_data);
4041       return SQACT_TXTALN;  /* NEXUS, PHYLIP, etc */
4042    }
4043 }
4044 
4045 static Uint1 sq_transform_code(Uint1 res, Int4 which)
4046 {
4047    if (which == 4) /* ncbi2na */
4048    {
4049       if (res == 1)
4050          return 0;
4051       else if (res == 3)
4052          return 1;
4053       else if (res == 7)
4054          return 2;
4055       else if (res == 18)
4056          return 3;
4057       else
4058          return 0;
4059    } else if (which == 2) /* ncbi4na */
4060    {
4061       if (res == 1)
4062          return 1;
4063       else if (res == 3)
4064          return 2;
4065       else if (res == 12)
4066          return 3;
4067       else if (res == 7)
4068          return 4;
4069       else if (res == 16)
4070          return 5;
4071       else if (res == 17)
4072          return 6;
4073       else if (res == 19)
4074          return 7;
4075       else if (res == 18)
4076          return 8; 
4077       else if (res == 20)
4078          return 9;
4079       else if (res == 22)
4080          return 10;
4081       else if (res == 8)
4082          return 11;
4083       else if (res == 10)
4084          return 12;
4085       else if (res == 4)
4086          return 13;
4087       else if (res == 2)
4088          return 14;
4089       else if (res == 13)
4090          return 15;
4091        else
4092          return 15;
4093    }
4094    return 0;
4095 }
4096 
4097 static void SQACT_FixBioseqs (BioseqPtr bsp, Pointer userdata)
4098 {
4099    Uint1Ptr           array;
4100    ByteStorePtr       bs;
4101    Int4               compact;
4102    SeqMgrDescContext  context;
4103    Int4               i;
4104    Int4               j;
4105    Int4               len;
4106    MolInfoPtr         mip;
4107    Uint1              res;
4108    Uint1              res1;
4109    Int4               shift;
4110    SeqPortPtr         spp;
4111    ValNodePtr         vnp;
4112 
4113    if (bsp == NULL)
4114       return;
4115    if (bsp->seq_data_type == Seq_code_gap) return;
4116    len = bsp->length-1;
4117    compact = 2;
4118    spp = SeqPortNew(bsp, 0, len, 0, Seq_code_ncbistdaa);
4119    while ((res = SeqPortGetResidue(spp)) != SEQPORT_EOF)
4120    {
4121       if (res != 1 && res != 3 && res != 0 && res != 18 && res != 7 && res != 13 && res != 24 && res != 21)
4122       {
4123          SeqPortFree(spp);
4124          return;
4125       } else if (res != 1 && res != 3 && res != 7 && res != 18)
4126          compact = 4;
4127    }
4128    SeqPortFree(spp);
4129    bs = BSNew((bsp->length+compact-1)/compact);
4130    array = (Uint1Ptr)MemNew((bsp->length+compact)*sizeof(Uint1));
4131    spp = SeqPortNew(bsp, 0, len, 0, Seq_code_ncbistdaa);
4132    for (i=0; i<bsp->length; i++)
4133    {
4134       res = SeqPortGetResidue(spp);
4135       array[i] = sq_transform_code(res, compact);
4136    }
4137    for (i=0; i<compact; i++)
4138       array[i+bsp->length] = 0;
4139    if (compact == 4)
4140       shift = 2;
4141    else
4142       shift = 4;
4143    for (j=0; j<bsp->length; j+=compact)
4144    {
4145       res = 0;
4146       res1 = 0;
4147       for (i=0; i<compact; i++)
4148       {
4149          res = array[j+i];
4150          res1<<=shift;
4151          res1 |= res;
4152       }
4153       BSPutByte(bs, res1);
4154    }
4155    MemFree(bsp->seq_data);
4156    bsp->seq_data = (SeqDataPtr) bs;
4157    if (compact == 4)
4158       bsp->seq_data_type = Seq_code_ncbi2na;
4159    else
4160       bsp->seq_data_type = Seq_code_ncbi4na;
4161    bsp->mol = Seq_mol_na;
4162    bsp->repr = Seq_repr_raw;
4163    SeqMgrIndexFeatures(0, (Pointer)(bsp));
4164    vnp = NULL;
4165    vnp = SeqMgrGetNextDescriptor(bsp, vnp, Seq_descr_molinfo, &context);
4166    if (vnp != NULL)
4167    {
4168       vnp = context.sdp;
4169       mip = (MolInfoPtr)(vnp->data.ptrvalue);
4170       mip->biomol = 1;
4171    }
4172    MemFree(array);
4173 }
4174 
4175 static Boolean CommonReadNewAsnProc (Handle obj, Boolean removeold, Boolean askForSubmit)
4176 
4177 {
4178   AsnIoPtr     aip;
4179   BaseFormPtr  bfp;
4180   Pointer      dataptr;
4181   Uint2        datatype;
4182   Uint2        entityID;
4183   FILE         *fp;
4184   Char         path [PATH_MAX];
4185   Boolean      rsult;
4186   SeqEntryPtr  sep;
4187   Int4         type;
4188   Uint2        updateEntityID;
4189 
4190 #ifdef WIN_MAC
4191   bfp = currentFormDataPtr;
4192 #else
4193   bfp = GetObjectExtra (obj);
4194 #endif
4195   rsult = FALSE;
4196   path [0] = '\0';
4197   if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
4198     Update ();
4199     fp = FileOpen (path, "r");
4200     if (fp == NULL) {
4201       ArrowCursor ();
4202       ErrPostEx (SEV_WARNING, 0, 0, "Unable to open file '%s'", path);
4203       return FALSE;
4204     }
4205     type = SQACT_GuessWhatIAm (fp);
4206     FileClose (fp);
4207     if (type == SQACT_UNPRINTABLECHARS || type == SQACT_TXTALN)
4208     {
4209       sep = NULL;
4210       if (type == SQACT_TXTALN)
4211       {
4212         sep = ReadAnyAlignment (TRUE, path);
4213       }
4214       if (sep == NULL)
4215       {
4216         aip = AsnIoOpen (path, "rb");
4217         if (aip != NULL) {
4218           sep = SeqEntryAsnRead (aip, NULL);
4219           AsnIoClose (aip);
4220         }
4221         if (sep == NULL)
4222         {
4223           ArrowCursor ();
4224           if (type == SQACT_UNPRINTABLECHARS)
4225           {
4226             ErrPostEx (SEV_WARNING, 0, 0, "File '%s' contains unprintable characters.  If this is a Word document, you need to save it as plain text.", path);
4227           }
4228           else
4229           {
4230             ErrPostEx (SEV_WARNING, 0, 0, "Error reading file");
4231           }
4232           return FALSE;
4233         }        
4234       }
4235       VisitBioseqsInSep (sep, NULL, SQACT_FixBioseqs);
4236       if (IS_Bioseq (sep)) {
4237         datatype = OBJ_BIOSEQ;
4238       } else {
4239         datatype = OBJ_BIOSEQSET;
4240       }
4241       dataptr = (Pointer) sep->data.ptrvalue;
4242       entityID = ObjMgrRegister (datatype, dataptr);
4243       rsult = HandleOneNewAsnProc (bfp, FALSE, askForSubmit, path, dataptr, datatype, entityID, &updateEntityID);
4244       if (updateEntityID != 0) 
4245       {
4246         ObjMgrSetDirtyFlag (updateEntityID, TRUE);
4247         ObjMgrSendMsg (OM_MSG_UPDATE, updateEntityID, 0, 0);
4248       }
4249     } else {
4250       rsult = DoReadAnythingLoop (bfp, path, path, removeold, askForSubmit, FALSE, TRUE, FALSE);
4251     }
4252   }
4253   ArrowCursor ();
4254   return rsult;
4255 }
4256 
4257 static void FinishAlignmentRead (Handle obj, SeqEntryPtr sep, CharPtr path) {
4258   BaseFormPtr  bfp;
4259   Pointer      dataptr;
4260   Uint2        datatype;
4261   Uint2        entityID;
4262   Boolean      rsult;
4263   Uint2        updateEntityID;
4264 
4265 #ifdef WIN_MAC
4266   bfp = currentFormDataPtr;
4267 #else
4268   bfp = GetObjectExtra (obj);
4269 #endif
4270 
4271   if (sep == NULL)
4272   {
4273     return;
4274   }
4275   VisitBioseqsInSep (sep, NULL, SQACT_FixBioseqs);
4276   if (IS_Bioseq (sep)) {
4277     datatype = OBJ_BIOSEQ;
4278   } else {
4279     datatype = OBJ_BIOSEQSET;
4280   }
4281   dataptr = (Pointer) sep->data.ptrvalue;
4282   entityID = ObjMgrRegister (datatype, dataptr);
4283   rsult = HandleOneNewAsnProc (bfp, FALSE, FALSE, path,
4284                                dataptr, datatype, entityID, &updateEntityID);
4285   if (updateEntityID != 0) {
4286     ObjMgrSetDirtyFlag (updateEntityID, TRUE);
4287     ObjMgrSendMsg (OM_MSG_UPDATE, updateEntityID, 0, 0);
4288   }
4289 }
4290 
4291 
4292 static void PrintExtraErrorInstructions (FILE *fp, CharPtr message)
4293 {
4294   CharPtr explanation, end;
4295   Char    tmp = '\0';
4296   if (fp == NULL || message == NULL) return;
4297 
4298   if (StringStr (message, "bad characters") == NULL
4299       && StringStr (message, " found at position ") == NULL) {
4300     return;
4301   }
4302 
4303   explanation = StringRChr (message, '(');
4304   if (explanation == NULL) return;
4305   if (StringNCmp (explanation, "(expect only ", 13) == 0) {
4306     end = StringStr (explanation + 13, " here)");
4307     if (end != NULL) {
4308       tmp = *end;
4309       *end = 0;
4310     }
4311     fprintf (fp, 
4312              "Try changing the sequence character specifications for %s.\n",
4313              explanation + 13);
4314     if (StringNCmp (explanation + 13, "beginning", 9) == 0) {
4315       fprintf (fp, 
4316 "\nWhen some of the sequences in an alignment are shorter or "
4317 "longer than others, beginning gap characters are added to "
4318 "the beginning of the sequence to maintain the correct spacing."
4319 "  These will not appear in your sequence file.\n");
4320     } else if (StringNCmp (explanation + 13, "end", 3) == 0) {
4321       fprintf (fp,
4322 "\nWhen some of the sequences in an alignment are shorter or "
4323 "longer than others, end gap characters are added to "
4324 "the end of the sequence to maintain the correct spacing."
4325 "  These will not appear in your sequence file.\n");
4326     } else {
4327       fprintf (fp,
4328 "\nMiddle gap characters are used to maintain the spacing "
4329 "inside an alignment.  These are not nucleotides and will "
4330 "not appear as part of your sequence file.\n"
4331 "Ambiguous/unknown characters are used to represent indeterminate/ambiguous "
4332 "nucleotides.  These will appear in your sequence file as 'n'.\n"
4333 "Match characters are used to indicate positions where "
4334 "sequences are identical to the first sequence.  These will be "
4335 "replaced by the actual characters from the first sequence.\n");
4336     }
4337     if (end != NULL) {
4338       *end = tmp;
4339     }
4340   } else if (StringCmp (explanation, 
4341                         "(can't specify match chars in first sequence).") == 0) {
4342     fprintf (fp, "Try changing the match character specification.\n");
4343     fprintf (fp,
4344 "\nMatch characters are used to indicate positions where "
4345 "sequences are identical to the first sequence.  These will be "
4346 "replaced by the actual characters from the first sequence.\n");
4347   }
4348 }
4349 static void PrintError (FILE *fp, TErrorInfoPtr eip)
4350 {
4351   if (eip == NULL || fp == NULL) return;
4352 
4353   fprintf (fp, "*****\nError category %d\n", eip->category);
4354   if (eip->line_num > -1) {
4355     fprintf (fp, "Line number %d\n", eip->line_num);
4356   }
4357   if (eip->id != NULL) {
4358     fprintf (fp, "Sequence ID %s\n", eip->id);
4359   }
4360   if (eip->message != NULL) {
4361     fprintf (fp, "%s\n", eip->message);
4362     PrintExtraErrorInstructions (fp, eip->message);
4363   }
4364 }
4365   
4366 static void WalkErrorList (TErrorInfoPtr list, FILE *fp)
4367 {
4368   TErrorInfoPtr eip;
4369   
4370   if (list == NULL || fp == NULL) return;
4371 
4372   for (eip = list; eip != NULL; eip = eip->next) {
4373     PrintError (fp, eip);
4374   }
4375 
4376 }
4377 
4378 static Int4 CountNucleotides (CharPtr sequence)
4379 {
4380   Int4    num = 0;
4381   CharPtr cp;
4382   
4383   if (sequence == NULL) return 0;       
4384   for (cp = sequence; *cp != 0; cp++)
4385   {
4386         if (*cp != '-') 
4387         {
4388           num++;
4389         }
4390   }
4391   return num;
4392 }
4393 
4394 static void PrintAlignmentSummary (TAlignmentFilePtr afp, FILE *fp)
4395 {
4396   Int4 index;
4397 
4398   if (fp == NULL) return;
4399 
4400   if (afp == NULL) {
4401     fprintf (fp, "Catastrophic failure during reading\n");
4402   } else {
4403     fprintf (fp, "Found %d sequences\n", afp->num_sequences);
4404     fprintf (fp, "Found %d organisms\n", afp->num_organisms);
4405     if (afp->num_sequences == afp->num_segments * afp->num_organisms)
4406     {
4407       for (index = 0; index < afp->num_sequences; index++)
4408       {
4409         fprintf (fp, "\t%s\t%d nucleotides\t", afp->ids [index],
4410                  CountNucleotides (afp->sequences[index]));
4411         if (index / afp->num_segments < afp->num_organisms) {
4412           fprintf (fp, "%s\n", afp->organisms [index / afp->num_segments]);
4413         } else {
4414           fprintf (fp, "No organism information\n");
4415         }
4416       }         
4417     }
4418     else
4419     {
4420       for (index = 0; index < afp->num_sequences; index++)
4421       {
4422         fprintf (fp, "\t%s\t%d nucleotides\t", afp->ids [index], 
4423                  CountNucleotides (afp->sequences[index]));
4424         if (index < afp->num_organisms) {
4425           fprintf (fp, "%s\n", afp->organisms [index]);
4426         } else {
4427           fprintf (fp, "No organism information\n");
4428         }
4429       }
4430       while (index < afp->num_organisms) {
4431         fprintf (fp, "Unclaimed organism: %s\n", afp->organisms [index]);
4432         index++;
4433       } 
4434     }
4435   }
4436 }
4437 
4438 
4439 static void ReportPotentialDupIDs (TAlignmentFilePtr afp, FILE *fp)
4440 {
4441   int     seq_index, k;
4442   int     curr_seg;
4443   int     num_sequences;
4444   Int4Ptr seq_len;
4445   BoolPtr may_be_dup;
4446   Int4    a, b;
4447 
4448   if (afp == NULL || afp->sequences == NULL || afp->num_sequences == 0) {
4449     return;
4450   }
4451 
4452   num_sequences = afp->num_sequences / afp->num_segments;
4453 
4454   may_be_dup = (BoolPtr) MemNew (sizeof (Boolean) * num_sequences);
4455   for (seq_index = 0; seq_index < num_sequences; seq_index++) {
4456     may_be_dup[seq_index] = FALSE;
4457   }
4458 
4459   seq_len = (Int4Ptr) MemNew (sizeof (Int4) * afp->num_sequences);
4460   for (seq_index = 0; seq_index < afp->num_sequences; seq_index++) {
4461     seq_len[seq_index] = StringLen (afp->sequences[seq_index]);
4462   }
4463 
4464   for (curr_seg = 0; curr_seg < afp->num_segments; curr_seg++) {
4465     for (seq_index = 0; seq_index < num_sequences - 1; seq_index++) {
4466       for (k = seq_index + 1; k < num_sequences; k++) {
4467         a = curr_seg * num_sequences + seq_index;
4468         b = curr_seg * num_sequences + k;
4469         if (seq_len[a] != seq_len[b]) {
4470           if (seq_len[a] % seq_len [b] == 0) {
4471             may_be_dup[seq_index] = TRUE;
4472           } else if (seq_len[b] % seq_len[a] == 0) {
4473             may_be_dup[k] = TRUE;
4474           }
4475         }
4476       }
4477     }
4478   }
4479   seq_len = MemFree (seq_len);
4480 
4481   for (seq_index = 0; seq_index < num_sequences; seq_index ++)
4482   {
4483     if (may_be_dup[seq_index]) {
4484       fprintf (fp, "Please check your file - %s may have been used as an ID for multiple sequences.\n", afp->ids[seq_index]);
4485     }
4486   }
4487 
4488   may_be_dup = MemFree (may_be_dup);
4489 }
4490 
4491 
4492 static Boolean DoSequenceLengthsMatch (TAlignmentFilePtr afp)
4493 {
4494   int     seq_index;
4495   int     curr_seg;
4496   Int4Ptr seq_len;
4497   Boolean rval;
4498 
4499   if (afp == NULL || afp->sequences == NULL || afp->num_sequences == 0) {
4500     return TRUE;
4501   }
4502 
4503   seq_len = (Int4Ptr) MemNew (sizeof (Int4) * afp->num_segments);
4504   if (seq_len == NULL) return FALSE;
4505   for (seq_index = 0; seq_index < afp->num_segments; seq_index ++)
4506   {
4507     seq_len [seq_index] = StringLen (afp->sequences[seq_index]);
4508   }
4509 
4510   curr_seg = 0;
4511   rval = TRUE;
4512   for (seq_index = afp->num_segments; seq_index < afp->num_sequences && rval; seq_index++) {
4513     if (StringLen (afp->sequences[seq_index]) != seq_len[curr_seg]) {
4514       rval = FALSE;
4515     }
4516         curr_seg ++;
4517         if (curr_seg >= afp->num_segments) curr_seg = 0;
4518   }
4519   MemFree (seq_len);
4520   return rval;
4521 }
4522 
4523 
4524 extern void 
4525 ProduceAlignmentNotes 
4526 (TAlignmentFilePtr afp,
4527  TErrorInfoPtr error_list)
4528 {
4529   Char         path [PATH_MAX];
4530   FILE         *fp;
4531   Boolean      ok_to_import = FALSE;
4532 
4533   TmpNam (path);
4534   fp = FileOpen (path, "wb");
4535   if (fp == NULL) return;
4536 
4537 
4538   if (afp != NULL && DoSequenceLengthsMatch (afp)) {
4539     ok_to_import = TRUE;
4540   }
4541 
4542   
4543   if (ok_to_import && error_list != NULL) {
4544     fprintf (fp, "Congratulations, you have successfully created a sequin file;\nhowever, I had trouble reading part of your file.\nPlease check your data carefully before submitting to be sure that all of your sequences\nwere included correctly.\nIf your file is incomplete, or contains incorrect sequences, please use the error report below\nto find the problem.\n");
4545   }
4546   ReportPotentialDupIDs (afp, fp);
4547 
4548   WalkErrorList (error_list, fp);
4549   PrintAlignmentSummary (afp, fp);
4550 
4551   FileClose (fp);
4552   LaunchGeneralTextViewer (path, "Alignment reading summary");
4553   FileRemove (path);
4554 }
4555 
4556 typedef struct alphabetformdata {
4557   FEATURE_FORM_BLOCK
4558 
4559   DialoG aln_settings;
4560   Handle obj;
4561   Char  path [PATH_MAX];
4562   FILE  *fp;
4563 } AlphabetFormData, PNTR AlphabetFormPtr;
4564 
4565 extern SeqEntryPtr 
4566 SeqEntryFromAlignmentFile 
4567 (FILE *fp,
4568  TSequenceInfoPtr sequence_info,
4569  Uint1   moltype,
4570  CharPtr no_org_err_msg)
4571 {
4572   TErrorInfoPtr     error_list;
4573   ReadBufferData    rbd;
4574   TAlignmentFilePtr afp;
4575   SeqEntryPtr       sep = NULL;
4576 
4577   if (fp == NULL || sequence_info == NULL) return NULL;
4578 
4579   error_list = NULL;
4580   rbd.fp = fp;
4581   rbd.current_data = NULL;
4582   afp = ReadAlignmentFile ( AbstractReadFunction,
4583                             (Pointer) &rbd,
4584                             AbstractReportError,
4585                             (Pointer) &error_list,
4586                             sequence_info);
4587 
4588   ProduceAlignmentNotes (afp, error_list);
4589   ErrorInfoFree (error_list);
4590   if (afp != NULL) {
4591     if (afp->num_organisms == 0 && no_org_err_msg != NULL) {
4592       Message (MSG_ERROR, no_org_err_msg);
4593     } else if (afp->num_organisms != 0 && afp->num_organisms != afp->num_sequences && afp->num_organisms * afp->num_segments != afp->num_sequences) {
4594       Message (MSG_ERROR, "Number of organisms must match number of sequences!");
4595     } else if (! DoSequenceLengthsMatch (afp)) {
4596       Message (MSG_ERROR, "Your alignment is incorrectly formatted.  Sequence plus gaps should be the same length for all sequences.");
4597     } else {
4598       sep = MakeSequinDataFromAlignment (afp, moltype);
4599     }
4600   }
4601 
4602   AlignmentFileFree (afp);
4603   return sep;
4604 }
4605 
4606 static void DoReadAlignment (ButtoN b)
4607 {
4608   AlphabetFormPtr  abc;
4609   TAlignmentFilePtr afp;
4610   TErrorInfoPtr     error_list;
4611   TSequenceInfoPtr  sequence_info;
4612   SeqEntryPtr      sep;
4613   Uint1            moltype;
4614   ReadBufferData   rbd;
4615 
4616   abc = GetObjectExtra (b);
4617   if (abc == NULL) return;
4618   Hide (abc->form);
4619   Update ();
4620 
4621   sequence_info = (TSequenceInfoPtr) DialogToPointer (abc->aln_settings);
4622   if (sequence_info == NULL) return;
4623 
4624   WatchCursor ();
4625   Update ();
4626 
4627   if (StringCmp (sequence_info->alphabet, protein_alphabet) == 0) {
4628     moltype = Seq_mol_aa;
4629   } else {
4630     moltype = Seq_mol_na;
4631   }
4632 
4633   error_list = NULL;
4634   rbd.fp = abc->fp;
4635   rbd.current_data = NULL;
4636   afp = ReadAlignmentFile ( AbstractReadFunction,
4637                             (Pointer) &rbd,
4638                             AbstractReportError,
4639                             (Pointer) &error_list,
4640                             sequence_info);
4641   if (afp != NULL) {
4642       sep = MakeSequinDataFromAlignment (afp, moltype);
4643       FinishAlignmentRead (abc->obj, sep, abc->path);
4644   }
4645   ProduceAlignmentNotes (afp, error_list);
4646   ErrorInfoFree (error_list);
4647   SequenceInfoFree (sequence_info);
4648 
4649   AlignmentFileFree (afp);
4650   FileClose (abc->fp);
4651   abc->fp = NULL;
4652   ArrowCursor ();
4653   Update ();
4654   Remove (abc->form);
4655 }
4656 
4657 
4658 /* Need cleanup for Alphabet Dialog to close File Pointer */
4659 static void CleanupAlphabetDialog (GraphiC g, VoidPtr data)
4660 {
4661     AlphabetFormPtr afp;
4662 
4663     afp = (AlphabetFormPtr) data;
4664     if (afp != NULL && afp->fp != NULL) {
4665         FileClose (afp->fp);
4666         afp->fp = NULL;
4667     }
4668     StdCleanupFormProc (g, data);
4669 }
4670 
4671 static void BuildGetAlphabetDialog (IteM i)
4672 {
4673   BaseFormPtr        bfp;
4674   ButtoN             b;
4675   GrouP              c, h;
4676   AlphabetFormPtr    afp;
4677   WindoW             w;
4678 
4679 #ifdef WIN_MAC
4680   bfp = currentFormDataPtr;
4681 #else
4682   bfp = GetObjectExtra (i);
4683 #endif
4684   if (bfp == NULL) return;
4685 
4686   afp = (AlphabetFormPtr) MemNew (sizeof (AlphabetFormData));
4687   if (afp == NULL) return;
4688   afp->obj = i;
4689 
4690   if (! GetInputFileName (afp->path, sizeof (afp->path), NULL, "TEXT")) return;
4691 
4692   afp->fp = FileOpen (afp->path, "r");
4693   if (afp->fp == NULL)
4694   {
4695     Message (MSG_ERROR, "Unable to open file");
4696     return;
4697   }
4698 
4699   w = FixedWindow (-50, -33, -10, -10, "Alignment Alphabet", StdCloseWindowProc);
4700   SetObjectExtra (w, afp, CleanupAlphabetDialog);
4701   afp->form = (ForM) w;
4702   afp->formmessage = NULL;
4703 
4704   h = HiddenGroup (w, -1, 0, NULL);
4705   SetGroupSpacing (h, 10, 10);
4706 
4707   afp->aln_settings = AlnSettingsDlg (h, TRUE);  
4708 
4709   c = HiddenGroup (h, 4, 0, NULL);
4710   b = DefaultButton (c, "Accept", DoReadAlignment);
4711   SetObjectExtra (b, afp, NULL);
4712   PushButton (c, "Cancel", StdCancelButtonProc);
4713 
4714   AlignObjects (ALIGN_CENTER, (HANDLE) afp->aln_settings, (HANDLE) c, NULL);
4715   RealizeWindow (w);
4716   Show (w);
4717   Update ();
4718 }
4719 
4720 extern void ReadAlignment (IteM i)
4721 {
4722   BuildGetAlphabetDialog (i);
4723 
4724 }
4725 
4726 
4727 typedef struct alnsettingsdlg {
4728   DIALOG_MESSAGE_BLOCK
4729   TexT missing;
4730   TexT match;
4731   TexT beginning_gap;
4732   TexT middle_gap;
4733   TexT end_gap;
4734 
4735   PopuP sequence_type;
4736 } AlnSettingsDlgData, PNTR AlnSettingsDlgPtr;
4737 
4738 static CharPtr aln_settings_help = "\
4739 Beginning Gap: When some of the sequences in an \
4740 alignment are shorter or longer than others, beginning \
4741 gap characters are added to the beginning of the sequence \
4742 to maintain the correct spacing.  These will not appear \
4743 in your sequence file.\n\
4744 Middle Gap: These characters are used to maintain the spacing \
4745 inside an alignment.  These are not nucleotides and will \
4746 not appear as part of your sequence file.\n\
4747 End Gap: When some of the sequences in an alignment are shorter \
4748 or longer than others, end gap characters are added to the end \
4749 of the sequence to maintain the correct spacing.  These will \
4750 not appear in your sequence file.\n\
4751 Ambiguous/Unknown: These characters are used to represent \
4752 indeterminate/ambiguous nucleotides.  These will appear in your \
4753 sequence file as 'n'.\n\
4754 Match: These characters are used to indicate positions where \
4755 sequences are identical to the first sequence.  These will be \
4756 replaced by the actual characters from the first sequence.";
4757 
4758 const char *nucleotide_alphabet = "ABCDGHKMRSTUVWYabcdghkmrstuvwy";
4759 const char *protein_alphabet = "ABCDEFGHIKLMPQRSTUVWXYZabcdefghiklmpqrstuvwxyz";
4760 
4761 extern TSequenceInfoPtr GetDefaultSequenceInfo (void)
4762 {
4763   TSequenceInfoPtr sequence_info = SequenceInfoNew();
4764 
4765   sequence_info->missing = MemFree (sequence_info->missing);
4766   sequence_info->missing = StringSave ("?Nn");
4767 
4768   sequence_info->beginning_gap = MemFree (sequence_info->beginning_gap);
4769   sequence_info->beginning_gap = StringSave ("-.Nn?");
4770 
4771   sequence_info->middle_gap = MemFree (sequence_info->middle_gap);
4772   sequence_info->middle_gap = StringSave ("-.");
4773 
4774   sequence_info->end_gap = MemFree (sequence_info->end_gap);
4775   sequence_info->end_gap = StringSave ("-.Nn?");
4776 
4777   sequence_info->match = MemFree (sequence_info->match);
4778   sequence_info->match = StringSave (":");
4779 
4780   sequence_info->alphabet = nucleotide_alphabet;
4781 
4782   return sequence_info;
4783 }
4784 
4785 static Pointer AlnSettingsDlgToData (DialoG d)
4786 {
4787   AlnSettingsDlgPtr dlg;
4788   TSequenceInfoPtr  sequence_info;
4789 
4790   dlg = (AlnSettingsDlgPtr) GetObjectExtra (d);
4791   if (dlg == NULL) return NULL;
4792 
4793   sequence_info = SequenceInfoNew ();
4794   if (sequence_info == NULL) return NULL;
4795 
4796   sequence_info->missing = MemFree (sequence_info->missing);
4797   sequence_info->missing = SaveStringFromText (dlg->missing);
4798 
4799   sequence_info->beginning_gap = MemFree (sequence_info->beginning_gap);
4800   sequence_info->beginning_gap = SaveStringFromText (dlg->beginning_gap);
4801 
4802   sequence_info->middle_gap = MemFree (sequence_info->middle_gap);
4803   sequence_info->middle_gap = SaveStringFromText (dlg->middle_gap);
4804 
4805   sequence_info->end_gap = MemFree (sequence_info->end_gap);
4806   sequence_info->end_gap = SaveStringFromText (dlg->end_gap);
4807 
4808   sequence_info->match = MemFree (sequence_info->match);
4809   sequence_info->match = SaveStringFromText (dlg->match);
4810 
4811   if (dlg->sequence_type != NULL) 
4812   {
4813     if (GetValue (dlg->sequence_type) == 1) {
4814       sequence_info->alphabet = nucleotide_alphabet;
4815     } else {
4816       sequence_info->alphabet = protein_alphabet;
4817     }
4818   }
4819   else
4820   {
4821     sequence_info->alphabet = nucleotide_alphabet;
4822   }
4823 
4824   return sequence_info;
4825 }
4826 
4827 
4828 static void DataToAlnSettingsDlg (DialoG d, Pointer data)
4829 {
4830   AlnSettingsDlgPtr dlg;
4831   TSequenceInfoPtr  sequence_info;
4832 
4833   dlg = (AlnSettingsDlgPtr) GetObjectExtra (d);
4834   if (dlg == NULL) return;
4835 
4836   sequence_info = (TSequenceInfoPtr) data;
4837 
4838   if (sequence_info == NULL)
4839   {
4840     SetTitle (dlg->missing, "?Nn");
4841     SetTitle (dlg->beginning_gap, "-.Nn?");
4842     SetTitle (dlg->middle_gap, "-.");
4843     SetTitle (dlg->end_gap, "-.Nn?");
4844     SetTitle (dlg->match, ":");
4845     if (dlg->sequence_type != NULL)
4846     {
4847       SetValue (dlg->sequence_type, 1);
4848     }
4849   }
4850   else
4851   {
4852     SetTitle (dlg->missing, sequence_info->missing);
4853     SetTitle (dlg->beginning_gap, sequence_info->beginning_gap);
4854     SetTitle (dlg->middle_gap, sequence_info->middle_gap);
4855     SetTitle (dlg->end_gap, sequence_info->end_gap);
4856     SetTitle (dlg->match, sequence_info->match);
4857 
4858     if (dlg->sequence_type != NULL) 
4859     {
4860       if (StringCmp (sequence_info->alphabet, protein_alphabet) == 0) 
4861       {
4862         SetValue (dlg->sequence_type, 2);
4863       }
4864       else
4865       {
4866         SetValue (dlg->sequence_type, 1);
4867       }
4868     }
4869   }
4870 }
4871 
4872 
4873 static ValNodePtr TestAlnSettingsDlg (DialoG d)
4874 {
4875   ValNodePtr        err_list = NULL;
4876   TSequenceInfoPtr  sequence_info;
4877   CharPtr           cp;
4878   CharPtr           fmt = "Character %c cannot appear in both %s and %s.";
4879   CharPtr           err_str;
4880   CharPtr           missing_name = "Ambiguous/Unknown";
4881   CharPtr           middle_gap_name = "Middle Gap";
4882   CharPtr           match_name = "Match";
4883 
4884   sequence_info = DialogToPointer (d);
4885   if (sequence_info == NULL) return NULL;
4886 
4887   /* missing and match cannot appear in middle gap list */
4888   cp = sequence_info->missing;
4889   while (cp != NULL && *cp != 0)
4890   {
4891     if (StringChr (sequence_info->middle_gap, *cp)) 
4892     {
4893       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) 
4894                                                    + StringLen (missing_name)
4895                                                    + StringLen (middle_gap_name)));
4896       sprintf (err_str, fmt, *cp, missing_name, middle_gap_name);
4897       ValNodeAddPointer (&err_list, 0, err_str);
4898     }
4899     cp++;
4900   }
4901 
4902   cp = sequence_info->match;
4903   while (cp != NULL && *cp != 0)
4904   {
4905     if (StringChr (sequence_info->middle_gap, *cp)) 
4906     {
4907       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) 
4908                                                    + StringLen (match_name)
4909                                                    + StringLen (middle_gap_name)));
4910       sprintf (err_str, fmt, *cp, match_name, middle_gap_name);
4911       ValNodeAddPointer (&err_list, 0, err_str);
4912     }
4913     cp++;
4914   }
4915 
4916   /* missing and match cannot share characters */
4917   cp = sequence_info->missing;
4918   while (cp != NULL && *cp != 0)
4919   {
4920     if (StringChr (sequence_info->match, *cp)) 
4921     {
4922       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) 
4923                                                    + StringLen (missing_name)
4924                                                    + StringLen (match_name)));
4925       sprintf (err_str, fmt, *cp, missing_name, match_name);
4926       ValNodeAddPointer (&err_list, 0, err_str);
4927     }
4928     cp++;
4929   }
4930 
4931   return err_list;
4932 }
4933 
4934 
4935 extern DialoG AlnSettingsDlg (GrouP h, Boolean allow_sequence_type)
4936 {
4937   AlnSettingsDlgPtr dlg;
4938   GrouP             p, g, p_msg;
4939   
4940   dlg = (AlnSettingsDlgPtr) MemNew (sizeof (AlnSettingsDlgData));
4941   p = HiddenGroup (h, -1, 0, NULL);
4942   SetObjectExtra (p, dlg, StdCleanupExtraProc);
4943   SetGroupSpacing (p, 10, 10);
4944 
4945   dlg->dialog = (DialoG) p;
4946   dlg->todialog = DataToAlnSettingsDlg;
4947   dlg->fromdialog = AlnSettingsDlgToData;
4948   dlg->testdialog = TestAlnSettingsDlg;
4949 
4950   g = HiddenGroup (p, 2, 0, NULL);
4951   StaticPrompt (g, "Ambiguous/Unknown", 0, dialogTextHeight, programFont, 'c');
4952   dlg->missing = DialogText (g, "?Nn", 5, NULL);
4953   StaticPrompt (g, "Match", 0, dialogTextHeight, programFont, 'c');
4954   dlg->match = DialogText (g, ".", 5, NULL);
4955   StaticPrompt (g, "Beginning Gap", 0, dialogTextHeight, programFont, 'c');
4956   dlg->beginning_gap = DialogText (g, "-.?nN", 5, NULL);
4957   StaticPrompt (g, "Middle Gap", 0, dialogTextHeight, programFont, 'c');
4958   dlg->middle_gap = DialogText (g, "-", 5, NULL);
4959   StaticPrompt (g, "End Gap", 0, dialogTextHeight, programFont, 'c');
4960   dlg->end_gap = DialogText (g, "-.?nN", 5, NULL);
4961   if (allow_sequence_type) {
4962     StaticPrompt (g, "Sequence Type", 0, dialogTextHeight, programFont, 'c');
4963     dlg->sequence_type = PopupList (g, TRUE, NULL);
4964     PopupItem (dlg->sequence_type, "Nucleotide");
4965     PopupItem (dlg->sequence_type, "Protein");
4966     SetValue (dlg->sequence_type, 1);
4967   }
4968   
4969   p_msg = MultiLinePrompt (p, aln_settings_help, 750, systemFont);
4970 
4971   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) p_msg, NULL);
4972   
4973   return (DialoG) p;
4974 }
4975 
4976 
4977 static void ReadNewAsnProc (IteM i)
4978 
4979 {
4980   CommonReadNewAsnProc ((Handle) i, FALSE, FALSE);
4981 }
4982 
4983 extern Boolean LIBCALLBACK SequinOpenMimeFile (CharPtr filename)
4984 
4985 {
4986   Boolean  rsult = FALSE;
4987 
4988 #ifdef WIN_MAC
4989   SafeHide (startupForm); /* if just Hide, triggers MacDeactProc, does not reactivate */
4990   Update ();
4991 #endif
4992   rsult = DoReadAnythingLoop (NULL, filename, filename, FALSE, FALSE, FALSE, TRUE, FALSE);
4993   if (! rsult) {
4994 /*
4995 #ifndef WIN16
4996     if (BiostrucAvail () && OpenMimeFileWithDeletion (filename, FALSE)) {
4997       Handle   www_cn3d;
4998       www_cn3d = Cn3DWin_Entrez(NULL, useEntrez);
4999       Show (www_cn3d);
5000       Select (www_cn3d);
5001     } else {
5002       Show (startupForm);
5003       Select (startupForm);
5004     }
5005 #else
5006     Show (startupForm);
5007     Select (startupForm);
5008 #endif
5009 */
5010     Show (startupForm);
5011     Select (startupForm);
5012   }
5013 #ifdef OS_MAC
5014   /* the Web browsers on other platforms get upset if you delete the file, */
5015   /* but apparently on the Mac you must delete it - comment from cn3dmain.c */
5016   /* but here it's for response to apple events, so should not free this file */
5017   /* FileRemove (filename); */
5018 #endif
5019   return rsult;
5020 }
5021 
5022 extern Boolean LIBCALLBACK SequinOpenResultFile (CharPtr filename)
5023 
5024 {
5025   return DoReadAnythingLoop (NULL, filename, NULL, FALSE, FALSE, FALSE, TRUE, FALSE);
5026 }
5027 
5028 extern Boolean LIBCALLBACK SequinHandleNetResults (CharPtr filename)
5029 
5030 {
5031   return DoReadAnythingLoop (NULL, filename, NULL, FALSE, FALSE, TRUE, TRUE, TRUE);
5032 }
5033 
5034 #ifdef WIN_MAC
5035 static void MacReadNewAsnProc (IteM i)
5036 
5037 {
5038   if (initialFormsActive) {
5039     CommonReadNewAsnProc ((Handle) i, TRUE, FALSE);
5040   } else {
5041     CommonReadNewAsnProc ((Handle) i, FALSE, FALSE);
5042   }
5043 }
5044 #endif
5045 
5046 static Boolean CountAlignmentsCallback (GatherContextPtr gcp)
5047 
5048 {
5049   Int4Ptr  rsultptr;
5050 
5051   if (gcp == NULL) return TRUE;
5052 
5053   rsultptr = (Int4Ptr) gcp->userdata;
5054   if (rsultptr == NULL ) return TRUE;
5055 
5056   switch (gcp->thistype) {
5057     case OBJ_SEQALIGN :
5058     case OBJ_SEQHIST_ALIGN :
5059       (*rsultptr)++;
5060       return TRUE;
5061     default :
5062       break;
5063   }
5064   return TRUE;
5065 }
5066 
5067 static Int4 LIBCALL CountSeqEntryAligns (Uint2 entityID, SeqEntryPtr sep)
5068 
5069 {
5070   GatherScope  gs;
5071   Int4         rsult;
5072 
5073   rsult = 0;
5074   if (entityID == 0 || sep == NULL) return 0;
5075   MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
5076   gs.seglevels = 1;
5077   MemSet((Pointer) (gs.ignore), (int) (TRUE), (size_t) (OBJ_MAX * sizeof (Boolean)));
5078   gs.ignore[OBJ_BIOSEQ] = FALSE;
5079   gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
5080   gs.ignore[OBJ_SEQALIGN] = FALSE;
5081   gs.ignore[OBJ_SEQANNOT] = FALSE;
5082   gs.ignore[OBJ_SEQHIST] = FALSE;
5083   gs.ignore[OBJ_SEQHIST_ALIGN] = FALSE;
5084   gs.scope = sep;
5085   GatherEntity (entityID, (Pointer) (&rsult), CountAlignmentsCallback, &gs);
5086   return rsult;
5087 }
5088 
5089 static BioseqSetPtr GetAlignmentSetForBioseq (BioseqPtr bsp, Uint2 entityID)
5090 {
5091   BioseqSetPtr bssp = NULL;
5092   SeqEntryPtr  sep, sep_top;
5093   Uint2        parenttype;
5094   Pointer      parentptr;
5095   
5096   if (bsp == NULL)
5097   {
5098     return NULL;
5099   }
5100   
5101   sep_top = GetTopSeqEntryForEntityID (entityID);
5102   
5103   sep = GetBestTopParentForData (entityID, bsp); 
5104   GetSeqEntryParent (sep, &parentptr, &parenttype);
5105   if (parenttype == OBJ_BIOSEQSET)
5106   {
5107     bssp = (BioseqSetPtr) parentptr;
5108   }
5109   else if (sep != NULL && IS_Bioseq_set (sep))
5110   {
5111     bssp = (BioseqSetPtr) sep->data.ptrvalue;
5112   }
5113   else if (sep_top != NULL && IS_Bioseq_set (sep_top))
5114   {
5115     bssp = (BioseqSetPtr) sep_top->data.ptrvalue;
5116   }
5117   return bssp;
5118 }
5119 
5120 static void EnableEditAlignItem (BaseFormPtr bfp)
5121 
5122 {
5123   BioseqPtr     bsp;
5124   BioseqSetPtr  bssp;
5125   IteM          editalign;
5126   IteM          editdup;
5127   IteM          editfeatprop;
5128   Int2          mssgalign;
5129   Int2          mssgdup;
5130   Int2          mssgfeatprop;
5131   Int4          num;
5132   SeqEntryPtr   sep;
5133   SelStructPtr  sel;
5134 
5135   if (bfp == NULL && bfp->input_entityID != 0) return;
5136   mssgalign = RegisterFormMenuItemName ("SequinEditAlignmentItem");
5137   mssgdup = RegisterFormMenuItemName ("SequinDuplicateItem");
5138   mssgfeatprop = RegisterFormMenuItemName ("SequinFeaturePropagate");
5139   editalign = FindFormMenuItem (bfp, mssgalign);
5140   editdup = FindFormMenuItem (bfp, mssgdup);
5141   editfeatprop = FindFormMenuItem (bfp, mssgfeatprop);
5142   sel = ObjMgrGetSelected ();
5143   sep = NULL;
5144   /*
5145   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
5146   if (bsp != NULL) {
5147     sep = GetBestTopParentForData (bfp->input_entityID, bsp);
5148   } else {
5149     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
5150   }
5151   */
5152   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
5153   num = CountSeqEntryAligns (bfp->input_entityID, sep);
5154   if (sep != NULL && num > 0) {
5155     if (sel != NULL && sel->entityID == bfp->input_entityID &&
5156         (sel->itemtype == OBJ_SEQALIGN || sel->itemtype == OBJ_SEQHIST_ALIGN)) {
5157       Enable (editalign);
5158     } else /* if (sel == NULL) */ {
5159       if (FindSeqAlignInSeqEntry (sep, OBJ_SEQALIGN) != NULL) {
5160         Enable (editalign);
5161       } else {
5162         Disable (editalign);
5163       }
5164     } /* else {
5165       Disable (editalign);
5166       Disable (editupwthaln);
5167     } */
5168   } else {
5169     Disable (editalign);
5170   }
5171   if (sel != NULL &&
5172       (sel->itemtype == OBJ_SEQDESC || sel->itemtype == OBJ_SEQFEAT)) {
5173     Enable (editdup);
5174   } else {
5175     Disable (editdup);
5176   }
5177   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
5178   if (num > 0 && bsp != NULL && sep != NULL && IS_Bioseq_set (sep)) {
5179     bssp = GetAlignmentSetForBioseq (bsp, bfp->input_entityID);
5180     if (bssp != NULL) {
5181       if (IsPopPhyEtcSet (bssp->_class)) {
5182         Enable (editfeatprop);
5183       } else if (bssp->_class == 7 && indexerVersion) {
5184         Enable (editfeatprop);
5185       } else {
5186         Disable (editfeatprop);
5187       }
5188     } else {
5189       Disable (editfeatprop);
5190     }
5191   } else {
5192     Disable (editfeatprop);
5193   }
5194 }
5195 
5196 static void EnableEditSeqAlignAndSubItems (BaseFormPtr bfp)
5197 
5198 {
5199   BioseqPtr      bsp;
5200   BioseqSetPtr   bssp;
5201   IteM           editseq;
5202   IteM           editsub;
5203   MenU           editupd;
5204   MenU           editupd_idx = NULL;
5205   MenU           editext;
5206   MenU           editadd;
5207   Int2           mssgadd;
5208   Int2           mssgseq;
5209   Int2           mssgsub;
5210   Int2           mssgupd;
5211   Int2           mssgupd_idx = 0;
5212   Int2           mssgext;
5213   ObjMgrDataPtr  omdp;
5214   SeqEntryPtr    sep;
5215 
5216   if (bfp == NULL && bfp->input_entityID != 0) return;
5217   mssgseq = RegisterFormMenuItemName ("SequinEditSequenceItem");
5218   mssgsub = RegisterFormMenuItemName ("SequinEditSubmitterItem");
5219   mssgupd = RegisterFormMenuItemName ("SequinUpdateSeqSubmenu");
5220   if (indexerVersion) {
5221     mssgupd_idx = RegisterFormMenuItemName ("SequinUpdateSeqSubmenuIndexer");
5222   }
5223   mssgext = RegisterFormMenuItemName ("SequinExtendSeqSubmenu");
5224   mssgadd = RegisterFormMenuItemName ("SequinAddSeqSubmenu");
5225   editseq = FindFormMenuItem (bfp, mssgseq);
5226   editsub = FindFormMenuItem (bfp, mssgsub);
5227   editupd = (MenU) FindFormMenuItem (bfp, mssgupd);
5228   if (indexerVersion) {
5229     editupd_idx = (MenU) FindFormMenuItem (bfp, mssgupd_idx);
5230   }
5231   editext = (MenU) FindFormMenuItem (bfp, mssgext);
5232   editadd = (MenU) FindFormMenuItem (bfp, mssgadd);
5233   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
5234   if (bsp != NULL) {
5235     Enable (editseq);
5236     Enable (editupd);
5237     if (indexerVersion) {
5238       Enable (editupd_idx);
5239     }
5240     Enable (editext);
5241     sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
5242     if (sep != NULL && IS_Bioseq_set (sep)) {
5243       bssp = (BioseqSetPtr) sep->data.ptrvalue;
5244       if (bssp != NULL && (bssp->_class == 7 || (IsPopPhyEtcSet (bssp->_class)))) {
5245         Enable (editadd);
5246       } else {
5247         Disable (editadd);
5248       }
5249     } else {
5250       Disable (editadd);
5251     }
5252 #ifdef WIN_MAC
5253     Enable (featPropItem);
5254 #endif
5255   } else {
5256     Disable (editseq);
5257     Disable (editupd);
5258     if (indexerVersion) {
5259       Disable (editupd_idx);
5260     }
5261     Disable (editext);
5262     Disable (editadd);
5263 #ifdef WIN_MAC
5264     Disable (featPropItem);
5265 #endif
5266   }
5267   omdp = ObjMgrGetData (bfp->input_entityID);
5268   if (omdp != NULL && omdp->datatype == OBJ_SEQSUB) {
5269     Enable (editsub);
5270 #ifdef WIN_MAC
5271     Enable (prepareItem);
5272     Enable (submitItem);
5273 #endif
5274   } else {
5275     Disable (editsub);
5276 #ifdef WIN_MAC
5277     Disable (prepareItem);
5278     Disable (submitItem);
5279 #endif
5280   }
5281   EnableEditAlignItem (bfp);
5282 }
5283 
5284 #ifdef WIN_MAC
5285 static void MedlineViewFormActivated (WindoW w)
5286 
5287 {
5288   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5289   initialFormsActive = FALSE;
5290   RepeatProcOnHandles (Enable,
5291                    (HANDLE) closeItem,
5292                    (HANDLE) duplicateViewItem,
5293                    (HANDLE) exportItem,
5294                    (HANDLE) printItem,
5295                    (HANDLE) copyItem,
5296                    (HANDLE) displayfontItem,
5297                    NULL);
5298 }
5299 
5300 static void BioseqViewFormActivated (WindoW w)
5301 
5302 {
5303   bioseqViewUp = TRUE;
5304   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5305   initialFormsActive = FALSE;
5306   /* SafeSetTitle (importItem, "Import Nucleotide FASTA..."); */
5307   RepeatProcOnHandles (Enable,
5308                    (HANDLE) openItem,
5309                    (HANDLE) closeItem,
5310                    (HANDLE) saveItem,
5311                    (HANDLE) saveAsItem,
5312                    (HANDLE) copyItem,
5313                    (HANDLE) deleteItem,
5314                    (HANDLE) findItem,
5315                    (HANDLE) findFFItem,
5316                    (HANDLE) findGeneItem,
5317                    (HANDLE) findProtItem,
5318                    (HANDLE) findPosItem,
5319                    (HANDLE) exportItem,
5320                    (HANDLE) duplicateViewItem,
5321                    (HANDLE) restoreItem,
5322                    (HANDLE) printItem,
5323                    (HANDLE) orfItem,
5324                    (HANDLE) targetItem,
5325                    (HANDLE) newDescMenu,
5326                    (HANDLE) newFeatMenu,
5327                    (HANDLE) advTableMenu,
5328                    (HANDLE) sucItem,
5329                    (HANDLE) newPubMenu,
5330                    (HANDLE) batchApplyMenu,
5331                    (HANDLE) batchEditMenu,
5332                    (HANDLE) prepareItem,
5333                    (HANDLE) edithistoryitem,
5334                    NULL);
5335   Enable (validateItem);
5336   Enable (validateMenu);
5337   Enable (vecscreenMenu);
5338   Enable (aluItem);
5339   Enable (submitItem);
5340   Enable (specialMenu);
5341   Enable (projectsMenu);
5342   Enable (analysisMenu);
5343   Enable (vectorScreenItem);
5344   Enable (cddBlastItem);
5345   Enable (cddSearchMenu);
5346   Enable (cddSearchItem);
5347   Enable (parseFileItem);
5348   Enable (spellItem);
5349   Enable (addSecondaryItem);
5350   Enable (displayfontItem);
5351   Disable (importItem);
5352   EnableFeaturesPerTarget ((BaseFormPtr) currentFormDataPtr);
5353   EnableAnalysisItems ((BaseFormPtr) currentFormDataPtr, FALSE);
5354   EnableEditSeqAlignAndSubItems ((BaseFormPtr) currentFormDataPtr);
5355 }
5356 
5357 /*
5358 static void TermSelectionActivateProc (WindoW w)
5359 
5360 {
5361   termListUp = TRUE;
5362   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5363   initialFormsActive = FALSE;
5364   if (UsingTextQuery ((ForM) w)) {
5365     SafeSetValue (queryChoice, 2);
5366   } else {
5367     SafeSetValue (queryChoice, 1);
5368   }
5369   RepeatProcOnHandles (Enable,
5370                    (HANDLE) importItem,
5371                    (HANDLE) exportItem,
5372                    (HANDLE) cutItem,
5373                    (HANDLE) copyItem,
5374                    (HANDLE) pasteItem,
5375                    (HANDLE) deleteItem,
5376                    (HANDLE) preferencesItem,
5377                    (HANDLE) queryChoice,
5378                    (HANDLE) clearUnusedItem,
5379                    NULL);
5380   Enable (loadUidItem);
5381   Enable (saveUidItem);
5382 }
5383 
5384 static void DocumentSummaryActivateProc (WindoW w)
5385 
5386 {
5387   docSumUp = TRUE;
5388   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5389   initialFormsActive = FALSE;
5390   if (UsingDelayedNeighbor ((ForM) w)) {
5391     SafeSetValue (neighborChoice, 2);
5392   } else {
5393     SafeSetValue (neighborChoice, 1);
5394   }
5395   RepeatProcOnHandles (Enable,
5396                    (HANDLE) saveAsItem,
5397                    (HANDLE) closeItem,
5398                    (HANDLE) importItem,
5399                    (HANDLE) exportItem,
5400                    (HANDLE) printItem,
5401                    (HANDLE) copyItem,
5402                    (HANDLE) preferencesItem,
5403                    (HANDLE) neighborChoice,
5404                    (HANDLE) docsumfontItem,
5405                    (HANDLE) analysisMenu,
5406                    NULL);
5407   Enable (loadUidItem);
5408   Enable (saveUidItem);
5409   EnableAnalysisItems ((BaseFormPtr) currentFormDataPtr, TRUE);
5410 }
5411 */
5412 
5413 static void SeqEditFormActivated (WindoW w)
5414 
5415 {
5416   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5417   initialFormsActive = FALSE;
5418   RepeatProcOnHandles (Enable,
5419                    (HANDLE) openItem,
5420                    (HANDLE) closeItem,
5421                    (HANDLE) cutItem,
5422                    (HANDLE) copyItem,
5423                    (HANDLE) pasteItem,
5424                    (HANDLE) deleteItem,
5425                    (HANDLE) importItem,
5426                    (HANDLE) exportItem,
5427                    NULL);
5428 }
5429 
5430 static void StdEditorFormActivated (WindoW w)
5431 
5432 {
5433   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5434   initialFormsActive = FALSE;
5435   RepeatProcOnHandles (Enable,
5436                    (HANDLE) openItem,
5437                    (HANDLE) closeItem,
5438                    (HANDLE) cutItem,
5439                    (HANDLE) copyItem,
5440                    (HANDLE) pasteItem,
5441                    (HANDLE) deleteItem,
5442                    (HANDLE) importItem,
5443                    (HANDLE) exportItem,
5444                    NULL);
5445 }
5446 
5447 static void StdValidatorFormActivated (WindoW w)
5448 
5449 {
5450   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5451   initialFormsActive = FALSE;
5452   RepeatProcOnHandles (Enable,
5453                    (HANDLE) openItem,
5454                    (HANDLE) closeItem,
5455                    (HANDLE) cutItem,
5456                    (HANDLE) copyItem,
5457                    (HANDLE) pasteItem,
5458                    (HANDLE) deleteItem,
5459                    (HANDLE) importItem,
5460                    (HANDLE) exportItem,
5461                    (HANDLE) printItem,
5462                    NULL);
5463 }
5464 
5465 static void TextViewProcFormActivated (WindoW w)
5466 
5467 {
5468   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5469   initialFormsActive = FALSE;
5470   RepeatProcOnHandles (Enable,
5471                    (HANDLE) openItem,
5472                    (HANDLE) closeItem,
5473                    (HANDLE) cutItem,
5474                    (HANDLE) copyItem,
5475                    (HANDLE) pasteItem,
5476                    (HANDLE) deleteItem,
5477                    (HANDLE) importItem,
5478                    (HANDLE) exportItem,
5479                    (HANDLE) printItem,
5480                    NULL);
5481 }
5482 
5483 static void ConfigFormActivated (WindoW w)
5484 
5485 {
5486   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5487   initialFormsActive = FALSE;
5488   RepeatProcOnHandles (Enable,
5489                    (HANDLE) cutItem,
5490                    (HANDLE) copyItem,
5491                    (HANDLE) pasteItem,
5492                    (HANDLE) deleteItem,
5493                    NULL);
5494 }
5495 
5496 static void StartupActivateProc (WindoW w)
5497 
5498 {
5499   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5500   initialFormsActive = FALSE;
5501   Enable (openItem);
5502 }
5503 
5504 static void FormatActivateProc (WindoW w)
5505 
5506 {
5507   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5508   initialFormsActive = TRUE;
5509   Enable (openItem);
5510 }
5511 
5512 static void SubmitBlockActivateProc (WindoW w)
5513 
5514 {
5515   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5516   initialFormsActive = TRUE;
5517   RepeatProcOnHandles (Enable,
5518                    (HANDLE) openItem,
5519                    (HANDLE) cutItem,
5520                    (HANDLE) copyItem,
5521                    (HANDLE) pasteItem,
5522                    (HANDLE) deleteItem,
5523                    (HANDLE) importItem,
5524                    (HANDLE) exportItem,
5525                    NULL);
5526 }
5527 
5528 static void GenomeFormActivateProc (WindoW w)
5529 
5530 {
5531   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5532   initialFormsActive = TRUE;
5533   RepeatProcOnHandles (Enable,
5534                    (HANDLE) openItem,
5535                    (HANDLE) cutItem,
5536                    (HANDLE) copyItem,
5537                    (HANDLE) pasteItem,
5538                    (HANDLE) deleteItem,
5539                    (HANDLE) importItem,
5540                    (HANDLE) exportItem,
5541                    NULL);
5542 }
5543 
5544 static void OrgAndSeqsActivateProc (WindoW w)
5545 
5546 {
5547   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5548   initialFormsActive = TRUE;
5549   RepeatProcOnHandles (Enable,
5550                    (HANDLE) openItem,
5551                    (HANDLE) cutItem,
5552                    (HANDLE) copyItem,
5553                    (HANDLE) pasteItem,
5554                    (HANDLE) deleteItem,
5555                    (HANDLE) importItem,
5556                    (HANDLE) exportItem,
5557                    NULL);
5558 }
5559 
5560 static void HelpActivateProc (WindoW w)
5561 
5562 {
5563   currentFormDataPtr = (VoidPtr) GetObjectExtra (w);
5564   RepeatProcOnHandles (Enable,
5565                    (HANDLE) openItem,
5566                    (HANDLE) closeItem,
5567                    (HANDLE) cutItem,
5568                    (HANDLE) copyItem,
5569                    (HANDLE) pasteItem,
5570                    (HANDLE) deleteItem,
5571                    (HANDLE) exportItem,
5572                    (HANDLE) printItem,
5573                    NULL);
5574 }
5575 
5576 static void MacDeactProc (WindoW w)
5577 
5578 {
5579   termListUp = FALSE;
5580   docSumUp = FALSE;
5581   bioseqViewUp = FALSE;
5582   currentFormDataPtr = NULL;
5583   initialFormsActive = FALSE;
5584   Enable (openItem);
5585   SafeSetTitle (importItem, "Import...");
5586   SafeSetTitle (exportItem, "Export...");
5587   SafeSetValue (queryChoice, 0);
5588   SafeSetValue (neighborChoice, 0);
5589   RepeatProcOnHandles (Disable,
5590                    (HANDLE) saveItem,
5591                    (HANDLE) saveAsItem,
5592                    (HANDLE) closeItem,
5593                    (HANDLE) cutItem,
5594                    (HANDLE) copyItem,
5595                    (HANDLE) pasteItem,
5596                    (HANDLE) deleteItem,
5597                    (HANDLE) duplicateViewItem,
5598                    (HANDLE) importItem,
5599                    (HANDLE) exportItem,
5600                    (HANDLE) findItem,
5601                    (HANDLE) findFFItem,
5602                    (HANDLE) findGeneItem,
5603                    (HANDLE) findProtItem,
5604                    (HANDLE) findPosItem,
5605                    (HANDLE) orfItem,
5606                    (HANDLE) targetItem,
5607                    (HANDLE) newDescMenu,
5608                    (HANDLE) newFeatMenu,
5609                    (HANDLE) advTableMenu,
5610                    (HANDLE) sucItem,
5611                    (HANDLE) newPubMenu,
5612                    (HANDLE) batchApplyMenu,
5613                    (HANDLE) batchEditMenu,
5614                    (HANDLE) prepareItem,
5615                    (HANDLE) editsequenceitem,
5616                    (HANDLE) editseqalignitem,
5617                    (HANDLE) editseqsubitem,
5618                    (HANDLE) edithistoryitem,
5619                    (HANDLE) updateSeqMenu,
5620                    (HANDLE) extendSeqMenu,
5621                    (HANDLE) addSeqMenu,
5622                    (HANDLE) featPropItem,
5623                    (HANDLE) updalignitem,
5624                    (HANDLE) updalignidxitem,
5625                    NULL);
5626   Disable (validateItem);
5627   Disable (validateMenu);
5628   Disable (vecscreenMenu);
5629   Disable (aluItem);
5630   Disable (submitItem);
5631   Disable (vectorScreenItem);
5632   Disable (cddBlastItem);
5633   Disable (cddSearchMenu);
5634   Disable (cddSearchItem);
5635   Disable (parseFileItem);
5636   Disable (spellItem);
5637   Disable (docsumfontItem);
5638   Disable (queryChoice);
5639   Disable (clearUnusedItem);
5640   Disable (neighborChoice);
5641   Disable (legendItem);
5642   Disable (duplicateItem);
5643   Disable (addSecondaryItem);
5644   Disable (displayfontItem);
5645   Disable (printItem);
5646   Disable (restoreItem);
5647   Disable (specialMenu);
5648   Disable (projectsMenu);
5649   Disable (analysisMenu);
5650   Disable (loadUidItem);
5651   Disable (saveUidItem);
5652   if (indexerVersion) {
5653     Disable (updateSeqMenuIndexer);
5654   }
5655 }
5656 #endif
5657 
5658 #ifndef WIN_MAC
5659 #define MedlineViewFormActivated NULL
5660 #define BioseqViewFormActivated NULL
5661 #define TermSelectionActivateProc NULL
5662 #define DocumentSummaryActivateProc NULL
5663 #define SeqEditFormActivated NULL
5664 #define StdEditorFormActivated NULL
5665 #define StdValidatorFormActivated NULL
5666 #define TextViewProcFormActivated NULL
5667 #define ConfigFormActivated NULL
5668 #define StartupActivateProc NULL
5669 #define FormatActivateProc NULL
5670 #define SubmitBlockActivateProc NULL
5671 #define OrgAndSeqsActivateProc NULL
5672 #define GenomeFormActivateProc NULL
5673 #define HelpActivateProc NULL
5674 #endif
5675 
5676 static void HideHelpForm (ButtoN b)
5677 
5678 {
5679   Hide (ParentWindow (b));
5680 }
5681 
5682 static void DisplayHelpFormProc (IteM i)
5683 
5684 {
5685   if (helpForm == NULL) {
5686     WatchCursor ();
5687     helpForm = CreateHelpForm (-95, -5, "Sequin Help", "sequin.hlp",
5688                                HideHelpForm, HelpActivateProc);
5689     ArrowCursor ();
5690   }
5691   if (helpForm != NULL) {
5692     Show (helpForm);
5693     Select (helpForm);
5694   }
5695 }
5696 
5697 /*#ifdef USE_MEDARCH*/
5698 
5699 static Boolean debug_fix_pub_equiv = FALSE;
5700 static Boolean debug_fix_pub_set = FALSE;
5701 
5702 static Boolean log_mla_asn = FALSE;
5703 static Boolean log_mla_set = FALSE;
5704 
5705 static ValNodePtr LookupAnArticleFuncNew (ValNodePtr oldpep, BoolPtr success)
5706 
5707 {
5708   CitArtPtr      cap = NULL;
5709   ArticleIdPtr   ids;
5710   MlaBackPtr     mbp;
5711   MlaRequestPtr  mrp;
5712   Int4           pmid = 0;
5713   ValNodePtr     pub = NULL;
5714   ValNodePtr     vnp;
5715 #ifdef OS_UNIX
5716   CharPtr        str;
5717 #endif
5718 
5719   if (success != NULL) {
5720     *success = FALSE;
5721   }
5722   if (oldpep == NULL) return NULL;
5723 
5724 #ifdef OS_UNIX
5725   if (! log_mla_set) {
5726     str = (CharPtr) getenv ("LOG_MLA_ASN");
5727     if (StringDoesHaveText (str)) {
5728       if (StringICmp (str, "TRUE") == 0) {
5729         log_mla_asn = TRUE;
5730       }
5731     }
5732     log_mla_set = TRUE;
5733   }
5734 #endif
5735 
5736   for (vnp = oldpep; vnp != NULL; vnp = vnp->next) {
5737     if (vnp->choice == PUB_Article) {
5738       cap = (CitArtPtr) vnp->data.ptrvalue;
5739     } else if (vnp->choice == PUB_PMid) {
5740       pmid = (Int4) vnp->data.intvalue;
5741     }
5742   }
5743 
5744   if (cap != NULL) {
5745     mrp = Mla2CreateCitArtMatchRequest (cap);
5746     if (mrp != NULL) {
5747       if (log_mla_asn) {
5748         LaunchAsnTextViewer ((Pointer) mrp, (AsnWriteFunc) MlaRequestAsnWrite, "citart match request");
5749       }
5750       mbp = Mla2SynchronousQuery (mrp);
5751       mrp = MlaRequestFree (mrp);
5752       if (mbp != NULL) {
5753         if (log_mla_asn) {
5754           LaunchAsnTextViewer ((Pointer) mbp, (AsnWriteFunc) MlaBackAsnWrite, "citart match result");
5755         }
5756         pmid = Mla2ExtractCitMatchReply (mbp);
5757         mbp = MlaBackFree (mbp);
5758       }
5759     }
5760   }
5761 
5762   if (pmid > 0) {
5763     mrp = Mla2CreatePubFetchRequest (pmid);
5764     if (mrp != NULL) {
5765       if (log_mla_asn) {
5766         LaunchAsnTextViewer ((Pointer) mrp, (AsnWriteFunc) MlaRequestAsnWrite, "get pub request");
5767       }
5768       mbp = Mla2SynchronousQuery (mrp);
5769       mrp = MlaRequestFree (mrp);
5770       if (mbp != NULL) {
5771         if (log_mla_asn) {
5772           LaunchAsnTextViewer ((Pointer) mbp, (AsnWriteFunc) MlaBackAsnWrite, "get pub result");
5773         }
5774         cap = Mla2ExtractPubFetchReply (mbp);
5775         if (cap != NULL) {
5776           if (log_mla_asn) {
5777             LaunchAsnTextViewer ((Pointer) cap, (AsnWriteFunc) CitArtAsnWrite, "before");
5778           }
5779           ChangeCitArtMLAuthorsToSTD (cap);
5780           if (log_mla_asn) {
5781             LaunchAsnTextViewer ((Pointer) cap, (AsnWriteFunc) CitArtAsnWrite, "after");
5782           }
5783           for (ids = cap->ids; ids != NULL; ids = ids->next) {
5784             if (ids->choice != ARTICLEID_PUBMED) continue;
5785             if (ids->data.intvalue != pmid) {
5786               Message (MSG_POSTERR, "CitArt ID %ld does not match PMID %ld",
5787                        (long) ids->data.intvalue, (long) pmid);
5788             }
5789           }
5790           pub = ValNodeAddPointer (NULL, PUB_Article, (Pointer) cap);
5791           ValNodeAddInt (&pub, PUB_PMid, pmid);
5792           if (success != NULL) {
5793             *success = TRUE;
5794           }
5795         }
5796         mbp = MlaBackFree (mbp);
5797       }
5798     }
5799   }
5800 
5801   return pub;
5802 }
5803 
5804 static ValNodePtr LookupAnArticleFunc (ValNodePtr oldpep, BoolPtr success)
5805 
5806 {
5807   FindPubOption  fpo;
5808   MonitorPtr     mon;
5809   Int4           muid = 0;
5810   ValNodePtr     pep;
5811   Int4           pmid = 0;
5812   ValNodePtr     pub;
5813   ValNodePtr     vnp;
5814 #ifdef OS_UNIX
5815   AsnIoPtr       aip;
5816   CharPtr        str;
5817 #endif
5818 
5819   pub = NULL;
5820   if (oldpep != NULL) {
5821     WatchCursor ();
5822     mon = MonitorStrNewEx ("Lookup Article", 40, FALSE);
5823     MonitorStrValue (mon, "Connecting to MedArch");
5824     Update ();
5825     if (MedArchInit ()) {
5826 #ifdef OS_UNIX
5827       if (! debug_fix_pub_set) {
5828         str = (CharPtr) getenv ("DEBUG_FIX_PUB_EQUIV");
5829         if (StringDoesHaveText (str)) {
5830           if (StringICmp (str, "TRUE") == 0) {
5831             debug_fix_pub_equiv = TRUE;
5832           }
5833         }
5834         debug_fix_pub_set = TRUE;
5835       }
5836 #endif
5837       pep = AsnIoMemCopy (oldpep, (AsnReadFunc) PubEquivAsnRead,
5838                           (AsnWriteFunc) PubEquivAsnWrite);
5839       fpo.always_look = TRUE;
5840       fpo.replace_cit = TRUE;
5841       fpo.lookups_attempted = 0;
5842       fpo.lookups_succeeded = 0;
5843       fpo.fetches_attempted = 0;
5844       fpo.fetches_succeeded = 0;
5845       MonitorStrValue (mon, "Performing Lookup");
5846       Update ();
5847 #ifdef OS_UNIX
5848       if (debug_fix_pub_equiv) {
5849         if (pep != NULL) {
5850           aip = AsnIoOpen ("origpubequiv.txt", "w");
5851           if (aip != NULL) {
5852             PubEquivAsnWrite (pep, aip, NULL);
5853             AsnIoClose (aip);
5854           }
5855         }
5856       }
5857 #endif
5858       pub = FixPubEquiv (pep, &fpo);
5859       if (fpo.fetches_succeeded && success != NULL) {
5860         *success = TRUE;
5861       }
5862 #ifdef OS_UNIX
5863       if (debug_fix_pub_equiv) {
5864         if (pub != NULL) {
5865           aip = AsnIoOpen ("fixpubequiv.txt", "w");
5866           if (aip != NULL) {
5867             PubEquivAsnWrite (pub, aip, NULL);
5868             AsnIoClose (aip);
5869           }
5870         }
5871       }
5872 #endif
5873       if (! fpo.fetches_succeeded) {
5874         ErrShow ();
5875         Update ();
5876       } else {
5877         for (vnp = pub; vnp != NULL; vnp = vnp->next) {
5878           if (vnp->choice == PUB_Muid) {
5879             muid = vnp->data.intvalue;
5880           } else if (vnp->choice == PUB_PMid) {
5881             pmid = vnp->data.intvalue;
5882           }
5883         }
5884         if (muid != 0 && pmid == 0) {
5885           pmid = MedArchMu2Pm (muid);
5886           if (pmid != 0) {
5887             ValNodeAddInt (&pub, PUB_PMid, pmid);
5888           }
5889         } else if (pmid != 0 && muid == 0) {
5890           muid = MedArchPm2Mu (pmid);
5891           if (muid != 0) {
5892             ValNodeAddInt (&pub, PUB_Muid, muid);
5893           }
5894         }
5895       }
5896       MonitorStrValue (mon, "Closing MedArch");
5897       Update ();
5898       MedArchFini ();
5899       MonitorFree (mon);
5900       ArrowCursor ();
5901       Update ();
5902     } else {
5903       ArrowCursor ();
5904       Message (MSG_ERROR, "Unable to connect to MedArch");
5905       MonitorFree (mon);
5906       Update ();
5907     }
5908   }
5909   return pub;
5910 }
5911 
5912 
5913 static Boolean HasMoreThanOneISOJTA (TitleMsgPtr titles)
5914 {
5915   TitleMsgPtr tmp;
5916   ValNodePtr  ttl;
5917   Int4 num_found = 0;
5918 
5919   for (tmp = titles; tmp != NULL; tmp = tmp->next) {
5920     for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
5921       if (ttl->choice == Cit_title_iso_jta) {
5922         if (num_found > 0) {
5923           return TRUE;
5924         }
5925         num_found++;
5926         break;
5927       }
5928     }
5929   }
5930   return FALSE;
5931 }
5932 
5933 
5934 static CharPtr GetExtendedDescription (TitleMsgPtr tmp) 
5935 {
5936   CharPtr iso_jta = NULL, name = NULL, issn = NULL, extended = NULL;
5937   ValNodePtr ttl;
5938 
5939   if (tmp == NULL) {
5940     return NULL;
5941   }
5942   
5943   for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
5944     if (ttl->choice == Cit_title_iso_jta) {
5945       iso_jta = ttl->data.ptrvalue;
5946     } else if (ttl->choice == Cit_title_name) {
5947       name = ttl->data.ptrvalue;
5948     } else if (ttl->choice == Cit_title_issn) {
5949       issn = ttl->data.ptrvalue;
5950     }
5951   }
5952   if (iso_jta == NULL) {
5953     return NULL;
5954   }
5955   if (name == NULL && issn == NULL) {
5956     extended = StringSave (iso_jta);
5957   } else if (name == NULL) {
5958     extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (issn) + 5));
5959     sprintf (extended, "%s||(%s)", iso_jta, issn);
5960   } else if (issn == NULL) {
5961     extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (name) + 5));
5962     sprintf (extended, "%s||(%s)", iso_jta, name);
5963   } else {
5964     extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (name) + StringLen (issn) + 6));
5965     sprintf (extended, "%s||(%s:%s)", iso_jta, name, issn);
5966   }
5967   return extended;
5968 }
5969 
5970 static Boolean LookupJournalFuncNew (CharPtr title, size_t maxsize, Int1Ptr jtaType, ValNodePtr PNTR all_titlesP)
5971 
5972 {
5973   ValNodePtr       first = NULL;
5974   ValNodePtr       last = NULL;
5975   MlaBackPtr       mbp;
5976   MlaRequestPtr    mrp;
5977   CharPtr          str, end;
5978   TitleMsgListPtr  tlp;
5979   TitleMsgPtr      tmp;
5980   ValNodePtr       ttl;
5981   ValNodePtr       vnp;
5982 
5983   if (all_titlesP != NULL) {
5984     *all_titlesP = NULL;
5985   }
5986   if (jtaType != NULL) {
5987     *jtaType = 0;
5988   }
5989   if (StringHasNoText (title)) return FALSE;
5990 
5991 #ifdef OS_UNIX
5992   if (! log_mla_set) {
5993     str = (CharPtr) getenv ("LOG_MLA_ASN");
5994     if (StringDoesHaveText (str)) {
5995       if (StringICmp (str, "TRUE") == 0) {
5996         log_mla_asn = TRUE;
5997       }
5998     }
5999     log_mla_set = TRUE;
6000   }
6001 #endif
6002 
6003   WatchCursor ();
6004   Update ();
6005 
6006   mrp = Mla2CreateJournalTitleRequest (title);
6007   if (mrp != NULL) {
6008   if (log_mla_asn) {
6009     LaunchAsnTextViewer ((Pointer) mrp, (AsnWriteFunc) MlaRequestAsnWrite, "lookup journal request");
6010   }
6011     mbp = Mla2SynchronousQuery (mrp);
6012     mrp = MlaRequestFree (mrp);
6013     if (mbp != NULL) {
6014       if (log_mla_asn) {
6015         LaunchAsnTextViewer ((Pointer) mbp, (AsnWriteFunc) MlaBackAsnWrite, "lookup journal result");
6016       }
6017       tlp = Mla2ExtractJournalTitleReply (mbp);
6018       if (tlp != NULL) {
6019         if (HasMoreThanOneISOJTA (tlp->titles)) {
6020           for (tmp = tlp->titles; tmp != NULL; tmp = tmp->next) {
6021             str = GetExtendedDescription (tmp);
6022             if (str != NULL) {
6023               ValNodeAddPointer (&first, 0, str);
6024             }
6025           }
6026         } else {
6027           for (tmp = tlp->titles; tmp != NULL; tmp = tmp->next) {
6028             for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
6029               if (ttl->choice != Cit_title_iso_jta) continue;
6030               str = (CharPtr) ttl->data.ptrvalue;
6031               if (StringHasNoText (str)) continue;
6032               vnp = ValNodeCopyStr (&last, ttl->choice, str);
6033               if (first == NULL) {
6034                 first = vnp;
6035               }
6036               last = vnp;
6037             }
6038           }
6039         }
6040         if (first != NULL) {
6041           str = (CharPtr) first->data.ptrvalue;
6042           StringNCpy_0 (title, str, maxsize);
6043           end = StringSearch (title, "||");
6044           if (end != NULL) {
6045             *end = 0;
6046           }
6047           if (jtaType != NULL) {
6048             *jtaType = Cit_title_iso_jta;
6049           }
6050         }
6051         if (all_titlesP == NULL) {
6052           first = ValNodeFreeData (first);
6053         } else {
6054           *all_titlesP = first;
6055         }
6056         tlp = TitleMsgListFree (tlp);
6057       }
6058       mbp = MlaBackFree (mbp);
6059     }
6060   }
6061 
6062   ArrowCursor ();
6063   Update ();
6064 
6065   return TRUE;
6066 }
6067 
6068 static Boolean LookupJournalFunc (CharPtr title, size_t maxsize, Int1Ptr jtaType, ValNodePtr PNTR all_titlesP)
6069 
6070 {
6071   ValNodePtr  first = NULL;
6072   Int4        i;
6073   ValNodePtr  last = NULL;
6074   MonitorPtr  mon;
6075   Int4        num;
6076   Char        str [256];
6077   CharPtr     titles [20];
6078   Int1        types [20];
6079   ValNodePtr  vnp;
6080 
6081   WatchCursor ();
6082   mon = MonitorStrNewEx ("Lookup Journal", 40, FALSE);
6083   MonitorStrValue (mon, "Connecting to MedArch");
6084   Update ();
6085   if (MedArchInit ()) {
6086     StringNCpy_0 (str, title, sizeof (str));
6087     if (str [0] != '\0') {
6088       MonitorStrValue (mon, "Performing Lookup");
6089       Update ();
6090       num = MedArchGetTitles (titles, types, str, (Int1) Cit_title_jta,
6091                               Cit_title_iso_jta, 20);
6092       if (num > 0 && all_titlesP != NULL) {
6093         for (i = 0; i < num; i++) {
6094           vnp = ValNodeCopyStr (&last, types [i], titles [i]);
6095           if (first == NULL) {
6096             first = vnp;
6097           }
6098           last = vnp;
6099         }
6100         *all_titlesP = first;
6101       }
6102       if (num > 0 && types [0] == Cit_title_iso_jta) {
6103         StringNCpy_0 (title, titles [0], maxsize);
6104         if (jtaType != NULL) {
6105           *jtaType = types [0];
6106         }
6107         for (i = 0; i < num; i++) {
6108           MemFree (titles [i]);
6109         }
6110       } else {
6111         /*
6112         Message (MSG_OK, "Unable to match journal");
6113         */
6114       }
6115     }
6116     MonitorStrValue (mon, "Closing MedArch");
6117     Update ();
6118     MedArchFini ();
6119     MonitorFree (mon);
6120     ArrowCursor ();
6121     Update ();
6122     return TRUE;
6123   } else {
6124     ArrowCursor ();
6125     Message (MSG_ERROR, "Unable to connect to MedArch");
6126     MonitorFree (mon);
6127     Update ();
6128   }
6129   return FALSE;
6130 }
6131 /*#endif*/
6132 
6133 /*#ifdef USE_TAXON*/
6134 static Boolean LookupTaxonomyFunc (Uint2 entityID)
6135 
6136 {
6137   SeqEntryPtr  sep;
6138 
6139   if (entityID < 1) return FALSE;
6140   sep = GetTopSeqEntryForEntityID (entityID);
6141   if (sep == NULL) return FALSE;
6142   if (! leaveAsOldAsn) {
6143     MySeqEntryToAsn3 (sep, TRUE, FALSE, TRUE);
6144   }
6145   return TRUE;
6146 }
6147 /*#endif*/
6148 
6149 extern void QuitProc (void);
6150 extern void QuitProc (void)
6151 
6152 {
6153   Boolean        dirty;
6154   Uint4          j;
6155   Uint4          num;
6156   ObjMgrPtr      omp;
6157   ObjMgrDataPtr  PNTR omdpp;
6158   ObjMgrDataPtr  tmp;
6159 #ifdef USE_SMARTNET
6160   SMUserDataPtr  sm_usr_data = NULL;
6161   OMUserDataPtr  omudp;
6162 #endif
6163 
6164 #ifdef WIN_MAC
6165   if (initialFormsActive) {
6166     if (Message (MSG_YN,
6167         "This will end your session without saving any data.\nAre you sure you want to exit?") == ANS_YES) {
6168       QuitProgram ();
6169     }
6170     return;
6171   }
6172 #endif
6173 
6174   if (smartnetMode) {
6175 #ifdef USE_SMARTNET
6176       
6177       omp = ObjMgrGet ();
6178       num = omp->HighestEntityID;
6179       for(j = 1; j <= omp->HighestEntityID; j++) {
6180           if((omudp = ObjMgrGetUserData(j, 0,0, SMART_KEY)) != NULL) {
6181             if((sm_usr_data = 
6182                 (SMUserDataPtr) omudp->userdata.ptrvalue) != NULL &&
6183                sm_usr_data->fd != 0) {
6184               sm_usr_data->header->status = SMStatClosed;
6185               SMSendMsgToClient(sm_usr_data);
6186             }              
6187           }
6188       }
6189 #endif
6190       QuitProgram ();
6191       return;
6192   }
6193 
6194   dirty = FALSE;
6195   omp = ObjMgrGet ();
6196   num = omp->currobj;
6197   for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
6198     tmp = *omdpp;
6199     if (tmp->parentptr == NULL) {
6200       if (tmp->dirty) {
6201         dirty = TRUE;
6202       }
6203     }
6204   }
6205   if (dirty) {
6206     if (Message (MSG_YN,
6207         "Some data have not been saved.\nAre you sure you want to exit?") == ANS_NO) {
6208       return;
6209     }
6210   } else if (subtoolMode || smartnetMode) {
6211     if (Message (MSG_YN,
6212         "Are you sure you want to exit?") == ANS_NO) {
6213       return;
6214     }
6215   }
6216 #ifndef WIN_MAC
6217   if (subtoolMode || smartnetMode || backupMode) {
6218     subtoolRecordDirty = FALSE;
6219     FileRemove (SEQUIN_EDIT_TEMP_FILE);
6220     /* FileRemove (SEQUIN_EDIT_PREV_FILE); */
6221     FileRemove (SEQUIN_EDIT_BACK_FILE);
6222     FileRemove (SEQUIN_EDIT_ARCH_FILE);
6223     FileRename (SEQUIN_EDIT_PREV_FILE, SEQUIN_EDIT_ARCH_FILE);
6224     if (backupMode) {
6225       FileRemove (SEQUIN_EDIT_ARCH_FILE);
6226     }
6227   }
6228 #endif
6229   QuitProgram ();
6230 }
6231 
6232 static void CloseProc (BaseFormPtr bfp)
6233 
6234 {
6235   BioseqViewFormPtr  bvfp;
6236   Uint2              entityID;
6237   Boolean            freeEditors = FALSE;
6238   Int4               num_dirty;
6239   Uint4              j;
6240   Uint4              num;
6241   Boolean            numview;
6242   ObjMgrPtr          omp;
6243   ObjMgrDataPtr      PNTR omdpp;
6244   OMUserDataPtr      omudp;
6245   ObjMgrDataPtr      tmp;
6246   Uint2              userkey;
6247   ValNodePtr         vnp;
6248 #ifdef USE_SMARTNET
6249   SMUserDataPtr     sm_usr_data = NULL;
6250 #endif
6251 
6252 #ifdef WIN_MAC
6253   if (initialFormsActive) return;
6254 #endif
6255   if (bfp != NULL) {
6256     omp = ObjMgrGet ();
6257     num = omp->currobj;
6258     for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
6259       tmp = *omdpp;
6260       if (tmp->parentptr == NULL && tmp->EntityID == bfp->input_entityID) {
6261         num_dirty = 0;
6262         numview = 0;
6263         for (omudp = tmp->userdata; omudp != NULL; omudp = omudp->next) {
6264           if (omudp->proctype == OMPROC_VIEW) {
6265             numview++;
6266             if (tmp->dirty) {
6267               num_dirty++;
6268             }
6269           }
6270         }
6271         if (num_dirty == 1 && numview < 2) {
6272           if (Message (MSG_OKC,
6273               "Closing the window will lose unsaved data.") != ANS_OK) {
6274             return;
6275           }
6276         }
6277         if (numview < 2) {
6278           freeEditors = TRUE;
6279         }
6280       }
6281     }
6282     if (freeEditors) {
6283       bvfp = (BioseqViewFormPtr) bfp;
6284       if (bvfp->input_entityID > 0 && bvfp->userkey > 0) {
6285         /* need to unlock far components before freeing data */
6286         if (bvfp->bvd.bsplist != NULL) {
6287           bvfp->bvd.bsplist = UnlockFarComponents (bvfp->bvd.bsplist);
6288         }
6289         userkey = bvfp->userkey;
6290         bvfp->userkey = 0;
6291         /* ObjMgrFreeUserData (bvfp->input_entityID, bvfp->procid, bvfp->proctype, userkey); */
6292         /* this may trigger another remove, hence bvfp->userkey first set to 0 */
6293         for (vnp = bvfp->bvd.entityList; vnp != NULL; vnp = vnp->next) {
6294           if (bvfp->input_entityID != (Uint2) vnp->data.intvalue) {
6295             ObjMgrFreeUserData ((Uint2) vnp->data.intvalue, bvfp->procid, bvfp->proctype, userkey);
6296           }
6297         }
6298         bvfp->userkey = userkey;
6299       }
6300       if (bvfp->bvd.entityList != NULL) {
6301         bvfp->bvd.entityList = ValNodeFree (bvfp->bvd.entityList);
6302       }
6303     }
6304     numview = 0;
6305     for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
6306       tmp = *omdpp;
6307 
6308       if (tmp->parentptr == NULL) {
6309           for (omudp = tmp->userdata; omudp != NULL; omudp = omudp->next) {
6310 
6311               if (omudp->proctype == OMPROC_VIEW) {
6312                   numview++;
6313               }
6314           }
6315       }
6316     }
6317 
6318     entityID = bfp->input_entityID;
6319     if(!smartnetMode) {
6320         /* RemoveSeqEntryViewer (bfp->form); */ /* can go back to Remove */
6321         Remove (bfp->form);
6322         if (freeEditors) {
6323           ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0);
6324         }
6325     }
6326 
6327     if (numview <= 1) {
6328         if (subtoolMode || stdinMode || binseqentryMode) {
6329             Message (MSG_OK, "No more viewers, quitting program.");
6330             QuitProgram ();
6331             return;
6332         } else if (smartnetMode) {
6333 #ifdef USE_SMARTNET
6334           if((omudp = 
6335               ObjMgrGetUserData(bfp->input_entityID, 0, 0, SMART_KEY)) != NULL) {
6336               if((sm_usr_data = 
6337                   (SMUserDataPtr) omudp->userdata.ptrvalue) != NULL && 
6338                  sm_usr_data->fd != (int) NULL) {
6339                   sm_usr_data->header->status = SMStatClosed;
6340                   SMSendMsgToClient(sm_usr_data); 
6341               }
6342 
6343               RemoveSeqEntryViewer (bfp->form);
6344               ObjMgrFreeUserData(entityID, 0, 0, SMART_KEY); 
6345               ObjMgrFreeUserData (entityID, 0, 0, DUMB_KEY);
6346               if (freeEditors) {
6347                 ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0);
6348                 if (DeleteRemainingViews(entityID)) {
6349                   VSeqMgrShow();
6350                 }
6351               }
6352               
6353           }
6354           return;
6355 #endif
6356         }
6357 
6358         WatchCursor ();
6359         Update ();
6360         if (! workbenchMode) {
6361             if (termListForm != NULL || docSumForm != NULL) {
6362             } else {
6363                 Show (startupForm);
6364                 Select (startupForm);
6365                 SendHelpScrollMessage (helpForm, "Initial Entry", NULL);
6366             }
6367             ArrowCursor ();
6368             Update ();
6369         }
6370     } else { /* numview > 1 */
6371         if(smartnetMode) {
6372             entityID = bfp->input_entityID;
6373             RemoveSeqEntryViewer (bfp->form);
6374 #ifdef USE_SMARTNET 
6375             /* sssddd   ObjMgrFreeUserData(entityID, 0, 0, SMART_KEY); */
6376 #endif 
6377             if (freeEditors) {
6378               ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0);
6379             }
6380         }
6381 
6382     }
6383   }
6384 }
6385 
6386 static void EditSubmitBlock (BaseFormPtr bfp)
6387 
6388 {
6389   Int2           handled;
6390   ObjMgrDataPtr  omdp;
6391 
6392   if (bfp != NULL && bfp->input_entityID != 0) {
6393     omdp = ObjMgrGetData (bfp->input_entityID);
6394     if (omdp != NULL) {
6395       if (omdp->datatype == OBJ_SEQSUB) {
6396         WatchCursor ();
6397         handled = GatherProcLaunch (OMPROC_EDIT, FALSE, bfp->input_entityID, 1,
6398                                     OBJ_SUBMIT_BLOCK, 0, 0, OBJ_SUBMIT_BLOCK, 0);
6399         ArrowCursor ();
6400         if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
6401           Message (MSG_FATAL, "Unable to launch editor.");
6402         }
6403       } else {
6404         Message (MSG_OK, "Record has no submit block.  This may be added when record is first read.");
6405       }
6406     }
6407   }
6408 }
6409 
6410 /*
6411 static void DisplayFontChangeProc (IteM i)
6412 
6413 {
6414   BaseFormPtr  bfp;
6415   FonT         fnt;
6416   FontSpec     fs;
6417 
6418 #ifdef WIN_MAC
6419   bfp = currentFormDataPtr;
6420 #else
6421   bfp = GetObjectExtra (i);
6422 #endif
6423   if (bfp != NULL) {
6424     MemSet ((Pointer) (&fs), 0, sizeof (FontSpec));
6425     fnt = programFont;
6426     if (seqviewprocs.displayFont != NULL) {
6427       fnt = seqviewprocs.displayFont;
6428     }
6429     GetFontSpec (fnt, &fs);
6430     if (ChooseFont (&fs, CFF_READ_FSP | CFF_MONOSPACE, NULL)) {
6431       seqviewprocs.displayFont = CreateFont (&fs);
6432       SendMessageToForm (bfp->form, VIB_MSG_REDRAW);
6433     }
6434   }
6435 }
6436 */
6437 
6438 static void DuplicateViewProc (IteM i)
6439 
6440 {
6441   BaseFormPtr  bfp;
6442   Int2         handled;
6443   Uint4        itemID;
6444 
6445 #ifdef WIN_MAC
6446   bfp = currentFormDataPtr;
6447 #else
6448   bfp = GetObjectExtra (i);
6449 #endif
6450   if (bfp == NULL) return;
6451   if (bfp->input_itemtype == OBJ_BIOSEQ) {
6452     WatchCursor ();
6453     itemID = bfp->input_itemID;
6454     if (itemID == 0) {
6455       itemID = 1;
6456     }
6457     seqviewprocs.forceSeparateViewer = TRUE;
6458     SeqEntrySetScope (NULL);
6459     handled = GatherProcLaunch (OMPROC_VIEW, FALSE, bfp->input_entityID, itemID,
6460                                 OBJ_BIOSEQ, 0, 0, OBJ_BIOSEQ, 0);
6461     ArrowCursor ();
6462     if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
6463       Message (MSG_ERROR, "Unable to launch additional viewer.");
6464     }
6465   } else if (bfp->input_itemtype == OBJ_MEDLINE_ENTRY) {
6466     WatchCursor ();
6467     itemID = bfp->input_itemID;
6468     if (itemID == 0) {
6469       itemID = 1;
6470     }
6471     handled = GatherProcLaunch (OMPROC_VIEW, FALSE, bfp->input_entityID, itemID,
6472                                 OBJ_MEDLINE_ENTRY, 0, 0, OBJ_MEDLINE_ENTRY, 0);
6473     ArrowCursor ();
6474     if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
6475       Message (MSG_ERROR, "Unable to launch additional viewer.");
6476     }
6477   }
6478 }
6479 
6480 
6481 static void RestoreSeqEntryProc (IteM i)
6482 
6483 {
6484   BaseFormPtr  bfp;
6485   Char         path [PATH_MAX];
6486   Uint2        new_entityID;
6487 
6488 #ifdef WIN_MAC
6489   bfp = currentFormDataPtr;
6490 #else
6491   bfp = GetObjectExtra (i);
6492 #endif
6493   if (bfp != NULL && bfp->input_itemtype == OBJ_BIOSEQ) {
6494     if (GetInputFileName (path, sizeof (path), "", "TEXT")) {
6495       new_entityID = RestoreEntityIDFromFile (path, bfp->input_entityID);
6496       if (new_entityID != 0) {
6497         bfp->input_entityID = new_entityID;
6498         ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
6499         ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
6500       }
6501     }
6502   }
6503 }
6504 
6505 void AddAboutAndHelpMenuItems (MenU m)
6506 
6507 {
6508   CommandItem (m, "About Sequin...", AboutProc);
6509   CommandItem (m, "Help...", DisplayHelpFormProc);
6510   SeparatorItem (m);
6511 }
6512 
6513 static void FindOrf (IteM i)
6514 
6515 {
6516   BaseFormPtr  bfp;
6517   BioseqPtr    bsp;
6518 
6519 #ifdef WIN_MAC
6520   bfp = currentFormDataPtr;
6521 #else
6522   bfp = GetObjectExtra (i);
6523 #endif
6524   if (bfp == NULL) return;
6525   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
6526   if (bsp == NULL) return;
6527   LaunchOrfViewer (bsp, bfp->input_entityID, bfp->input_itemID, FALSE);
6528 }
6529 
6530 static void FindAlu (IteM i)
6531 
6532 {
6533   MsgAnswer    ans;
6534   BaseFormPtr  bfp;
6535   BioseqPtr    bsp;
6536   Boolean      got_some;
6537 
6538 #ifdef WIN_MAC
6539   bfp = currentFormDataPtr;
6540 #else
6541   bfp = GetObjectExtra (i);
6542 #endif
6543   if (bfp == NULL) return;
6544   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
6545   if (bsp == NULL) return;
6546   if (bsp->length >= 100) {
6547     ans = Message (MSG_OKC, "This calculation may take a while");
6548     if (ans == ANS_CANCEL) return;
6549   }
6550   WatchCursor ();
6551   got_some = FindHumanRepeats (bsp, TRUE);
6552   ArrowCursor ();
6553   if (got_some) {
6554     Message (MSG_OK, "Repeat regions were found.");
6555     ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
6556     ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
6557   } else {
6558     Message (MSG_OK, "No Repeat regions found.");
6559   }
6560 }
6561 
6562 typedef struct changetargetform {
6563   FORM_MESSAGE_BLOCK
6564   TexT               seqid;
6565   BaseFormPtr        base;
6566 } ChangeTargetForm, PNTR ChangeTargetFormPtr;
6567 
6568 static void AcceptChangeTargetProc (ButtoN b)
6569 
6570 {
6571   ChangeTargetFormPtr  cfp;
6572   Char                 str [128];
6573 
6574   cfp = (ChangeTargetFormPtr) GetObjectExtra (b);
6575   if (cfp == NULL) return;
6576   GetTitle (cfp->seqid, str, sizeof (str));
6577   SetBioseqViewTarget (cfp->base, str);
6578 }
6579 
6580 static void ClearTargetBtn (ButtoN b)
6581 
6582 {
6583   ChangeTargetFormPtr  cfp;
6584 
6585   cfp = (ChangeTargetFormPtr) GetObjectExtra (b);
6586   if (cfp == NULL) return;
6587   SetTitle (cfp->seqid, "");
6588 }
6589 
6590 static void ChangeTargetMessageProc (ForM f, Int2 mssg)
6591 
6592 {
6593   StdEditorProcsPtr  sepp;
6594 
6595   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
6596   if (sepp != NULL) {
6597     if (sepp->handleMessages != NULL) {
6598       sepp->handleMessages (f, mssg);
6599     }
6600   }
6601 }
6602 
6603 extern void ChangeTargetBaseForm (BaseFormPtr bfp)
6604 {
6605   ButtoN               b;
6606   GrouP                c;
6607   ChangeTargetFormPtr  cfp;
6608   GrouP                g;
6609   StdEditorProcsPtr    sepp;
6610   WindoW               w;
6611 
6612   if (bfp == NULL) return;
6613 
6614   cfp = (ChangeTargetFormPtr) MemNew (sizeof (ChangeTargetForm));
6615   if (cfp == NULL) return;
6616   w = FixedWindow (-50, -33, -10, -10, "Select Target by SeqID", StdCloseWindowProc);
6617   SetObjectExtra (w, cfp, StdCleanupFormProc);
6618   cfp->form = (ForM) w;
6619   cfp->formmessage = ChangeTargetMessageProc;
6620 
6621   g = HiddenGroup (w, -1, 0, NULL);
6622   SetGroupSpacing (g, 10, 10);
6623 
6624   cfp->seqid = DialogText (g, "", 12, NULL);
6625   cfp->base = bfp;
6626   c = HiddenGroup (g, 3, 0, NULL);
6627   SetGroupSpacing (c, 10, 10);
6628   b = DefaultButton (c, "Accept", AcceptChangeTargetProc);
6629   SetObjectExtra (b, cfp, NULL);
6630   b = PushButton (c, "Clear", ClearTargetBtn);
6631   SetObjectExtra (b, cfp, NULL);
6632   PushButton (c, "Cancel", StdCancelButtonProc);
6633 
6634   AlignObjects (ALIGN_CENTER, (HANDLE) cfp->seqid, (HANDLE) c, NULL);
6635   RealizeWindow (w);
6636   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
6637   if (sepp != NULL) {
6638     SetActivate (w, sepp->activateForm);
6639   }
6640   Show (w);
6641   Select (w);
6642 }
6643 
6644 static void DoChangeTarget (IteM i)
6645 
6646 {
6647   BaseFormPtr          bfp;
6648 
6649 #ifdef WIN_MAC
6650   bfp = currentFormDataPtr;
6651 #else
6652   bfp = GetObjectExtra (i);
6653 #endif
6654   ChangeTargetBaseForm (bfp);
6655 }
6656 
6657 static void ConfigFormMessage (ForM f, Int2 mssg)
6658 
6659 {
6660   BaseFormPtr        bfp;
6661   StdEditorProcsPtr  sepp;
6662 
6663   bfp = (BaseFormPtr) GetObjectExtra (f);
6664   if (bfp != NULL) {
6665     switch (mssg) {
6666       case VIB_MSG_CUT :
6667         StdCutTextProc (NULL);
6668         break;
6669       case VIB_MSG_COPY :
6670         StdCopyTextProc (NULL);
6671         break;
6672       case VIB_MSG_PASTE :
6673         StdPasteTextProc (NULL);
6674         break;
6675       case VIB_MSG_DELETE :
6676         StdDeleteTextProc (NULL);
6677         break;
6678       default :
6679         sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
6680         if (sepp != NULL && sepp->handleMessages != NULL) {
6681           sepp->handleMessages (f, mssg);
6682         }
6683         break;
6684     }
6685   }
6686 }
6687 
6688 static void ConfigAccepted (void)
6689 
6690 {
6691   if (WriteSequinAppParam ("SETTINGS", "PUBLICNETWORKSEQUIN", "TRUE")) {
6692     Message (MSG_OK, "Setting will take affect when you restart Sequin");
6693   }
6694 }
6695 
6696 static void ConfigCancelled (void)
6697 
6698 {
6699   Message (MSG_OK, "No changes to the network configuration have been made");
6700 }
6701 
6702 static void ConfigTurnedOff (void)
6703 
6704 {
6705   if (WriteSequinAppParam ("SETTINGS", "PUBLICNETWORKSEQUIN", "FALSE")) {
6706     Message (MSG_OK, "Setting will take affect when you restart Sequin");
6707   }
6708 }
6709 
6710 typedef struct prefsform {
6711   FORM_MESSAGE_BLOCK
6712   DialoG             prefs;
6713 } PrefsForm, PNTR PrefsFormPtr;
6714 
6715 /*
6716 static void AcceptPrefsProc (ButtoN b)
6717 
6718 {
6719   EntrezPrefsPtr  epp;
6720   PrefsFormPtr    pfp;
6721 
6722   pfp = (PrefsFormPtr) GetObjectExtra (b);
6723   if (pfp == NULL) return;
6724   Hide (pfp->form);
6725   epp = (EntrezPrefsPtr) DialogToPointer (pfp->prefs);
6726   if (epp != NULL) {
6727     entrezglobals.persistDefault = epp->persistDefault;
6728     entrezglobals.alignDefault = epp->alignDefault;
6729     entrezglobals.lookupDirect = epp->lookupDirect;
6730     entrezglobals.showAsn = epp->showAsn;
6731     ReplaceString (&entrezglobals.initDatabase, epp->initDatabase);
6732     ReplaceString (&entrezglobals.initField, epp->initField);
6733     ReplaceString (&entrezglobals.initMode, epp->initMode);
6734     ReplaceString (&medviewprocs.initMedLabel, epp->initMedLabel);
6735     ReplaceString (&seqviewprocs.initNucLabel, epp->initNucLabel);
6736     ReplaceString (&seqviewprocs.initProtLabel, epp->initProtLabel);
6737     ReplaceString (&seqviewprocs.initGenomeLabel, epp->initGenomeLabel);
6738     SetSequinAppParamTF ("PREFERENCES", "PARENTSPERSIST", entrezglobals.persistDefault);
6739     SetSequinAppParamTF ("PREFERENCES", "ALIGNCHECKED", entrezglobals.alignDefault);
6740     SetSequinAppParamTF ("PREFERENCES", "LOOKUPDIRECT", entrezglobals.lookupDirect);
6741     SetSequinAppParamTF ("PREFERENCES", "SHOWASNPAGE", entrezglobals.showAsn);
6742     SetSequinAppParam ("SETTINGS", "DATABASE", entrezglobals.initDatabase);
6743     SetSequinAppParam ("SETTINGS", "FIELD", entrezglobals.initField);
6744     SetSequinAppParam ("SETTINGS", "MODE", entrezglobals.initMode);
6745     SetSequinAppParam ("SETTINGS", "MEDPAGE", medviewprocs.initMedLabel);
6746     SetSequinAppParam ("SETTINGS", "NUCPAGE", seqviewprocs.initNucLabel);
6747     SetSequinAppParam ("SETTINGS", "PRTPAGE", seqviewprocs.initProtLabel);
6748     SetSequinAppParam ("SETTINGS", "GENMPAGE", seqviewprocs.initGenomeLabel);
6749   }
6750   EntrezPrefsFree (epp);
6751   Remove (pfp->form);
6752 }
6753 */
6754 
6755 static void DefaultMessageProc (ForM f, Int2 mssg)
6756 
6757 {
6758   StdEditorProcsPtr  sepp;
6759 
6760   sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
6761   if (sepp != NULL) {
6762     if (sepp->handleMessages != NULL) {
6763       sepp->handleMessages (f, mssg);
6764     }
6765   }
6766 }
6767 
6768 static void PreferencesProc (IteM i)
6769 
6770 {
6771   /*
6772   ButtoN          b;
6773   GrouP           c;
6774   EntrezPrefsPtr  epp;
6775   GrouP           g;
6776   PrefsFormPtr    pfp;
6777   WindoW          w;
6778 
6779   pfp = (PrefsFormPtr) MemNew (sizeof (PrefsForm));
6780   if (pfp == NULL) return;
6781   if (! EntrezIsInited ()) {
6782     EntrezBioseqFetchEnable ("Sequin", TRUE);
6783     SequinEntrezInit ("Sequin", FALSE, NULL);
6784   }
6785   w = FixedWindow (-50, -33, -10, -10, "Preferences", StdCloseWindowProc);
6786   SetObjectExtra (w, pfp, StdCleanupFormProc);
6787   pfp->form = (ForM) w;
6788   pfp->formmessage = DefaultMessageProc;
6789   g = HiddenGroup (w, -1, 0, NULL);
6790   SetGroupSpacing (g, 10, 10);
6791   pfp->prefs = CreateEntrezPrefsDialog (g, NULL);
6792   c = HiddenGroup (g, 2, 0, NULL);
6793   b = DefaultButton (c, "Accept", AcceptPrefsProc);
6794   SetObjectExtra (b, pfp, NULL);
6795   PushButton (c, "Cancel", StdCancelButtonProc);
6796   AlignObjects (ALIGN_CENTER, (HANDLE) pfp->prefs, (HANDLE) c, NULL);
6797   RealizeWindow (w);
6798   epp = EntrezPrefsNew ();
6799   if (epp != NULL) {
6800     epp->persistDefault = entrezglobals.persistDefault;
6801     epp->alignDefault = entrezglobals.alignDefault;
6802     epp->lookupDirect = entrezglobals.lookupDirect;
6803     epp->showAsn = entrezglobals.showAsn;
6804     epp->initDatabase = StringSaveNoNull (entrezglobals.initDatabase);
6805     epp->initField = StringSaveNoNull (entrezglobals.initField);
6806     epp->initMode = StringSaveNoNull (entrezglobals.initMode);
6807     epp->initMedLabel = StringSaveNoNull (medviewprocs.initMedLabel);
6808     epp->initNucLabel = StringSaveNoNull (seqviewprocs.initNucLabel);
6809     epp->initProtLabel = StringSaveNoNull (seqviewprocs.initProtLabel);
6810     epp->initGenomeLabel = StringSaveNoNull (seqviewprocs.initGenomeLabel);
6811   }
6812   PointerToDialog (pfp->prefs, (Pointer) epp);
6813   EntrezPrefsFree (epp);
6814   Show (w);
6815   Select (w);
6816   */
6817 }
6818 
6819 void NetConfigureProc (IteM i)
6820 
6821 {
6822   Boolean  netCurrentlyOn = FALSE;
6823   Char     str [32];
6824 
6825   if (GetSequinAppParam ("SETTINGS", "PUBLICNETWORKSEQUIN", NULL, str, sizeof (str))) {
6826     if (StringICmp (str, "TRUE") == 0) {
6827       netCurrentlyOn = TRUE;
6828     }
6829   }
6830   if (useEntrez) {
6831     netCurrentlyOn = TRUE;
6832   }
6833   SendHelpScrollMessage (helpForm, "Misc Menu", "Net Configure");
6834   ShowNetConfigForm (ConfigFormActivated, ConfigFormMessage,
6835                      ConfigAccepted, ConfigCancelled,
6836                      ConfigTurnedOff, netCurrentlyOn);
6837 }
6838 
6839 
6840 extern void SqnReadAlignView (BaseFormPtr bfp, BioseqPtr target_bsp, SeqEntryPtr source_sep, Boolean do_update)
6841 
6842 {
6843   BioseqPtr  nbsp;
6844 
6845   if (target_bsp == NULL || source_sep == NULL) return;
6846   nbsp = FindNucBioseq (source_sep);
6847   if (nbsp == NULL) return;
6848 
6849   if (do_update) {
6850     UpdateSeqAfterDownload (bfp, target_bsp, nbsp);
6851   } else {
6852     ExtendSeqAfterDownload (bfp, target_bsp, nbsp);
6853   }
6854 }
6855 
6856 extern void NewFeaturePropagate (
6857   IteM i
6858 );
6859 
6860 static void ExtendSeqWithFASTA (IteM i)
6861 
6862 {
6863   NewExtendSequence (i);
6864 }
6865 
6866 static void ExtendSeqWithRec (IteM i)
6867 
6868 {
6869   NewExtendSequence (i);
6870 }
6871 
6872 NLM_EXTERN Int4 GenomeFromLocName (CharPtr loc_name);
6873 
6874 /*******COLOMBE ***********/
6875 
6876 
6877 static void CommonAddSeq (IteM i, Int2 type)
6878 
6879 {
6880   Nlm_QualNameAssocPtr qp;
6881   BaseFormPtr        bfp;
6882   Uint1              biomol;
6883   BioSourcePtr       biop = NULL;
6884   BioseqPtr          bsp;
6885   BioseqSetPtr       bssp;
6886   Pointer            dataptr;
6887   Uint2              datatype;
6888   FILE               *fp;
6889   MolInfoPtr         mip;
6890   MolInfoPtr         molinf = NULL;
6891   OrgRefPtr          orp;
6892   SeqEntryPtr        nuc;
6893   Char               path [PATH_MAX];
6894   CharPtr            ptr;
6895   SeqEntryPtr        sep;
6896   BioSourcePtr       src = NULL;
6897   Char               str [128];
6898   CharPtr            tax = NULL;
6899   CharPtr            title = NULL;
6900   SeqEntryPtr        top;
6901   ValNodePtr         vnp;
6902   Int4               tmp;
6903 
6904 #ifdef WIN_MAC
6905   bfp = currentFormDataPtr;
6906 #else
6907   bfp = GetObjectExtra (i);
6908 #endif
6909   if (bfp == NULL) return;
6910   top = GetTopSeqEntryForEntityID (bfp->input_entityID);
6911   if (top == NULL) return;
6912   if (type == 1 || type == 2) {
6913     if (! GetInputFileName (path, sizeof (path),"","TEXT")) return;
6914     fp = FileOpen (path, "r");
6915     if (fp == NULL) return;
6916     if (IS_Bioseq_set (top)) {
6917       bssp = (BioseqSetPtr) top->data.ptrvalue;
6918       if (bssp != NULL && bssp->_class != BioseqseqSet_class_phy_set) {
6919         sep = bssp->seq_set;
6920         vnp = SeqEntryGetSeqDescr (top, Seq_descr_source, NULL);
6921         if (vnp != NULL) {
6922           src = (BioSourcePtr) vnp->data.ptrvalue;
6923           if (src != NULL) {
6924             orp = biop->org;
6925             if (orp != NULL) {
6926               tax = orp->taxname;
6927             }
6928           }
6929         }
6930       }
6931     }
6932     nuc = FindNucSeqEntry (top);
6933     vnp = SeqEntryGetSeqDescr (nuc, Seq_descr_molinfo, NULL);
6934     if (vnp != NULL) {
6935       molinf = (MolInfoPtr) vnp->data.ptrvalue;
6936     }
6937     while ((dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, NULL, FALSE, FALSE, TRUE, FALSE)) != NULL) {
6938       if (datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET) {
6939         bsp = NULL;
6940         bssp = NULL;
6941         sep = SeqMgrGetSeqEntryForData (dataptr);
6942         if (sep == NULL) {
6943           sep = SeqEntryNew ();
6944           if (datatype == OBJ_BIOSEQ) {
6945             bsp = (BioseqPtr) dataptr;
6946             sep->choice = 1;
6947             sep->data.ptrvalue = bsp;
6948             SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, sep);
6949           } else if (datatype == OBJ_BIOSEQSET) {
6950             bssp = (BioseqSetPtr) dataptr;
6951             sep->choice = 2;
6952             sep->data.ptrvalue = bssp;
6953             SeqMgrSeqEntry (SM_BIOSEQSET, (Pointer) bssp, sep);
6954           } else {
6955             sep = SeqEntryFree (sep);
6956           }
6957         }
6958         if (sep != NULL) {
6959           AddSeqEntryToSeqEntry (top, sep, TRUE);
6960           title = SeqEntryGetTitle (sep);
6961           vnp = SeqEntryGetSeqDescr (sep, Seq_descr_source, NULL);
6962           if (vnp == NULL || title != NULL) {
6963             ptr = StringISearch (title, "[org=");
6964             if (ptr != NULL) {
6965               StringNCpy_0 (str, ptr + 5, sizeof (str));
6966               ptr = StringChr (str, ']');
6967             } else {
6968               ptr = StringISearch (title, "[organism=");
6969               if (ptr != NULL) {
6970                 StringNCpy_0 (str, ptr + 10, sizeof (str));
6971                 ptr = StringChr (str, ']');
6972               }
6973             }
6974             if (ptr != NULL) {
6975               *ptr = '\0';
6976               biop = BioSourceNew ();
6977               if (biop != NULL) {
6978                 orp = OrgRefNew ();
6979                 biop->org = orp;
6980                 if (orp != NULL) {
6981                   SetTaxNameAndRemoveTaxRef (orp, StringSave (str));
6982                 }
6983                 vnp = CreateNewDescriptor (sep, Seq_descr_source);
6984                 if (vnp != NULL) {
6985                   vnp->data.ptrvalue = (Pointer) biop;
6986                 }
6987               }
6988             }
6989           }
6990           if (vnp == NULL && tax != NULL) {
6991             biop = BioSourceNew ();
6992             if (biop != NULL) {
6993               orp = OrgRefNew ();
6994               biop->org = orp;
6995               if (orp != NULL) {
6996                 SetTaxNameAndRemoveTaxRef (orp, tax);
6997               }
6998               vnp = CreateNewDescriptor (sep, Seq_descr_source);
6999               if (vnp != NULL) {
7000                 vnp->data.ptrvalue = (Pointer) biop;
7001               }
7002             }
7003           }
7004           vnp = SeqEntryGetSeqDescr (sep, Seq_descr_source, NULL);
7005           if (vnp != NULL) {
7006             biop = (BioSourcePtr) vnp->data.ptrvalue;
7007           }
7008           if (biop != NULL && title != NULL) {
7009             for (qp = current_orgmod_subtype_alist; qp->name != NULL; qp++) {
7010               MakeSearchStringFromAlist (str, qp->name);
7011               AddToOrgMod (biop, title, str, qp->value);
7012               ExciseString (title, str, "]");
7013             }
7014             for (qp = current_subsource_subtype_alist; qp->name != NULL; qp++) {
7015               MakeSearchStringFromAlist (str, qp->name);
7016               AddToSubSource (biop, title, str, qp->value);
7017               ExciseString (title, str, "]");
7018             }
7019             AddToOrgMod (biop, title, "[note=", 255);
7020             ExciseString (title, "[note=", "]");
7021             AddToSubSource (biop, title, "[subsource=", 255);
7022             ExciseString (title, "[subsource=", "]");
7023             ExciseString (title, "[org=", "]");
7024             ExciseString (title, "[organism=", "]");
7025             if (bsp != NULL) {
7026               ptr = StringISearch (title, "[molecule=");
7027               if (ptr != NULL) {
7028                 StringNCpy_0 (str, ptr + 10, sizeof (str));
7029                 ptr = StringChr (str, ']');
7030                 if (ptr != NULL) {
7031                   *ptr = '\0';
7032                   if (StringCmp (str, "dna") == 0) {
7033                     bsp->mol = Seq_mol_dna;
7034                   } else if (StringCmp (str, "rna") == 0) {
7035                     bsp->mol = Seq_mol_rna;
7036                   }
7037                 }
7038               }
7039             }
7040             ptr = StringISearch (title, "[location=");
7041             if (ptr != NULL) {
7042               StringNCpy_0 (str, ptr + 10, sizeof (str));
7043               ptr = StringChr (str, ']');
7044               if (ptr != NULL) {
7045                 *ptr = '\0';
7046                 if (StringICmp (str, "Mitochondrial") == 0) { /* alternative spelling */
7047                   biop->genome = 5;
7048                 }
7049                 tmp = GenomeFromLocName (str);
7050                 if (tmp > -1) {
7051                   biop->genome = tmp;
7052                 }
7053               }
7054             }
7055             ptr = StringISearch (title, "[moltype=");
7056             if (ptr != NULL) {
7057               biomol = 0;
7058               StringNCpy_0 (str, ptr + 8, sizeof (str));
7059               ptr = StringChr (str, ']');
7060               if (ptr != NULL) {
7061                 *ptr = '\0';
7062                 if (StringICmp (str, "genomic") == 0) {
7063                   biomol = MOLECULE_TYPE_GENOMIC;
7064                 } else if (StringICmp (str, "mRNA") == 0) {
7065                   biomol = MOLECULE_TYPE_MRNA;
7066                 }
7067                 if (biomol != 0) {
7068                   mip = MolInfoNew ();
7069                   if (mip != NULL) {
7070                     mip->biomol = biomol;
7071                     vnp = CreateNewDescriptor (sep, Seq_descr_molinfo);
7072                     if (vnp != NULL) {
7073                       vnp->data.ptrvalue = (Pointer) mip;
7074                     }
7075                   }
7076                 }
7077               }
7078             }
7079           }
7080           ExciseString (title, "[molecule=", "]");
7081           ExciseString (title, "[moltype=", "]");
7082           ExciseString (title, "[location=", "]");
7083           TrimSpacesAroundString (title);
7084           if (title != NULL && StringHasNoText (title)) {
7085             vnp = NULL;
7086             if (IS_Bioseq (sep)) {
7087               bsp = (BioseqPtr) sep->data.ptrvalue;
7088               vnp = ValNodeExtract (&(bsp->descr), Seq_descr_title);
7089             } else if (IS_Bioseq_set (sep)) {
7090               bssp = (BioseqSetPtr) sep->data.ptrvalue;
7091               vnp = ValNodeExtract (&(bssp->descr), Seq_descr_title);
7092             }
7093             if (vnp != NULL && StringHasNoText ((CharPtr) vnp->data.ptrvalue)) {
7094               vnp = ValNodeFreeData (vnp);
7095             }
7096           }
7097           sep = FindNucSeqEntry (sep);
7098           vnp = SeqEntryGetSeqDescr (sep, Seq_descr_molinfo, NULL);
7099           if (vnp == NULL && molinf != NULL) {
7100             mip = MolInfoNew ();
7101             if (mip != NULL) {
7102               vnp = CreateNewDescriptor (sep, Seq_descr_molinfo);
7103               if (vnp != NULL) {
7104                 vnp->data.ptrvalue = (Pointer) mip;
7105                 mip->biomol = molinf->biomol;
7106                 mip->tech = molinf->tech;
7107                 mip->completeness = molinf->completeness;
7108               }
7109             }
7110           }
7111         }
7112       }
7113     }
7114     FileClose (fp);
7115     ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
7116     ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
7117     Update ();
7118   } else {
7119     Message (MSG_OK, "Not yet implemented");
7120   }
7121 }
7122 
7123 static void AddSeqWithFASTA (IteM i)
7124 
7125 {
7126   CommonAddSeq (i, 1);
7127 }
7128 
7129 static void AddSeqWithRec (IteM i)
7130 
7131 {
7132   CommonAddSeq (i, 2);
7133 }
7134 
7135 /*#ifdef ALLOW_DOWNLOAD*/
7136 BioseqPtr  updateTargetBspKludge = NULL;
7137 
7138 static void ExtendSeqWithAcc (IteM i)
7139 
7140 {
7141   BaseFormPtr  bfp;
7142   BioseqPtr    bsp;
7143   SeqEntryPtr  sep;
7144 
7145 #ifdef WIN_MAC
7146   bfp = currentFormDataPtr;
7147 #else
7148   bfp = GetObjectExtra (i);
7149 #endif
7150   if (bfp == NULL) return;
7151   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
7152   if (sep == NULL) return;
7153   bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
7154   if (bsp == NULL) return;
7155   updateTargetBspKludge = bsp;
7156   CommonFetchFromNet (DownloadAndExtendProc, StdCancelButtonProc);
7157 }
7158 /*#endif*/
7159 
7160 
7161 #ifndef WIN_MAC
7162 extern void CreateNewLayoutMenu (MenU m, BaseFormPtr bp);
7163 
7164 static void MedlineViewFormMenus (WindoW w)
7165 
7166 {
7167   BaseFormPtr  bfp;
7168   IteM         i;
7169   MenU         m;
7170 
7171   bfp = (BaseFormPtr) GetObjectExtra (w);
7172   if (bfp != NULL) {
7173     m = PulldownMenu (w, "File");
7174     FormCommandItem (m, "Close", bfp, VIB_MSG_CLOSE);
7175     SeparatorItem (m);
7176     i = CommandItem (m, "Duplicate", DuplicateViewProc);
7177     SetObjectExtra (i, bfp, NULL);
7178     SeparatorItem (m);
7179     FormCommandItem (m, "Export...", bfp, VIB_MSG_EXPORT);
7180     SeparatorItem (m);
7181     /*
7182     FormCommandItem (m, "Save", bfp, VIB_MSG_SAVE);
7183     FormCommandItem (m, "Save As...", bfp, VIB_MSG_SAVE_AS);
7184     SeparatorItem (m);
7185     */
7186     FormCommandItem (m, "Print...", bfp, VIB_MSG_PRINT);
7187 
7188     m = PulldownMenu (w, "Edit");
7189     FormCommandItem (m, COPY_MENU_ITEM, bfp, VIB_MSG_COPY);
7190   }
7191 }
7192 
7193 
7194 static void BioseqViewFormMenus (WindoW w)
7195 
7196 {
7197   BaseFormPtr    bfp;
7198   IteM           i;
7199   MenU           m;
7200   Int2           mssgadd;
7201   Int2           mssgalign;
7202   Int2           mssgdup;
7203   Int2           mssgfeatprop;
7204   Int2           mssgseq;
7205   Int2           mssgsub;
7206   Int2           mssgupd, mssgupd_idx;
7207   Int2           mssgext;
7208   ObjMgrDataPtr  omdp;
7209   MenU           sub;
7210 
7211   bfp = (BaseFormPtr) GetObjectExtra (w);
7212   if (bfp != NULL) {
7213     m = PulldownMenu (w, "File/ F");
7214 /*#ifdef INTERNAL_NCBI_SEQUIN*/
7215     if (indexerVersion) {
7216       if (subtoolMode || stdinMode || binseqentryMode) {
7217         FormCommandItem (m, "Abort Session", bfp, VIB_MSG_QUIT);
7218         SeparatorItem (m);
7219         CommandItem (m, "Accept Changes", SubtoolDoneProc);
7220         SeparatorItem (m);
7221       } else if (smartnetMode) {
7222 #ifdef USE_SMARTNET
7223         FormCommandItem (m, "Abort Session", bfp, VIB_MSG_CLOSE);
7224         SeparatorItem (m);
7225         i = CommandItem (m, "Accept Changes", SmartnetDoneProc);
7226         SetObjectExtra (i, bfp, NULL);
7227         SeparatorItem (m);
7228 #endif
7229       }
7230     }
7231 /*#endif*/
7232     AddAboutAndHelpMenuItems (m);
7233     i = CommandItem (m, "Open...", ReadNewAsnProc);
7234     SetObjectExtra (i, bfp, NULL);
7235     if (indexerVersion) {
7236       i = CommandItem (m, "FASTA Nucleotide Direct to Sequence Editor", FastaNucDirectToSeqEdProc);
7237       SetObjectExtra (i, bfp, NULL);
7238     }
7239     SeparatorItem (m);
7240     FormCommandItem (m, "Close", bfp, VIB_MSG_CLOSE);
7241     SeparatorItem (m);
7242     /* FormCommandItem (m, "Import Nucleotide FASTA...", bfp, VIB_MSG_IMPORT); */
7243     FormCommandItem (m, "Export...", bfp, VIB_MSG_EXPORT);
7244     SeparatorItem (m);
7245     i = CommandItem (m, "Duplicate View", DuplicateViewProc);
7246     SetObjectExtra (i, bfp, NULL);
7247     SeparatorItem (m);
7248     FormCommandItem (m, "Save", bfp, VIB_MSG_SAVE);
7249     FormCommandItem (m, "Save As...", bfp, VIB_MSG_SAVE_AS);
7250     i = CommandItem (m, "Save As Binary Seq-entry...", SaveBinSeqEntry);
7251     SetObjectExtra (i, bfp, NULL);
7252     SeparatorItem (m);
7253     i = CommandItem (m, "Restore...", RestoreSeqEntryProc);
7254     SetObjectExtra (i, bfp, NULL);
7255     if ((! subtoolMode) && (! stdinMode) &&
7256         (! binseqentryMode) && (! smartnetMode)) {
7257       SeparatorItem (m);
7258       i = CommandItem (m, "Prepare Submission...", PrepareSeqSubmitProc);
7259       SetObjectExtra (i, bfp, NULL);
7260       omdp = ObjMgrGetData (bfp->input_entityID);
7261       if (omdp != NULL && omdp->datatype != OBJ_SEQSUB) {
7262         Disable (i);
7263       }
7264       /*
7265       i = CommandItem (m, "Submit to NCBI", SubmitToNCBI);
7266       SetObjectExtra (i, bfp, NULL);
7267       if (omdp != NULL && omdp->datatype != OBJ_SEQSUB) {
7268         Disable (i);
7269       }
7270       */
7271     }
7272 /*#ifdef INTERNAL_NCBI_SEQUIN*/
7273     if (indexerVersion) {
7274       if ((! subtoolMode) && (! stdinMode) &&
7275           (! binseqentryMode) && (! smartnetMode)) {
7276         SeparatorItem (m);
7277         FormCommandItem (m, "Print", bfp, VIB_MSG_PRINT);
7278         SeparatorItem (m);
7279         FormCommandItem (m, "Quit/Q", bfp, VIB_MSG_QUIT);
7280       } else {
7281         SeparatorItem (m);
7282         i = CommandItem (m, "Propagate Top Descriptors", ForcePropagate);
7283         SetObjectExtra (i, bfp, NULL);
7284         SeparatorItem (m);
7285         FormCommandItem (m, "Print", bfp, VIB_MSG_PRINT);
7286         if (smartnetMode) {
7287           SeparatorItem (m);
7288           FormCommandItem (m, "Quit/Q", bfp, VIB_MSG_QUIT);
7289         }
7290       }
7291     } else {
7292 /*#else*/
7293       if (subtoolMode || stdinMode || binseqentryMode) {
7294         FormCommandItem (m, "Print", bfp, VIB_MSG_PRINT);
7295         SeparatorItem (m);
7296         FormCommandItem (m, "Abort Session", bfp, VIB_MSG_QUIT);
7297         SeparatorItem (m);
7298         CommandItem (m, "Accept Changes", SubtoolDoneProc);
7299       } else if (smartnetMode) {
7300 #ifdef USE_SMARTNET
7301         FormCommandItem (m, "Print", bfp, VIB_MSG_PRINT);
7302         SeparatorItem (m);
7303         FormCommandItem (m, "Abort Session", bfp, VIB_MSG_CLOSE);
7304         SeparatorItem (m);
7305         i = CommandItem (m, "Accept Changes", SmartnetDoneProc);
7306         SetObjectExtra (i, bfp, NULL);
7307         SeparatorItem (m);
7308         FormCommandItem (m, "Quit/Q", bfp, VIB_MSG_QUIT);
7309 #endif
7310       } else {
7311         SeparatorItem (m);
7312         FormCommandItem (m, "Print", bfp, VIB_MSG_PRINT);
7313         SeparatorItem (m);
7314         FormCommandItem (m, "Quit/Q", bfp, VIB_MSG_QUIT);
7315       }
7316     }
7317 /*#endif*/
7318 
7319     m = PulldownMenu (w, "Edit/ E");
7320     if (subtoolMode || smartnetMode || backupMode) {
7321       FormCommandItem (m, UNDO_MENU_ITEM, bfp, VIB_MSG_UNDO);
7322       SeparatorItem (m);
7323     }
7324     FormCommandItem (m, COPY_MENU_ITEM, bfp, VIB_MSG_COPY);
7325     FormCommandItem (m, CLEAR_MENU_ITEM, bfp, VIB_MSG_DELETE);
7326     SeparatorItem (m);
7327     if (extraServices) {
7328       mssgdup = RegisterFormMenuItemName ("SequinDuplicateItem");
7329       FormCommandItem (m, "Duplicate...", bfp, mssgdup);
7330       SeparatorItem (m);
7331     }
7332     if (genomeCenter != NULL || indexerVersion) {
7333       SetupEditSecondary (m, bfp);
7334       SeparatorItem (m);
7335     }
7336     mssgseq = RegisterFormMenuItemName ("SequinEditSequenceItem");
7337     mssgalign = RegisterFormMenuItemName ("SequinEditAlignmentItem");
7338     mssgsub = RegisterFormMenuItemName ("SequinEditSubmitterItem");
7339     mssgupd = RegisterFormMenuItemName ("SequinUpdateSeqSubmenu");
7340     if (indexerVersion)
7341     {
7342       mssgupd_idx = RegisterFormMenuItemName ("SequinUpdateSeqSubmenuIndexer");
7343     }
7344     mssgext = RegisterFormMenuItemName ("SequinExtendSeqSubmenu");
7345     mssgfeatprop = RegisterFormMenuItemName ("SequinFeaturePropagate");
7346     mssgadd = RegisterFormMenuItemName ("SequinAddSeqSubmenu");
7347     FormCommandItem (m, "Edit Sequence...", bfp, mssgseq);
7348     FormCommandItem (m, "Alignment Assistant...", bfp, mssgalign);
7349     FormCommandItem (m, "Edit Submitter Info...", bfp, mssgsub);
7350     if (indexerVersion) {
7351       SeparatorItem (m);
7352       i = CommandItem (m, "Edit History....", EditSequenceHistory);
7353       SetObjectExtra (i, bfp, NULL);
7354     }
7355     SeparatorItem (m);
7356     
7357     if (indexerVersion)
7358     {
7359       /* indexer version */
7360       sub = SubMenu (m, "Indexer Update Sequence");
7361       SetFormMenuItem (bfp, mssgupd_idx, (IteM) sub);
7362       i = CommandItem (sub, "Single Sequence", TestUpdateSequenceIndexer);
7363       SetObjectExtra (i, bfp, NULL);
7364       if (useEntrez) {
7365         i = CommandItem (sub, "Download Accession", UpdateSequenceViaDownloadIndexer);
7366         SetObjectExtra (i, bfp, NULL);    
7367       }
7368       i = CommandItem (sub, "Multiple Sequences", TestUpdateSequenceSetIndexer);
7369       SetObjectExtra (i, bfp, NULL);
7370       
7371       /* public version */
7372       sub = SubMenu (m, "Public Update Sequence");
7373       i = CommandItem (sub, "Single Sequence", TestUpdateSequenceSubmitter);
7374       SetObjectExtra (i, bfp, NULL);
7375       if (useEntrez) {
7376         i = CommandItem (sub, "Download Accession", UpdateSequenceViaDownloadSubmitter);
7377         SetObjectExtra (i, bfp, NULL);    
7378       }
7379       i = CommandItem (sub, "Multiple Sequences", TestUpdateSequenceSetSubmitter);
7380       SetObjectExtra (i, bfp, NULL);
7381       
7382       SeparatorItem (m);
7383     }
7384     else
7385     {
7386       sub = SubMenu (m, "Update Sequence");
7387       SetFormMenuItem (bfp, mssgupd, (IteM) sub);
7388       i = CommandItem (sub, "Single Sequence", TestUpdateSequenceSubmitter);
7389       SetObjectExtra (i, bfp, NULL);
7390       if (useEntrez) {
7391         i = CommandItem (sub, "Download Accession", UpdateSequenceViaDownloadSubmitter);
7392         SetObjectExtra (i, bfp, NULL);    
7393       }
7394       i = CommandItem (sub, "Multiple Sequences", TestUpdateSequenceSetSubmitter);
7395       SetObjectExtra (i, bfp, NULL);
7396     }
7397     
7398     sub = SubMenu (m, "Extend Sequence");
7399     SetFormMenuItem (bfp, mssgext, (IteM) sub);
7400     i = CommandItem (sub, "Read FASTA File...", ExtendSeqWithFASTA);
7401     SetObjectExtra (i, bfp, NULL);
7402     i = CommandItem (sub, "Read Sequence Record...", ExtendSeqWithRec);
7403     SetObjectExtra (i, bfp, NULL);
7404     i = CommandItem (sub, "Read FASTA or ASN.1 Set", ExtendFastaSet);
7405     SetObjectExtra (i, bfp, NULL);
7406     if (useEntrez) {
7407       i = CommandItem (sub, "Download Accession...", ExtendSeqWithAcc);
7408       SetObjectExtra (i, bfp, NULL);
7409     }
7410             
7411     SeparatorItem (m);
7412     i = CommandItem (m, "Feature Propagate...", NewFeaturePropagate);
7413     SetObjectExtra (i, bfp, NULL);
7414     SetFormMenuItem (bfp, mssgfeatprop, i);
7415     SeparatorItem (m);
7416     sub = SubMenu (m, "Add Sequence");
7417     SetFormMenuItem (bfp, mssgadd, (IteM) sub);
7418     i = CommandItem (sub, "Add FASTA File...", AddSeqWithFASTA);
7419     SetObjectExtra (i, bfp, NULL);
7420     i = CommandItem (sub, "Add Sequence Record...", AddSeqWithRec);
7421     SetObjectExtra (i, bfp, NULL);
7422     if (! extraServices) {
7423       SeparatorItem (m);
7424       i = CommandItem (m, "Parse File to Source", ParseFileToSource);
7425       SetObjectExtra (i, bfp, NULL);
7426     }
7427 
7428     m = PulldownMenu (w, "Search/ R");
7429     i = CommandItem (m, "Find ASN.1.../ F", FindStringProc);
7430     SetObjectExtra (i, bfp, NULL);
7431     i = CommandItem (m, "Find FlatFile.../ G", FindFlatfileProc);
7432     SetObjectExtra (i, bfp, NULL);
7433     SeparatorItem (m);
7434     i = CommandItem (m, "Find by Gene...", FindGeneProc);
7435     SetObjectExtra (i, bfp, NULL);
7436     i = CommandItem (m, "Find by Protein...", FindProtProc);
7437     SetObjectExtra (i, bfp, NULL);
7438     i = CommandItem (m, "Find by Position...", FindPosProc);
7439     SetObjectExtra (i, bfp, NULL);
7440     SeparatorItem (m);
7441     if (indexerVersion) {
7442       sub = SubMenu (m, "Validate/ V");
7443       i = CommandItem (sub, "Validate Record/ R", ValSeqEntryProc);
7444       SetObjectExtra (i, bfp, NULL);
7445       i = CommandItem (sub, "Validate no Alignments/ A", ValSeqEntryProcNoAln);
7446       SetObjectExtra (i, bfp, NULL);
7447       i = CommandItem (sub, "Validate check Inference", ValSeqEntryProcInfAccn);
7448       SetObjectExtra (i, bfp, NULL);
7449       SeparatorItem (sub);
7450       i = CommandItem (sub, "Validate Inst", ValSeqEntryProcInst);
7451       SetObjectExtra (i, bfp, NULL);
7452       i = CommandItem (sub, "Validate Hist", ValSeqEntryProcHist);
7453       SetObjectExtra (i, bfp, NULL);
7454       i = CommandItem (sub, "Validate Context", ValSeqEntryProcContext);
7455       SetObjectExtra (i, bfp, NULL);
7456       i = CommandItem (sub, "Validate Graph", ValSeqEntryProcGraph);
7457       SetObjectExtra (i, bfp, NULL);
7458       i = CommandItem (sub, "Validate Set", ValSeqEntryProcSet);
7459       SetObjectExtra (i, bfp, NULL);
7460       i = CommandItem (sub, "Validate Feat", ValSeqEntryProcFeat);
7461       SetObjectExtra (i, bfp, NULL);
7462       i = CommandItem (sub, "Validate Desc", ValSeqEntryProcDesc);
7463       SetObjectExtra (i, bfp, NULL);
7464     } else {
7465       i = CommandItem (m, "Validate/ V", ValSeqEntryProc);
7466       SetObjectExtra (i, bfp, NULL);
7467     }
7468 #ifdef USE_SPELL
7469     SeparatorItem (m);
7470     i = CommandItem (m, "Spell Check...", SpellCheckSeqEntryProc);
7471     SetObjectExtra (i, bfp, NULL);
7472 #endif
7473 /*#ifdef USE_BLAST*/
7474     if (useBlast) {
7475       SeparatorItem (m);
7476       if (indexerVersion) {
7477         i = CommandItem (m, "CDD BLAST...", SimpleCDDBlastProc);
7478         SetObjectExtra (i, bfp, NULL);
7479       }
7480       if (extraServices) {
7481         sub = SubMenu (m, "CDD Search");
7482         i = CommandItem (sub, "Features", SimpleCDDSearchFeatProc);
7483         SetObjectExtra (i, bfp, NULL);
7484         i = CommandItem (sub, "Alignments", SimpleCDDSearchAlignProc);
7485         SetObjectExtra (i, bfp, NULL);
7486       } else {
7487         i = CommandItem (m, "CDD Search", SimpleCDDSearchFeatProc);
7488         SetObjectExtra (i, bfp, NULL);
7489       }
7490     }
7491 /*#endif*/
7492     SeparatorItem (m);
7493     sub = SubMenu (m, "Vector Screen");
7494     i = CommandItem (sub, "UniVec", SimpleUniVecScreenProc);
7495     SetObjectExtra (i, bfp, NULL);
7496     i = CommandItem (sub, "UniVec Core", SimpleUniVecCoreScreenProc);
7497     SetObjectExtra (i, bfp, NULL);
7498     SeparatorItem (m);
7499     i = CommandItem (m, "ORF Finder...", FindOrf);
7500     SetObjectExtra (i, bfp, NULL);
7501     /*
7502     i = CommandItem (m, "Repeat Finder...", FindAlu);
7503     SetObjectExtra (i, bfp, NULL);
7504     */
7505     SeparatorItem (m);
7506     i = CommandItem (m, "Select Target...", DoChangeTarget);
7507     SetObjectExtra (i, bfp, NULL);
7508 
7509     /*
7510     if (! indexerVersion) {
7511       m = PulldownMenu (w, "Options");
7512       sub = SubMenu (m, "Font Selection");
7513       i = CommandItem (sub, "Display Font...", DisplayFontChangeProc);
7514       SetObjectExtra (i, bfp, NULL);
7515       SeparatorItem (m);
7516       CreateLegendItem (m, bfp);
7517     }
7518     */
7519 
7520 /*#ifdef EXTRA_SERVICES*/
7521     if (extraServices) {
7522       m = PulldownMenu (w, "Special/ S");
7523       SetupSpecialMenu (m, bfp);
7524       m = PulldownMenu (w, "Projects");
7525       MakeSpecialProjectsMenu (m, bfp);
7526     }
7527 /*#endif*/
7528 
7529     m = PulldownMenu (w, "Misc");
7530     /*
7531     CommandItem (m, "Style Manager...", StyleManagerProc);
7532     SeparatorItem (m);
7533     */
7534     CommandItem (m, "Net Configure...", NetConfigureProc);
7535     if (useEntrez) {
7536       /*
7537       SeparatorItem (m);
7538       CommandItem (m, "Entrez2 Query...", Entrez2QueryProc);
7539       */
7540 /*
7541 #ifndef WIN16
7542       if (BiostrucAvail ()) {
7543         SeparatorItem (m);
7544         CommandItem (m, "Cn3D Window...", Cn3DWinShowProc);
7545       }
7546 #endif
7547 */
7548     }
7549     if (useDesktop) {
7550       SeparatorItem (m);
7551       VSMAddToMenu (m, VSM_DESKTOP);
7552     }
7553 
7554     CreateAnalysisMenu (w, bfp, TRUE, FALSE);
7555 
7556     m = PulldownMenu (w, "Annotate/ A");
7557     SetupNewFeaturesMenu (m, bfp);
7558     SeparatorItem (m);
7559     sub = SubMenu (m, "Batch Feature Apply");
7560     SetupBatchApplyMenu (sub, bfp);
7561     sub = SubMenu (m, "Batch Feature Edit");
7562     SetupBatchEditMenu (sub, bfp);
7563     SeparatorItem (m);
7564     sub = SubMenu (m, "Publications");
7565     SetupNewPublicationsMenu (sub, bfp);
7566     SeparatorItem (m);
7567     sub = SubMenu (m, "Descriptors");
7568     SetupNewDescriptorsMenu (sub, bfp);
7569     SeparatorItem (m);
7570     i = CommandItem (m, "Generate Definition Line", AutoDef);
7571     SetObjectExtra (i, bfp, NULL);
7572     sub = SubMenu (m, "Advanced Table Readers");
7573     i = CommandItem (sub, "Load Structured Comments from Table", SubmitterCreateStructuredComments);
7574     SetObjectExtra (i, bfp, NULL);
7575     i = CommandItem (m, "Sort Unique Count By Group", SUCSubmitterProc);
7576     SetObjectExtra (i, bfp, NULL);
7577 
7578     if (indexerVersion) {
7579       m = PulldownMenu (w, "Options");
7580       sub = SubMenu (m, "Font Selection");
7581       i = CommandItem (sub, "Display Font...", DisplayFontChangeProc);
7582       SetObjectExtra (i, bfp, NULL);
7583       /*
7584       SeparatorItem (m);
7585       CreateLegendItem (m, bfp);
7586       */
7587       SeparatorItem (m);
7588       sub = SubMenu (m, "Layout Override");
7589       CreateNewLayoutMenu (sub, bfp);
7590     }
7591   }
7592 }
7593 #endif
7594 
7595 static void GetRidCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
7596 
7597 {
7598   BioseqPtr     bsp;
7599   BioseqSetPtr  bssp;
7600   SeqAnnotPtr   nextsap;
7601   Pointer PNTR  prevsap;
7602   SeqAnnotPtr   sap;
7603 
7604   if (sep == NULL || sep->data.ptrvalue == NULL) return;
7605   if (IS_Bioseq (sep)) {
7606     bsp = (BioseqPtr) sep->data.ptrvalue;
7607     sap = bsp->annot;
7608     prevsap = (Pointer PNTR) &(bsp->annot);
7609   } else if (IS_Bioseq_set (sep)) {
7610     bssp = (BioseqSetPtr) sep->data.ptrvalue;
7611     sap = bssp->annot;
7612     prevsap = (Pointer PNTR) &(bssp->annot);
7613   } else return;
7614   while (sap != NULL) {
7615     nextsap = sap->next;
7616     if (sap->data == NULL) {
7617       *(prevsap) = sap->next;
7618       sap->next = NULL;
7619       SeqAnnotFree (sap);
7620     } else {
7621       prevsap = (Pointer PNTR) &(sap->next);
7622     }
7623     sap = nextsap;
7624   }
7625 }
7626 
7627 static void GetRidOfEmptyAnnotTables (Uint2 entityID)
7628 
7629 {
7630   SeqEntryPtr  sep;
7631 
7632   if (entityID < 1) return;
7633   sep = GetTopSeqEntryForEntityID (entityID);
7634   if (sep == NULL) return;
7635   SeqEntryExplore (sep, NULL, GetRidCallback);
7636 }
7637 
7638 static CharPtr deleteProtMsg =
7639 "The protein product of a CDS (shown in the /translation qualifier)\n\
7640 is actually a separate data element in the record.  Unless explicitly\n\
7641 deleted, it will remain hidden in the record after you delete the CDS.";
7642 
7643 static CharPtr deleteGeneMsg =
7644 "The /gene qualifier is generated from an overlapping gene feature.\n\
7645 If you delete a CDS you may also want to delete this separate gene.";
7646 
7647 static CharPtr deleteCdnaMsg =
7648 "The cDNA product of an mRNA is actually a separate data element\n\
7649 in the record.  Unless explicitly deleted, it will remain hidden\n\
7650 in the record after you delete the mRNA.";
7651 
7652 typedef struct deletecdsoptions {
7653   Boolean delete_feature;
7654   Boolean delete_gene;
7655   Boolean delete_cdna;
7656   Boolean delete_protein;
7657 } DeleteCDSOptionsData, PNTR DeleteCDSOptionsPtr;
7658 
7659 static void GetDeleteCDSOptions (DeleteCDSOptionsPtr dcop)
7660 {
7661   WindoW w;
7662   GrouP  h, g, c;
7663   ButtoN b;
7664   ModalAcceptCancelData acd;
7665   ButtoN delete_gene = NULL;
7666   ButtoN delete_cdna = NULL;
7667   ButtoN delete_protein = NULL;
7668   
7669   if (dcop == NULL) return;
7670   if (!dcop->delete_gene
7671       && !dcop->delete_cdna
7672       && !dcop->delete_protein) {
7673     return;
7674   }
7675   
7676   acd.accepted = FALSE;
7677   acd.cancelled = FALSE;
7678   
7679   w = ModalWindow(-20, -13, -10, -10, NULL);
7680   h = HiddenGroup (w, -1, 0, NULL);
7681   SetGroupSpacing (h, 10, 10);
7682 
7683   g = HiddenGroup (h, 2, 0, NULL);
7684   SetGroupSpacing (g, 10, 10);
7685   if (dcop->delete_gene) {
7686     delete_gene = CheckBox (g, "Delete overlapping gene", NULL);
7687     MultiLinePrompt (g, deleteGeneMsg, 30 * stdCharWidth, systemFont);
7688   }
7689   
7690   if (dcop->delete_cdna) {
7691     delete_cdna = CheckBox (g, "Delete cDNA", NULL);
7692     SetStatus (delete_cdna, TRUE);
7693     MultiLinePrompt (g, deleteCdnaMsg, 30 * stdCharWidth, systemFont);
7694   }
7695 
7696   if (dcop->delete_protein) {
7697     delete_protein = CheckBox (g, "Delete protein product", NULL);
7698     SetStatus (delete_protein, TRUE);
7699     MultiLinePrompt (g, deleteProtMsg, 30 * stdCharWidth, systemFont);
7700   }
7701 
7702   c = HiddenGroup (h, 3, 0, NULL);
7703   SetGroupSpacing (c, 10, 10);
7704   b = PushButton (c, "Accept", ModalAcceptButton);
7705   SetObjectExtra (b, &acd, NULL);
7706   b = PushButton (c, "Cancel", ModalCancelButton);
7707   SetObjectExtra (b, &acd, NULL);
7708   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
7709   
7710   Show(w); 
7711   Select (w);
7712   while (!acd.accepted && ! acd.cancelled)
7713   {
7714     ProcessExternalEvent ();
7715     Update ();
7716   }
7717   ProcessAnEvent ();
7718   Remove (w);
7719   if (acd.accepted)
7720   {
7721     dcop->delete_feature = TRUE;
7722     dcop->delete_gene = delete_gene == NULL ? FALSE : GetStatus (delete_gene);
7723     dcop->delete_cdna = delete_cdna == NULL ? FALSE : GetStatus (delete_cdna);
7724     dcop->delete_protein = delete_protein == NULL ? FALSE : GetStatus (delete_protein);
7725   }
7726   else
7727   {
7728     dcop->delete_feature = FALSE;
7729     dcop->delete_gene = FALSE;
7730     dcop->delete_cdna = FALSE;
7731     dcop->delete_protein = FALSE;
7732   }
7733 }
7734 
7735 static Boolean DeleteSelectedFeatureOrDescriptor (GatherContextPtr gcp)
7736 
7737 {
7738   BioseqPtr       bsp;
7739   BioseqPtr       cdna;
7740   Uint2           entityID;
7741   SeqFeatPtr      gene;
7742   Uint4           itemID;
7743   Uint2           itemtype;
7744   BioseqSetPtr    nps;
7745   BioseqSetPtr    parent;
7746   SeqFeatPtr      sfp;
7747   SeqIdPtr        sip;
7748   DeleteCDSOptionsData dcod;
7749   SeqMgrFeatContext    fcontext;
7750   ObjValNodePtr        ovn;
7751   SeqDescrPtr          sdp;
7752 #ifdef USE_SMARTNET
7753   UserObjectPtr   uop;
7754 #endif
7755 
7756   if (gcp->thistype != OBJ_SEQDESC && gcp->thistype != OBJ_SEQFEAT) {
7757     /* This function should only handle descriptors and features */
7758     return FALSE;
7759   } else if (gcp->thisitem == NULL) {
7760     return TRUE;
7761   }
7762 
7763 #ifdef USE_SMARTNET
7764   /* This code will prevent from deletion SMART User Object */
7765 
7766   if(gcp->thistype == OBJ_SEQDESC) {
7767       if((sdp = (SeqDescrPtr) gcp->thisitem) != NULL) {
7768           if(sdp->choice == 14 &&
7769              ((uop = ( UserObjectPtr) sdp->data.ptrvalue) != NULL)) {
7770               if(!StringCmp(uop->_class, SMART_OBJECT_LABEL)) {
7771                   Message(MSG_ERROR, "You may not delete SMART Object Label");
7772                   return TRUE;
7773               }
7774           }
7775       }
7776   }
7777 #endif
7778 
7779   /* delete the descriptor */
7780   if (gcp->thistype == OBJ_SEQDESC) {
7781     sdp = (SeqDescrPtr) gcp->thisitem;
7782     if (sdp != NULL && sdp->extended != 0) {
7783       ovn = (ObjValNodePtr) sdp;
7784       ovn->idx.deleteme = TRUE;
7785       return TRUE;
7786     } else {
7787       return FALSE;
7788     }
7789   }
7790 
7791   /* because it wasn't a descriptor, this must be a feature */
7792   sfp = (SeqFeatPtr) gcp->thisitem;
7793   bsp = NULL;
7794   gene = NULL;
7795   cdna = NULL;
7796   nps = NULL;
7797   entityID = gcp->entityID;
7798   itemID = gcp->itemID;
7799   itemtype = gcp->thistype;
7800 
7801   /* When deleting some features, there are other objects that the user may wish to
7802    * remove at the same time.
7803    * When removing a coding region, the user may wish to also do the following:
7804    *   1) Remove the overlapping gene
7805    *   2) Remove the product protein
7806    * When removing an mRNA, the user may wish to also do the following:
7807    *   1) Remove the cDNA product
7808    *   2) Remove the nucprotset parent
7809    */
7810   if (sfp->idx.subtype == FEATDEF_mRNA && sfp->product != NULL) {
7811     sip = SeqLocId (sfp->product);
7812     if (sip != NULL) {
7813       cdna = BioseqFind (sip);
7814       if (cdna != NULL) {
7815         if (cdna->idx.parenttype == OBJ_BIOSEQSET) {
7816           parent = (BioseqSetPtr) cdna->idx.parentptr;
7817           while (parent != NULL) {
7818             if (parent->_class == BioseqseqSet_class_nuc_prot) {
7819               nps = parent;
7820             }
7821             if (parent->idx.parenttype == OBJ_BIOSEQSET) {
7822               parent = (BioseqSetPtr) parent->idx.parentptr;
7823             } else {
7824               parent = NULL;
7825             }
7826           }
7827         }
7828       }
7829     }
7830   } else if (sfp->idx.subtype == FEATDEF_CDS) {
7831     if (sfp->product != NULL) {
7832       sip = SeqLocId (sfp->product);
7833       if (sip != NULL) {
7834         bsp = BioseqFind (sip);
7835       }
7836     }
7837     if (SeqMgrGetGeneXref(sfp) == NULL) {
7838       gene = SeqMgrGetOverlappingGene (sfp->location, &fcontext);
7839     }
7840   }
7841 
7842   MemSet (&dcod, 0, sizeof (dcod));
7843   if (sfp != NULL) {
7844     dcod.delete_feature = TRUE;
7845   }
7846   if (nps != NULL || cdna != NULL) {
7847     dcod.delete_cdna = TRUE;
7848   }
7849   if (bsp != NULL) {
7850     dcod.delete_protein = TRUE;
7851   }
7852 
7853   if (gene != NULL) {
7854     dcod.delete_gene = TRUE;
7855   }
7856 
7857   GetDeleteCDSOptions (&dcod);
7858   if (!dcod.delete_feature) {
7859     return TRUE;
7860   }
7861 
7862 
7863   /* delete the feature */
7864   sfp->idx.deleteme = TRUE;
7865 
7866   /* delete cdna product */
7867   if (dcod.delete_cdna) {
7868     if (nps != NULL) {
7869       nps->idx.deleteme = TRUE;
7870     } else if (cdna != NULL) {
7871       cdna->idx.deleteme = TRUE;
7872     }
7873   }
7874 
7875   /* delete protein product */
7876   if (bsp != NULL && dcod.delete_protein) {
7877     bsp->idx.deleteme = TRUE;
7878   }
7879 
7880   /* delete overlapping gene */
7881   if (gene != NULL && dcod.delete_gene) {
7882     gene->idx.deleteme = TRUE;
7883   }
7884 
7885   /* Note - delete marked objects is called by the calling function */
7886 
7887   return TRUE;
7888 }
7889 
7890 static void TermSelectionFormMessage (ForM f, Int2 mssg)
7891 
7892 {
7893   BaseFormPtr  bfp;
7894 
7895   bfp = (BaseFormPtr) GetObjectExtra (f);
7896   if (bfp != NULL) {
7897     switch (mssg) {
7898       case VIB_MSG_CLOSE :
7899         Hide (f);
7900         break;
7901       case VIB_MSG_QUIT :
7902         QuitProc ();
7903         break;
7904       default :
7905         break;
7906     }
7907   }
7908 }
7909 
7910 static void DocumentSummaryFormMessage (ForM f, Int2 mssg)
7911 
7912 {
7913   BaseFormPtr  bfp;
7914 
7915   bfp = (BaseFormPtr) GetObjectExtra (f);
7916   if (bfp != NULL) {
7917     switch (mssg) {
7918       case VIB_MSG_CHANGE :
7919         EnableAnalysisItems (bfp, TRUE);
7920         break;
7921       case VIB_MSG_CLOSE :
7922         Hide (f);
7923         break;
7924       case VIB_MSG_QUIT :
7925         QuitProc ();
7926         break;
7927       default :
7928         break;
7929     }
7930   }
7931 }
7932 
7933 static void SequinMedlineFormMessage (ForM f, Int2 mssg)
7934 
7935 {
7936   BaseFormPtr  bfp;
7937 
7938   bfp = (BaseFormPtr) GetObjectExtra (f);
7939   if (bfp != NULL) {
7940     switch (mssg) {
7941       case VIB_MSG_CLOSE :
7942         Remove (f);
7943         break;
7944       case VIB_MSG_QUIT :
7945         QuitProc ();
7946         break;
7947       default :
7948         break;
7949     }
7950   }
7951 }
7952 
7953 typedef struct seltbl {
7954   size_t             count;
7955   SelStructPtr PNTR  selarray;
7956   Boolean            geneasked;
7957   Boolean            productasked;
7958   Boolean            removegene;
7959   Boolean            removeproduct;
7960 } SelTbl, PNTR SelTblPtr;
7961 
7962 static Boolean MarkSelectedItem (GatherObjectPtr gop)
7963 
7964 {
7965   Int2           L, R, mid;
7966   SelStructPtr   ssp;
7967   SelTblPtr      tbl;
7968   MsgAnswer      ans;
7969   BioseqPtr      bsp;
7970   ObjValNodePtr  ovn;
7971   SeqAlignPtr    sap;
7972   SeqDescrPtr    sdp;
7973   SeqFeatPtr     sfp, gene;
7974   SeqGraphPtr    sgp;
7975 
7976   if (gop == NULL) return TRUE;
7977   tbl = (SelTblPtr) gop->userdata;
7978   if (tbl == NULL) return TRUE;
7979 
7980   L = 0;
7981   R = tbl->count - 1;
7982   while (L <= R) {
7983     mid = (L + R) / 2;
7984     ssp = tbl->selarray [mid];
7985     if (ssp == NULL) return TRUE;
7986     if (ssp->entityID > gop->entityID) {
7987       R = mid - 1;
7988     } else if (ssp->entityID < gop->entityID) {
7989       L = mid + 1;
7990     } else if (ssp->itemtype > gop->itemtype) {
7991       R = mid - 1;
7992     } else if (ssp->itemtype < gop->itemtype) {
7993       L = mid + 1;
7994     } else if (ssp->itemID > gop->itemID) {
7995       R = mid - 1;
7996     } else if (ssp->itemID < gop->itemID) {
7997       L = mid + 1;
7998     } else if (gop->dataptr != NULL &&
7999                ssp->entityID == gop->entityID &&
8000                ssp->itemtype == gop->itemtype &&
8001                ssp->itemID == gop->itemID) {
8002       switch (gop->itemtype) {
8003         case OBJ_SEQDESC :
8004           sdp = (SeqDescrPtr) gop->dataptr;
8005           if (sdp != NULL && sdp->extended != 0) {
8006             ovn = (ObjValNodePtr) sdp;
8007             ovn->idx.deleteme = TRUE;
8008           }
8009           break;
8010         case OBJ_SEQFEAT :
8011           sfp = (SeqFeatPtr) gop->dataptr;
8012           if (sfp != NULL) {
8013             sfp->idx.deleteme = TRUE;
8014             if (SeqMgrGetGeneXref (sfp) == NULL) {
8015               gene = SeqMgrGetOverlappingGene (sfp->location, NULL);
8016               if (gene != NULL) {
8017                 if (! tbl->geneasked) {
8018                   ans = Message (MSG_YN, "Remove overlapping gene?");
8019                   if (ans == ANS_YES) {
8020                     tbl->removegene = TRUE;
8021                   }
8022                   tbl->geneasked = TRUE;
8023                 }
8024                 if (tbl->removegene) {
8025                   gene->idx.deleteme = TRUE;
8026                 }
8027               }
8028             }
8029             if (sfp->data.choice == SEQFEAT_CDREGION) {
8030               bsp = BioseqFind (SeqLocId (sfp->product));
8031               if (bsp != NULL) {
8032                 if (! tbl->productasked) {
8033                   ans = Message (MSG_YN, "Remove protein products?");
8034                   if (ans == ANS_YES) {
8035                     tbl->removeproduct = TRUE;
8036                   }
8037                   tbl->productasked = TRUE;
8038                 }
8039                 if (tbl->removeproduct) {
8040                   bsp->idx.deleteme = TRUE;
8041                 }
8042               }
8043             }
8044           }
8045           break;
8046         case OBJ_SEQALIGN :
8047           sap = (SeqAlignPtr) gop->dataptr;
8048           if (sap != NULL) {
8049             sap->idx.deleteme = TRUE;
8050           }
8051           break;
8052         case OBJ_SEQGRAPH :
8053           sgp = (SeqGraphPtr) gop->dataptr;
8054           if (sgp != NULL) {
8055             sgp->idx.deleteme = TRUE;
8056           }
8057           break;
8058         default :
8059           break;
8060       }
8061       return TRUE;
8062     }
8063   }
8064 
8065   return TRUE;
8066 }
8067 
8068 static int LIBCALLBACK SortSelStructByIDs (VoidPtr ptr1, VoidPtr ptr2)
8069 
8070 {
8071   SelStructPtr  ssp1, ssp2;
8072 
8073   if (ptr1 == NULL || ptr2 == NULL) return 0;
8074   ssp1 = *((SelStructPtr PNTR) ptr1);
8075   ssp2 = *((SelStructPtr PNTR) ptr2);
8076   if (ssp1 == NULL || ssp2 == NULL) return 0;
8077 
8078   if (ssp1->entityID > ssp2->entityID) return 1;
8079   if (ssp1->entityID < ssp2->entityID) return -1;
8080 
8081   if (ssp1->itemtype > ssp2->itemtype) return 1;
8082   if (ssp1->itemtype < ssp2->itemtype) return -1;
8083 
8084   if (ssp1->itemID > ssp2->itemID) return 1;
8085   if (ssp1->itemID < ssp2->itemID) return -1;
8086 
8087   return 0;
8088 }
8089 
8090 static void DeleteMultipleSelections (Uint2 entityID, SelStructPtr selhead)
8091 
8092 {
8093   size_t             count;
8094   SelStructPtr       sel;
8095   SelStructPtr PNTR  selarray;
8096   SelTbl             tbl;
8097 
8098   if (entityID < 1 || selhead == NULL) return;
8099 
8100   for (count = 0, sel = selhead; sel != NULL; sel = sel->next, count++) continue;
8101   if (count < 1) return;
8102 
8103   selarray = (SelStructPtr PNTR) MemNew (sizeof (SelStructPtr) * (size_t) (count + 1));
8104   if (selarray == NULL) return;
8105   for (count = 0, sel = selhead; sel != NULL; sel = sel->next, count++) {
8106     selarray [count] = sel;
8107   }
8108 
8109   HeapSort (selarray, (size_t) count, sizeof (SelStructPtr), SortSelStructByIDs);
8110 
8111   MemSet ((Pointer) &tbl, 0, sizeof (tbl));
8112   tbl.count = count;
8113   tbl.selarray = selarray;
8114 
8115   GatherObjectsInEntity (entityID, 0, NULL, MarkSelectedItem, (Pointer) &tbl, NULL);
8116 
8117   MemFree (selarray);
8118   DeleteMarkedObjects (entityID, 0, NULL);
8119 }
8120 
8121 extern void SequinSeqViewFormMessage (ForM f, Int2 mssg)
8122 
8123 {
8124   MsgAnswer     ans;
8125   BaseFormPtr   bfp;
8126   BioseqPtr     bsp;
8127   Uint4         entityID;
8128   Uint4         itemID;
8129   Int2          mssgalign;
8130   Int2          mssgdup;
8131   Int2          mssgseq;
8132   Int2          mssgsub;
8133   SeqEntryPtr   oldsep;
8134   OMProcControl  ompc;
8135 /******** COLOMBE
8136   SeqAlignPtr   salp; ********COLOMBE END*/
8137   SeqAnnotPtr   sap;
8138   SelStructPtr  sel;
8139   SeqEntryPtr   sep;
8140   SeqIdPtr      sip;
8141 
8142   bfp = (BaseFormPtr) GetObjectExtra (f);
8143   if (bfp != NULL) {
8144     switch (mssg) {
8145       case VIB_MSG_SAVE :
8146         if (FixSpecialCharacters (bfp->input_entityID))
8147         {
8148           SaveSeqSubmitProc (bfp, FALSE);
8149         }
8150         break;
8151       case VIB_MSG_SAVE_AS :
8152         if (FixSpecialCharacters (bfp->input_entityID))
8153         {
8154           SaveSeqSubmitProc (bfp, TRUE);
8155         }
8156         break;
8157       case VIB_MSG_CLOSE :
8158         CloseProc (bfp);
8159         break;
8160       case VIB_MSG_QUIT :
8161         QuitProc ();
8162         break;
8163       case VIB_MSG_ACCEPT :
8164         ProcessDoneButton (f);
8165         break;
8166       case VIB_MSG_RESET :
8167 #ifdef USE_SMARTNET
8168         SmartResetProc ((IteM)f);
8169 #endif
8170         break;
8171       case VIB_MSG_IMPORT :
8172         /* ReadFastaProc (); */
8173         break;
8174       case VIB_MSG_CUT :
8175         break;
8176       case VIB_MSG_COPY :
8177         break;
8178       case VIB_MSG_UNDO :
8179         if (subtoolMode || smartnetMode || backupMode) {
8180           if (FileLength (SEQUIN_EDIT_PREV_FILE) > 0) {
8181             sep = GetTopSeqEntryForEntityID (subtoolEntityID);
8182             if (Message (MSG_YN, "Restore from backup?") == ANS_YES) {
8183               oldsep = RestoreFromFile (SEQUIN_EDIT_PREV_FILE);
8184               ReplaceSeqEntryWithSeqEntry (sep, oldsep, TRUE);
8185               subtoolEntityID = ObjMgrGetEntityIDForChoice (sep);
8186               ObjMgrSetDirtyFlag (subtoolEntityID, TRUE);
8187               ObjMgrSendMsg (OM_MSG_UPDATE, subtoolEntityID, 0, 0);
8188             }
8189           }
8190         }
8191         break;
8192       case VIB_MSG_PASTE :
8193         break;
8194       case VIB_MSG_DELETE :
8195         sel = ObjMgrGetSelected ();
8196         if (sel != NULL) {
8197           if (sel->itemtype == OBJ_BIOSEQ && sel->next == NULL) {
8198             if (! indexerVersion) {
8199               ans = Message (MSG_OKC, "Are you sure you want to delete this Bioseq?");
8200               if (ans == ANS_CANCEL) return;
8201               ans = Message (MSG_OKC, "Are you REALLY sure you want to delete this Bioseq?");
8202               if (ans == ANS_CANCEL) return;
8203             }
8204             bsp = GetBioseqGivenIDs (sel->entityID, sel->itemID, sel->itemtype);
8205             sip = SeqIdDup (bsp->id);
8206             entityID = sel->entityID;
8207             MemSet ((Pointer) (&ompc), 0, sizeof (OMProcControl));
8208             ompc.do_not_reload_from_cache = TRUE;
8209             ompc.input_entityID = sel->entityID;
8210             ompc.input_itemID = sel->itemID;
8211             ompc.input_itemtype = sel->itemtype;
8212             if (! DetachDataForProc (&ompc, FALSE)) {
8213               Message (MSG_ERROR, "DetachDataForProc failed");
8214             }
8215             sep = GetTopSeqEntryForEntityID (entityID);
8216             SeqAlignBioseqDeleteByIdFromSeqEntry (sep, sip);
8217             SeqIdFree (sip);
8218             /* see VSeqMgrDeleteProc - probably leaving one dangling SeqEntry */
8219             BioseqFree (bsp);
8220             ObjMgrSetDirtyFlag (entityID, TRUE);
8221             ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
8222             ObjMgrDeSelect (0, 0, 0, 0, NULL);
8223             Update ();
8224           }
8225           if (sel->itemtype == OBJ_SEQANNOT && sel->next == NULL && extraServices) {
8226             entityID = sel->entityID;
8227             MemSet ((Pointer) (&ompc), 0, sizeof (OMProcControl));
8228             ompc.do_not_reload_from_cache = TRUE;
8229             ompc.input_entityID = sel->entityID;
8230             ompc.input_itemID = sel->itemID;
8231             ompc.input_itemtype = sel->itemtype;
8232             if (! DetachDataForProc (&ompc, FALSE)) {
8233               Message (MSG_ERROR, "DetachDataForProc failed");
8234             }
8235             ObjMgrSetDirtyFlag (entityID, TRUE);
8236             ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
8237             ObjMgrDeSelect (0, 0, 0, 0, NULL);
8238             Update ();
8239           }
8240           if (sel->next == NULL && (sel->itemtype == OBJ_SEQDESC || sel->itemtype == OBJ_SEQFEAT)) {
8241             entityID = sel->entityID;
8242             GatherItem (sel->entityID, sel->itemID, sel->itemtype,
8243                         NULL, DeleteSelectedFeatureOrDescriptor);
8244             DeleteMarkedObjects (entityID, 0, NULL);
8245             GetRidOfEmptyAnnotTables (entityID);
8246             sep = GetTopSeqEntryForEntityID (entityID);
8247             RenormalizeNucProtSets (sep, TRUE);
8248             ObjMgrSetDirtyFlag (entityID, TRUE);
8249             ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
8250             ObjMgrDeSelect (0, 0, 0, 0, NULL);
8251             Update ();
8252           } else {
8253             /* Message (MSG_OK, "Unable to delete multiple objects"); */
8254             ans = Message (MSG_YN, "Are you sure you want to delete multiple objects?");
8255             if (ans == ANS_NO) return;
8256             entityID = bfp->input_entityID;
8257             DeleteMultipleSelections (entityID, sel);
8258             GetRidOfEmptyAnnotTables (entityID);
8259             sep = GetTopSeqEntryForEntityID (entityID);
8260             RenormalizeNucProtSets (sep, TRUE);
8261             ObjMgrSetDirtyFlag (entityID, TRUE);
8262             ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
8263             ObjMgrDeSelect (0, 0, 0, 0, NULL);
8264           }
8265         } else {
8266           Message (MSG_OK, "Nothing selected");
8267         }
8268         break;
8269       case VIB_MSG_CHANGE :
8270         EnableFeaturesPerTarget (bfp);
8271         EnableAnalysisItems (bfp, FALSE);
8272         EnableEditSeqAlignAndSubItems (bfp);
8273         break;
8274       case VIB_MSG_SELECT :
8275         EnableEditAlignItem (bfp);
8276         break;
8277       default :
8278         mssgseq = RegisterFormMenuItemName ("SequinEditSequenceItem");
8279         mssgalign = RegisterFormMenuItemName ("SequinEditAlignmentItem");
8280         mssgsub = RegisterFormMenuItemName ("SequinEditSubmitterItem");
8281         mssgdup = RegisterFormMenuItemName ("SequinDuplicateItem");
8282         if (mssg == mssgseq) {
8283           bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
8284           if (bsp != NULL) {
8285             WatchCursor ();
8286             Update ();
8287             SeqEntrySetScope (NULL);
8288             GatherProcLaunch (OMPROC_EDIT, FALSE, bfp->input_entityID, bfp->input_itemID,
8289                               bfp->input_itemtype, 0, 0, bfp->input_itemtype, 0);
8290             ArrowCursor ();
8291             Update ();
8292           }
8293         } else if (mssg == mssgalign) {
8294           sel = ObjMgrGetSelected ();
8295           if (sel != NULL &&
8296               (sel->itemtype == OBJ_SEQALIGN || sel->itemtype == OBJ_SEQHIST_ALIGN)) {
8297             WatchCursor ();
8298             Update ();
8299             SeqEntrySetScope (NULL);
8300             GatherProcLaunch (OMPROC_EDIT, FALSE, sel->entityID, sel->itemID,
8301                               sel->itemtype, 0, 0, sel->itemtype, 0);
8302             ArrowCursor ();
8303             Update ();
8304           } else /* if (sel == NULL) */ {
8305             sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8306 /******** COLOMBE
8307             salp = FindSeqAlignInSeqEntry (sep, OBJ_SEQALIGN);
8308             if (salp != NULL) {
8309               itemID = GetItemIDGivenPointer (bfp->input_entityID, OBJ_SEQALIGN, (Pointer) salp);
8310               if (itemID != 0) {
8311                 WatchCursor ();
8312                 Update ();
8313                 GatherProcLaunch (OMPROC_EDIT, FALSE, bfp->input_entityID, itemID,
8314                                   OBJ_SEQALIGN, 0, 0, OBJ_SEQALIGN, 0);
8315                 ArrowCursor ();
8316                 Update ();
8317               }
8318             }
8319 COLOMBE END *******************/
8320             sap  = (SeqAnnotPtr)FindSeqAlignInSeqEntry (sep, OBJ_SEQANNOT);
8321             if (sap) {
8322               itemID = GetItemIDGivenPointer (bfp->input_entityID, OBJ_SEQANNOT, (Pointer)sap);
8323               if (itemID != 0) {
8324                 WatchCursor ();
8325                 Update ();
8326                 SeqEntrySetScope (NULL);
8327                 GatherProcLaunch (OMPROC_EDIT, FALSE, bfp->input_entityID, itemID, OBJ_SEQANNOT, 0, 0, OBJ_SEQANNOT, 0);
8328                 ArrowCursor ();
8329                 Update ();
8330               }
8331             }
8332           }
8333         } else if (mssg == mssgsub) {
8334           EditSubmitBlock (bfp);
8335         } else if (mssg == mssgdup) {
8336           sel = ObjMgrGetSelected ();
8337           if (sel != NULL &&
8338               (sel->itemtype == OBJ_SEQDESC || sel->itemtype == OBJ_SEQFEAT)) {
8339             stdedprocs.duplicateExisting = TRUE;
8340             WatchCursor ();
8341             Update ();
8342             SeqEntrySetScope (NULL);
8343             GatherProcLaunch (OMPROC_EDIT, FALSE, sel->entityID, sel->itemID,
8344                               sel->itemtype, 0, 0, sel->itemtype, 0);
8345             ArrowCursor ();
8346             Update ();
8347             stdedprocs.duplicateExisting = FALSE;
8348           }
8349         }
8350         break;
8351     }
8352   }
8353 }
8354 
8355 static void SequinSeqEditFormMessage (ForM f, Int2 mssg)
8356 
8357 {
8358   BaseFormPtr  bfp;
8359 
8360   bfp = (BaseFormPtr) GetObjectExtra (f);
8361   if (bfp != NULL) {
8362     switch (mssg) {
8363       case VIB_MSG_QUIT :
8364         QuitProc ();
8365         break;
8366       default :
8367         break;
8368     }
8369   }
8370 }
8371 
8372 /* from salfiles.c */
8373 static Int4 AccessionToGi (CharPtr string, CharPtr program)
8374 {
8375    /*
8376    CharPtr str;
8377    LinkSetPtr lsp;
8378    Int4 gi;
8379 
8380    EntrezInit (program, TRUE, NULL);
8381    str = MemNew (StringLen (string) + 10);
8382    sprintf (str, "\"%s\" [ACCN]", string);
8383    lsp = EntrezTLEvalString (str, TYP_NT, -1, NULL, NULL);
8384    MemFree (str);
8385    if (lsp == NULL)
8386        return 0;
8387    if (lsp->num <= 0) {
8388        LinkSetFree (lsp);
8389        return 0;
8390    }
8391    gi = lsp->uids [0];
8392    LinkSetFree (lsp);
8393    EntrezFini ();
8394    return gi;
8395    */
8396    return 0;
8397 }
8398 
8399 static SeqEntryPtr LIBCALLBACK SeqEdDownload (CharPtr program, CharPtr accession,
8400                                               Int4 uid, Boolean is_na, BoolPtr is_new)
8401 
8402 {
8403   BioseqPtr    bsp;
8404   SeqEntryPtr  sep = NULL;
8405   SeqId        sid;
8406   /*
8407   LinkSetPtr   lsp;
8408   Int2         seqtype;
8409   Char         str [64];
8410   */
8411 
8412   if (is_new != NULL) {
8413      *is_new = TRUE;
8414   }
8415 /*********/
8416   if (uid==0 && ! StringHasNoText (accession))
8417     uid = AccessionToGi (accession, program);
8418   if (uid > 0) {
8419     sid.choice = SEQID_GI;
8420     sid.data.intvalue = uid;
8421     sid.next = NULL;
8422     bsp = BioseqFind (&sid);
8423     if (bsp) {
8424       sep = SeqMgrGetSeqEntryForData (bsp);
8425     }
8426   }
8427   if (sep) {
8428     if (is_new != NULL) {
8429       *is_new = FALSE;
8430     }
8431     return sep;
8432   }
8433 /********************/
8434   /*
8435   EntrezInit (program, TRUE, NULL);
8436   if (uid==0 && ! StringHasNoText (accession)) {
8437     if (is_na) {
8438       seqtype = TYP_NT;
8439     } else {
8440       seqtype = TYP_AA;
8441     }
8442     sprintf (str, "\"%s\" [ACCN]", accession);
8443     lsp = EntrezTLEvalString (str, seqtype, -1, NULL, NULL);
8444     if (lsp != NULL) {
8445       uid = lsp->uids [0];
8446     }
8447     LinkSetFree (lsp);
8448   }
8449   if (uid > 0) {
8450     sid.choice = SEQID_GI;
8451     sid.data.intvalue = uid;
8452     sid.next = NULL;
8453     bsp = BioseqLockById (&sid);
8454     if (bsp != NULL) {
8455       sep = SeqMgrGetSeqEntryForData (bsp);
8456       BioseqUnlock (bsp);
8457     } else {
8458       sep = EntrezSeqEntryGet (uid, 0);
8459       if (is_new != NULL) {
8460         *is_new = TRUE;
8461       }
8462     }
8463   }
8464   EntrezFini ();
8465   return sep;
8466   */
8467   return NULL;
8468 }
8469 
8470 static void SequinStdEditorFormMessage (ForM f, Int2 mssg)
8471 
8472 {
8473   BaseFormPtr  bfp;
8474 
8475   bfp = (BaseFormPtr) GetObjectExtra (f);
8476   if (bfp != NULL) {
8477     switch (mssg) {
8478       case VIB_MSG_CLOSE :
8479         Remove (f);
8480         break;
8481       case VIB_MSG_QUIT :
8482         QuitProc ();
8483         break;
8484       case VIB_MSG_CUT :
8485         StdCutTextProc (NULL);
8486         break;
8487       case VIB_MSG_COPY :
8488         StdCopyTextProc (NULL);
8489         break;
8490       case VIB_MSG_PASTE :
8491         StdPasteTextProc (NULL);
8492         break;
8493       case VIB_MSG_DELETE :
8494         StdDeleteTextProc (NULL);
8495         break;
8496       default :
8497         break;
8498     }
8499   }
8500 }
8501 
8502 static void ProcessHelpMessage (CharPtr heading, CharPtr section)
8503 
8504 {
8505   SendHelpScrollMessage (helpForm, heading, section);
8506 }
8507 
8508 /*
8509 static void MakeTermListForm (void)
8510 
8511 {
8512   if (! EntrezIsInited ()) {
8513     EntrezBioseqFetchEnable ("Sequin", TRUE);
8514     SequinEntrezInit ("Sequin", FALSE, NULL);