NCBI C Toolkit Cross Reference

C/desktop/cdrgn.c


  1 /*   cdrgn.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:  cdrgn.c
 27 *
 28 * Author:  Jonathan Kans
 29 *
 30 * Version Creation Date:   1/22/95
 31 *
 32 * $Revision: 6.122 $
 33 *
 34 * File Description: 
 35 *
 36 * Modifications:  
 37 * --------------------------------------------------------------------------
 38 * Date     Name        Description of modification
 39 * -------  ----------  -----------------------------------------------------
 40 *
 41 *
 42 * ==========================================================================
 43 */
 44 
 45 #include <cdrgn.h>
 46 #include <biosrc.h>
 47 #include <seqport.h>
 48 #include <gather.h>
 49 #include <tofasta.h>
 50 #include <document.h>
 51 #include <suggslp.h>
 52 #include <salutil.h>
 53 #include <salign.h>
 54 #include <edutil.h>
 55 #include <bspview.h>
 56 #include <toasn3.h>
 57 #include <subutil.h>
 58 #include <explore.h>
 59 #include <pmfapi.h>
 60 #include <seqpanel.h>
 61 #define NLM_GENERATED_CODE_PROTO
 62 #include <objmacro.h>
 63 #include <macroapi.h>
 64 
 65 #define CODING_REGION_PAGE    0
 66 #define GENE_PAGE             0
 67 #define PROT_PAGE             0
 68 #define RNA_PAGE              0
 69 #define COMMON_PAGE           1
 70 #define LOCATION_PAGE         2
 71 
 72 #define NUM_PAGES  8
 73 
 74 typedef struct cdrgnform {
 75   FEATURE_FORM_BLOCK
 76   SeqEntryPtr   sep;
 77   GrouP         pages [NUM_PAGES];
 78   DialoG        foldertabs;
 79   Int2          currentPage;
 80   ButtoN        conceptTransA;
 81   GrouP         protTextGrp;
 82   TexT          protNameText;
 83   TexT          protDescText;
 84   GrouP         protPromptGrp;
 85   DialoG        ecProcs;
 86   Uint2         protEntityID;
 87   Uint4         protItemID;
 88   Uint2         protItemtype;
 89   Boolean       protFound;
 90   PrompT        protlen;
 91   DialoG        protseq;
 92   GrouP         protSeqIdGrp;
 93   TexT          protSeqIdTxt;
 94   ButtoN        forceNear;
 95   ButtoN        launchBtn;
 96   ButtoN        edProtBtn;
 97   ButtoN        edProtBtn2;
 98   ButtoN        edSeqBtn;
 99   BioseqPtr     usethisbioseq;
100   Boolean       autoUpdatePartials;
101   Boolean       autoRetranslate;
102   Boolean       locvisited;
103   ButtoN        convertToMiscFeat;
104   Boolean       saveAsMiscFeat;
105   ButtoN        makemRNAMatch;
106 } CdRgnForm, PNTR CdRgnFormPtr;
107 
108 typedef struct cdrgnpage {
109   DIALOG_MESSAGE_BLOCK
110   ButtoN             orf;
111   PopuP              frame;
112   ButtoN             conflict;
113   PopuP              geneticCode;
114   DialoG             cdBrk;
115   Int2               count;
116   EnumFieldAssoc     PNTR alist;
117   EnumFieldAssocPtr  alists [2];
118   GrouP              cdRgnGrp [4];
119   GrouP              commonGrp;
120   Int2               currentPage;
121   CdRgnFormPtr       cfp;
122 } CdRgnPage, PNTR CdRgnPagePtr;
123 
124 typedef struct rawbioseqpage {
125   DIALOG_MESSAGE_BLOCK
126   ByteStorePtr  bs;
127   Uint1         mol;
128   Uint1         repr;
129   Uint1         seq_data_type;
130   DoC           doc;
131   CdRgnFormPtr  cfp;
132 } RawBioseqPage, PNTR RawBioseqPagePtr;
133 
134 /* rna moved here to be available in product page */
135 
136 typedef struct rnaform {
137   FEATURE_FORM_BLOCK
138   SeqEntryPtr   sep;
139   GrouP         pages [NUM_PAGES];
140   DialoG        foldertabs;
141   Int2          currentPage;
142   Boolean       empty_feat;
143 } RnaForm, PNTR RnaFormPtr;
144 
145 typedef struct rnapage {
146   DIALOG_MESSAGE_BLOCK
147   PopuP         type;
148   ButtoN        pseudo;
149   GrouP         nameGrp;
150   PrompT        rrnaPrompt;
151   PrompT        ornaPrompt;
152   TexT          name;
153   GrouP         trnaGrp;
154   PopuP         AAitem;
155   DialoG        codons;
156   DialoG        anticodon;
157   GrouP         trnaPages [3];
158   RnaFormPtr    rfp;
159 
160   /* for ncRNA page */
161   GrouP         ncrnaGrp;
162   DialoG        ncrnaClass;
163   TexT          ncrnaProduct;
164 
165   /* for tmRNA page */
166   GrouP         tmrnaGrp;
167   TexT          tmrnaProduct;
168   DialoG        tmrnaTagPeptide;
169   
170   /* for switching between types */
171   Int4          prev_rna_type;
172 } RnaPage, PNTR RnaPagePtr;
173 
174 
175 static ParData brParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
176 static ColData brColFmt = {0, 0, 80, 0, NULL, 'l', FALSE, FALSE, FALSE, FALSE, TRUE};
177 
178 static Boolean RawFastaFileFunc (BioseqPtr bsp, Int2 key, CharPtr buf, Uint4 buflen, Pointer data)
179 
180 {
181   FILE  *fp;
182 
183   fp = (FILE *) data;
184   switch (key) {
185     case FASTA_SEQLINE :
186       fprintf (fp, "%s\n", buf);
187       break;
188     default :
189       break;
190   }
191   return TRUE;
192 }
193 
194 static void BioseqPtrToRawBioseqPage (DialoG d, Pointer data)
195 
196 {
197   BioseqPtr         bsp;
198   Char              buf [256];
199   FILE              *fp;
200   MyFsa             mfa;
201   ErrSev            oldErrSev;
202   Char              path [PATH_MAX];
203   RecT              r;
204   RawBioseqPagePtr  rbpp;
205 
206   rbpp = (RawBioseqPagePtr) GetObjectExtra (d);
207   bsp = (BioseqPtr) data;
208   if (rbpp != NULL) {
209     rbpp->bs = BSFree (rbpp->bs);
210     Reset (rbpp->doc);
211     if (bsp != NULL) {
212       if ((bsp->repr == Seq_repr_raw || bsp->repr == Seq_repr_const) &&
213           bsp->seq_data_type != Seq_code_gap) {
214         rbpp->bs = BSDup ((ByteStorePtr) bsp->seq_data);
215         rbpp->seq_data_type = bsp->seq_data_type;
216         rbpp->mol = bsp->mol;
217         rbpp->repr = bsp->repr;
218         TmpNam (path);
219         fp = FileOpen (path, "w");
220         if (fp != NULL) {
221           MemSet ((Pointer) (&mfa), 0, sizeof (MyFsa));
222           mfa.buf = buf;
223           mfa.buflen = 255;
224           mfa.seqlen = 50;
225           mfa.mydata = (Pointer) fp;
226           mfa.myfunc = RawFastaFileFunc;
227           mfa.bad_asn1 = FALSE;
228           mfa.order = 0;
229           mfa.accession = NULL;
230           mfa.organism = NULL;
231           mfa.tech = 0;
232           mfa.do_virtual = FALSE;
233           mfa.formatdb = TRUE;
234 
235           if (ISA_na(bsp->mol))
236             mfa.code = Seq_code_iupacna;
237           else
238             mfa.code = Seq_code_ncbieaa;
239 
240           oldErrSev = ErrSetMessageLevel (SEV_MAX);
241           /*
242           BioseqToFastaX (bsp, &mfa, ISA_na (bsp->mol));
243           */
244           BioseqFastaStream (bsp, fp, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, 50, 0, 0, FALSE);
245           ErrSetMessageLevel (oldErrSev);
246         }
247         FileClose (fp);
248         ObjectRect (rbpp->doc, &r);
249         InsetRect (&r, 4, 4);
250         brColFmt.pixWidth = r.right - r.left;
251         DisplayFancy (rbpp->doc, path, &brParFmt, &brColFmt, programFont, 4);
252         FileRemove (path);
253       }
254     }
255     Update ();
256   }
257 }
258 
259 static Pointer RawBioseqPageToBioseqPtr (DialoG d)
260 
261 {
262   BioseqPtr         bsp;
263   Char              ch;
264   CdRgnFormPtr      cfp;
265   Int4              cnt;
266   Int4              cntr;
267   Int2              i;
268   Char              ids [32];
269   Int4              nxt;
270   Char              str [102];
271   RawBioseqPagePtr  rbpp;
272 
273   bsp = NULL;
274   rbpp = (RawBioseqPagePtr) GetObjectExtra (d);
275   if (rbpp != NULL) {
276     bsp = BioseqNew ();
277     if (bsp != NULL) {
278       cfp = rbpp->cfp;
279       ids [0] = '\0';
280       if (cfp != NULL) {
281         if (Visible (cfp->protSeqIdGrp)) {
282           GetTitle (cfp->protSeqIdTxt, ids, sizeof (ids) - 1);
283         }
284       }
285       if (StringHasNoText (ids)) {
286         if (ISA_na (rbpp->mol)) {
287           bsp->id = MakeSeqID ("dna_seq");
288         } else if (ISA_aa (rbpp->mol)) {
289           bsp->id = MakeSeqID ("prt_seq");
290         } else {
291           bsp->id = MakeSeqID ("oth_seq");
292         }
293       } else {
294         bsp->id = MakeSeqID (ids);
295       }
296       bsp->mol = rbpp->mol;
297       bsp->repr = rbpp->repr;
298       /*
299       bsp->seq_data_type = ISA_na (bsp->mol) ? Seq_code_iupacna : Seq_code_ncbieaa;
300       */
301       bsp->seq_data_type = rbpp->seq_data_type;
302       bsp->length = BSLen (rbpp->bs);
303       if (bsp->length == 0) {
304         bsp = BioseqFree (bsp);
305         return NULL;
306       }
307       bsp->seq_data = (SeqDataPtr) BSNew (bsp->length);
308       if (bsp->seq_data != NULL) {
309         BSSeek (rbpp->bs, 0, SEEK_SET);
310         cntr = BSLen (rbpp->bs);
311         cnt = MIN (cntr, 100L);
312         while (cnt > 0) {
313           cntr -= cnt;
314           nxt = MIN (cntr, 100L);
315           BSRead (rbpp->bs, str, cnt * sizeof (Char));
316           for (i = 0; i < cnt; i++) {
317             ch = str [i];
318             str [i] = TO_UPPER (ch);
319           }
320           if (nxt == 0 && cnt > 0 && bsp->seq_data_type == Seq_code_ncbieaa) {
321             if (str [cnt - 1] == '*') {
322               cnt--;
323               if (bsp->length > 0) {
324                 (bsp->length)--;
325               }
326             }
327           }
328           BSWrite ((ByteStorePtr) bsp->seq_data, str, cnt * sizeof (Char));
329           cnt = nxt;
330         }
331       }
332       /*
333       if (bsp->seq_data_type == Seq_code_ncbieaa) {
334         BioseqRawConvert (bsp, Seq_code_iupacaa);
335       }
336       */
337       SeqMgrAddToBioseqIndex (bsp);
338     }
339   }
340   return (Pointer) bsp;
341 }
342 
343 static void CleanupRawBioseqPage (GraphiC g, VoidPtr data)
344 
345 {
346   RawBioseqPagePtr  rbpp;
347 
348   rbpp = (RawBioseqPagePtr) data;
349   if (rbpp != NULL) {
350     BSFree (rbpp->bs);
351   }
352   MemFree (data);
353 }
354 
355 static DialoG CreateBioseqRawDialog (GrouP h, CharPtr title, Uint1 mol, CdRgnFormPtr cfp)
356 
357 {
358   Int2              charwid;
359   RawBioseqPagePtr  rbpp;
360   GrouP             m;
361   GrouP             p;
362   GrouP             s;
363 
364   p = HiddenGroup (h, 1, 0, NULL);
365   SetGroupSpacing (p, 10, 10);
366 
367   rbpp = (RawBioseqPagePtr) MemNew (sizeof (RawBioseqPage));
368   if (rbpp != NULL) {
369 
370     SetObjectExtra (p, rbpp, CleanupRawBioseqPage);
371     rbpp->dialog = (DialoG) p;
372     rbpp->todialog = BioseqPtrToRawBioseqPage;
373     rbpp->fromdialog = RawBioseqPageToBioseqPtr;
374     rbpp->testdialog = NULL;
375 
376     if (title != NULL && title [0] != '\0') {
377       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
378     } else {
379       s = HiddenGroup (p, 0, -2, NULL);
380     }
381     m = HiddenGroup (s, -1, 0, NULL);
382     SetGroupSpacing (m, 10, 10);
383 
384     rbpp->cfp = cfp;
385     rbpp->mol = mol;
386     SelectFont (programFont);
387     charwid = CharWidth ('0');
388     SelectFont (systemFont);
389     rbpp->doc = DocumentPanel (m, charwid * 50 + 2, stdLineHeight * 6);
390   }
391 
392   return (DialoG) p;
393 }
394 
395 static void ConvertToAACodeBreak (CdRgnFormPtr cfp, CdRegionPtr crp, CodeBreakPtr cb)
396 
397 {
398   SeqFeatPtr  sfp;
399   SeqLocPtr   slp;
400 
401   if (cfp == NULL || crp == NULL || cb == NULL) return;
402   sfp = SeqFeatNew ();
403   if (sfp == NULL) return;
404   sfp->data.choice = SEQFEAT_CDREGION;
405   sfp->data.value.ptrvalue = crp;
406   sfp->location = DialogToPointer (cfp->location);
407   sfp->product = DialogToPointer (cfp->product);
408   while (cb != NULL) {
409     slp = dnaLoc_to_aaLoc (sfp, cb->loc, TRUE, NULL, TRUE);
410     cb->loc = SeqLocFree (cb->loc);
411     cb->loc = slp;
412     cb = cb->next;
413   }
414   SeqLocFree (sfp->product);
415   SeqLocFree (sfp->location);
416   MemFree (sfp);
417 }
418 
419 static void ConvertToNTCodeBreak (CdRgnFormPtr cfp, CdRegionPtr crp, CodeBreakPtr cb)
420 
421 {
422   SeqFeatPtr  sfp;
423   SeqLocPtr   slp;
424 
425   if (cfp == NULL || crp == NULL || cb == NULL) return;
426   sfp = SeqFeatNew ();
427   if (sfp == NULL) return;
428   sfp->data.choice = SEQFEAT_CDREGION;
429   sfp->data.value.ptrvalue = crp;
430   sfp->location = DialogToPointer (cfp->location);
431   sfp->product = DialogToPointer (cfp->product);
432   while (cb != NULL) {
433     slp = aaLoc_to_dnaLoc (sfp, cb->loc);
434     cb->loc = SeqLocFree (cb->loc);
435     cb->loc = slp;
436     cb = cb->next;
437   }
438   SeqLocFree (sfp->product);
439   SeqLocFree (sfp->location);
440   MemFree (sfp);
441 }
442 
443 static void CdRegionPtrToCdRgnPage (DialoG d, Pointer data)
444 
445 {
446   CodeBreakPtr    cbhead;
447   CodeBreakPtr    cbp;
448   CdRgnPagePtr    cpp;
449   CdRegionPtr     crp;
450   CodeBreakPtr    curr;
451   GeneticCodePtr  gcp;
452   Int4            id;
453   CodeBreakPtr    last;
454   Char            name [256];
455   ValNodePtr      tmp;
456   SeqFeatPtr      mrna;
457   SeqLocPtr       slp;
458   SeqMgrFeatContext fcontext;
459 
460   cpp = (CdRgnPagePtr) GetObjectExtra (d);
461   crp = (CdRegionPtr) data;
462   if (cpp != NULL) {
463     if (crp != NULL) {
464       SetStatus (cpp->orf, crp->orf);
465       if (crp->orf) {
466         SafeShow (cpp->orf);
467       }
468       SetStatus (cpp->conflict, crp->conflict);
469       if (crp->conflict) {
470         SafeShow (cpp->conflict);
471       }
472       SetValue (cpp->frame, crp->frame + 1);
473       id = 0;
474       name [0] = '\0';
475       gcp = crp->genetic_code;
476       if (gcp != NULL) {
477         tmp = (ValNodePtr) gcp->data.ptrvalue;
478         for (tmp = (ValNodePtr) gcp->data.ptrvalue; tmp != NULL; tmp = tmp->next) {
479           switch (tmp->choice) {
480             case 1 :
481               if (name [0] == '\0') {
482                 StringNCpy_0 (name, (CharPtr) tmp->data.ptrvalue, sizeof (name));
483               }
484               break;
485             case 2 :
486               id = tmp->data.intvalue;
487               break;
488             default :
489               break;
490           }
491         }
492         if (id == 0) {
493           gcp = GeneticCodeFind (id, name);
494           if (gcp != NULL) {
495             for (tmp = (ValNodePtr) gcp->data.ptrvalue; tmp != NULL; tmp = tmp->next) {
496               switch (tmp->choice) {
497                 case 2 :
498                   id = tmp->data.intvalue;
499                   break;
500                 default :
501                   break;
502               }
503             }
504           }
505         }
506       }
507       if (id > 0 && id < NUM_GENETIC_CODES) {
508         SetValue (cpp->geneticCode, gcIdToIndex [(Int2) id]);
509       } else {
510         SetValue (cpp->geneticCode, 1);
511       }
512       cbhead = NULL;
513       last = NULL;
514       curr = crp->code_break;
515       while (curr != NULL) {
516         cbp = AsnIoMemCopy ((Pointer) curr,
517                             (AsnReadFunc) CodeBreakAsnRead,
518                             (AsnWriteFunc) CodeBreakAsnWrite);
519         if (cbhead == NULL) {
520           cbhead = cbp;
521         }
522         if (last != NULL) {
523           last->next = cbp;
524         }
525         last = cbp;
526         curr = curr->next;
527       }
528       ConvertToAACodeBreak (cpp->cfp, crp, cbhead);
529       PointerToDialog (cpp->cdBrk, cbhead);
530       CodeBreakFree (cbhead);
531 
532     } else {
533       SafeSetStatus (cpp->orf, FALSE);
534       SafeSetStatus (cpp->conflict, FALSE);
535       SafeSetValue (cpp->frame, 1);
536       SafeSetValue (cpp->geneticCode, 1);
537     }
538     /* look for overlapping mRNA */
539     slp = DialogToPointer (cpp->cfp->location);
540     mrna = SeqMgrGetOverlappingmRNA (slp, &fcontext);
541     slp = SeqLocFree (slp);
542     if (mrna == NULL) {
543       Hide (cpp->cfp->makemRNAMatch);
544     } else {
545       Show (cpp->cfp->makemRNAMatch);
546     }
547 
548   }
549 }
550 
551 static SeqIdPtr  globalid;
552 
553 static CodeBreakPtr RemoveNullLocationCodeBreaks (CodeBreakPtr cbp)
554 {
555   CodeBreakPtr this_cbp, prev_cbp, next_cbp;
556   
557   prev_cbp = NULL;
558   for (this_cbp = cbp; this_cbp != NULL; this_cbp = next_cbp)
559   {
560       next_cbp = this_cbp->next;
561       if (this_cbp->loc == NULL)
562       {
563         Message (MSG_ERROR, "A code break was removed because the location is now invalid");
564         if (prev_cbp == NULL)
565         {
566             cbp = this_cbp->next;
567         }
568         else
569         {
570             prev_cbp->next = this_cbp->next;
571         }
572         this_cbp->next = NULL;
573         CodeBreakFree (this_cbp);
574       }
575   }
576   return cbp;
577 }
578 
579 static Pointer CdRgnPageToCdRegionPtr (DialoG d)
580 
581 {
582   BioseqPtr     bsp = NULL;
583   CodeBreakPtr  cbp;
584   CdRgnFormPtr  cfp;
585   ValNodePtr    code;
586   CdRgnPagePtr  cpp;
587   CdRegionPtr   crp;
588   ImpFeatPtr    ifp;
589   SeqIdPtr      sip;
590   SeqLocPtr     slp;
591   Int2          val;
592   ValNodePtr    vnp;
593 
594   crp = NULL;
595   cpp = (CdRgnPagePtr) GetObjectExtra (d);
596   if (cpp != NULL) {
597     cfp = cpp->cfp;
598     if (cfp != NULL && cfp->saveAsMiscFeat) {
599       ifp = ImpFeatNew ();
600       if (ifp != NULL) {
601         ifp->key = StringSave ("misc_feature");
602       }
603       return (Pointer) ifp;
604     }
605     crp = CdRegionNew ();
606     if (crp != NULL) {
607       crp->orf = GetStatus (cpp->orf);
608       crp->conflict = GetStatus (cpp->conflict);
609       crp->frame = (Uint1) GetValue (cpp->frame) - 1;
610       crp->gaps = 0;
611       crp->mismatch = 0;
612       crp->stops = 0;
613       val = gcIndexToId [GetValue (cpp->geneticCode)];
614       if (val == 0) {
615         val = 1;  /* default to standard genetic code if not set */
616       }
617       if (val > 0 && val < NUM_GENETIC_CODES) {
618         code = ValNodeNew (NULL);
619         if (code != NULL) {
620           code->choice = 254;
621           vnp = ValNodeNew (NULL);
622           code->data.ptrvalue = vnp;
623           if (vnp != NULL) {
624             vnp->choice = 2;
625             vnp->data.intvalue = (Int4) val;
626           }
627         }
628         crp->genetic_code = code;
629         globalid = NULL;
630         cfp = cpp->cfp;
631         if (cfp != NULL) {
632           slp = DialogToPointer (cfp->product);
633           if (slp != NULL) {
634             sip = SeqLocId (slp);
635             if (sip != NULL) {
636               bsp = BioseqFind (sip);
637               if (bsp != NULL) {
638                 globalid = SeqIdFindBest (bsp->id, 0);
639               }
640             }
641             SeqLocFree (slp);
642           }
643         }
644         if (globalid != NULL) {
645           cbp = DialogToPointer (cpp->cdBrk);
646           ConvertToNTCodeBreak (cpp->cfp, crp, cbp);
647           /* remove any code breaks that have fallen off the end of the protein */
648           cbp = RemoveNullLocationCodeBreaks (cbp);
649           crp->code_break = cbp;
650         }
651       }
652     }
653   }
654   return (Pointer) crp;
655 }
656 
657 static void PopulateGeneticCodePopup (PopuP gc)
658 
659 {
660   Int2  i;
661 
662   if (gc != NULL) {
663     PopupItem (gc, " ");
664     for (i = 1; i <= numGeneticCodes; i++) {
665       PopupItem (gc, gcNames [i]);
666     }
667   }
668 }
669 
670 static void CleanupCdRgnPage (GraphiC g, VoidPtr data)
671 
672 {
673   CdRgnPagePtr  cpp;
674   Int2          j;
675 
676   cpp = (CdRgnPagePtr) data;
677   if (cpp != NULL) {
678     if (cpp->alist != NULL) {
679       for (j = 0; j < cpp->count; j++) {
680         MemFree (cpp->alist [j].name);
681       }
682     }
683     MemFree (cpp->alist);
684   }
685   MemFree (data);
686 }
687 
688 static void SetCdRgnImportExportItems (CdRgnFormPtr cfp)
689 
690 {
691   CdRgnPagePtr  cpp;
692   IteM          exportItm;
693   IteM          importItm;
694 
695   if (cfp != NULL) {
696     importItm = FindFormMenuItem ((BaseFormPtr) cfp, VIB_MSG_IMPORT);
697     exportItm = FindFormMenuItem ((BaseFormPtr) cfp, VIB_MSG_EXPORT);
698     switch (cfp->currentPage) {
699       case CODING_REGION_PAGE :
700         cpp = (CdRgnPagePtr) GetObjectExtra (cfp->data);
701         if (cpp != NULL) {
702           if (cpp->currentPage == 0) {
703             SafeSetTitle (importItm, "Import Protein FASTA...");
704             SafeSetTitle (exportItm, "Export Protein FASTA...");
705             SafeEnable (importItm);
706             SafeEnable (exportItm);
707           } else {
708             SafeSetTitle (importItm, "Import...");
709             SafeSetTitle (exportItm, "Export...");
710             SafeDisable (importItm);
711             SafeDisable (exportItm);
712           }
713         } else {
714           SafeSetTitle (importItm, "Import...");
715           SafeSetTitle (exportItm, "Export...");
716           SafeDisable (importItm);
717           SafeDisable (exportItm);
718         }
719         break;
720       case COMMON_PAGE :
721         SafeSetTitle (importItm, "Import...");
722         SafeSetTitle (exportItm, "Export...");
723         SafeDisable (importItm);
724         SafeDisable (exportItm);
725         break;
726       case LOCATION_PAGE :
727         SafeSetTitle (importItm, "Import SeqLoc...");
728         SafeSetTitle (exportItm, "Export SeqLoc...");
729         SafeEnable (importItm);
730         SafeEnable (exportItm);
731         break;
732       default :
733         break;
734     }
735   }
736 }
737 
738 static CharPtr cdRgnTabs [] = {
739   "Product", "Protein", "Exceptions", "Misc", NULL
740 };
741 
742 static void ChangeCdRgnSubPage (VoidPtr data, Int2 newval, Int2 oldval)
743 
744 {
745   CdRgnPagePtr  cpp;
746 
747   cpp = (CdRgnPagePtr) data;
748   if (cpp != NULL) {
749     cpp->currentPage = newval;
750     if (oldval >= 0 && oldval <= 3) {
751       SafeHide (cpp->cdRgnGrp [oldval]);
752     }
753     /*
754     if (newval == 3) {
755       SafeHide (cpp->commonGrp);
756     }
757     */
758     if (newval >= 0 && newval <= 3) {
759       SafeShow (cpp->cdRgnGrp [newval]);
760     }
761     /*
762     if (newval >= 0 && newval < 3) {
763       SafeShow (cpp->commonGrp);
764     }
765     */
766     SetCdRgnImportExportItems (cpp->cfp);
767     Update ();
768   }
769 }
770 
771 static Boolean ProtViewLaunchFunc (GatherContextPtr gcp)
772 
773 {
774   BioseqPtr        bsp;
775   Int2             handled;
776   SeqViewProcsPtr  svpp;
777 
778   if (gcp == NULL) return TRUE;
779   bsp = (BioseqPtr) gcp->userdata;
780   if (bsp == NULL) return TRUE;
781   if (gcp->thistype == OBJ_BIOSEQ) {
782     if (bsp == (BioseqPtr) gcp->thisitem) {
783       WatchCursor ();
784       svpp = (SeqViewProcsPtr) GetAppProperty ("SeqDisplayForm");
785       if (svpp != NULL) {
786         svpp->forceSeparateViewer = TRUE;
787       }
788       handled = GatherProcLaunch (OMPROC_VIEW, FALSE, gcp->entityID, gcp->itemID,
789                                   OBJ_BIOSEQ, 0, 0, OBJ_BIOSEQ, 0);
790       ArrowCursor ();
791       if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
792         Message (MSG_ERROR, "Unable to launch viewer on protein product.");
793       }
794       return FALSE;
795     }
796   }
797   return TRUE;
798 }
799 
800 static void LaunchProteinViewer (ButtoN b)
801 
802 {
803   BioseqPtr     bsp;
804   CdRgnFormPtr  cfp;
805   GatherScope   gs;
806   SeqIdPtr      sip;
807   SeqLocPtr     slp;
808 
809   cfp = (CdRgnFormPtr) GetObjectExtra (b);
810   if (cfp != NULL) {
811     slp = DialogToPointer (cfp->product);
812     if (slp != NULL) {
813       sip = SeqLocId (slp);
814       if (sip != NULL) {
815         bsp = BioseqFind (sip);
816         if (bsp != NULL) {
817           MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
818           gs.seglevels = 1;
819           gs.get_feats_location = TRUE;
820           MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
821           gs.ignore[OBJ_BIOSEQ] = FALSE;
822           gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
823           GatherEntity (cfp->input_entityID, (Pointer) bsp, ProtViewLaunchFunc, &gs);
824         }
825       }
826       SeqLocFree (slp);
827     }
828   }
829 }
830 
831 static Boolean EdProtSeqLaunchFunc (GatherContextPtr gcp)
832 
833 {
834   BioseqPtr  bsp;
835   Int2       handled;
836 
837   if (gcp == NULL) return TRUE;
838   bsp = (BioseqPtr) gcp->userdata;
839   if (bsp == NULL) return TRUE;
840   if (gcp->thistype == OBJ_BIOSEQ) {
841     if (bsp == (BioseqPtr) gcp->thisitem) {
842       WatchCursor ();
843       handled = GatherProcLaunch (OMPROC_EDIT, FALSE, gcp->entityID, gcp->itemID,
844                                   OBJ_BIOSEQ, OBJ_BIOSEQ, Seq_repr_raw, OBJ_BIOSEQ, Seq_repr_raw);
845       ArrowCursor ();
846       if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
847         Message (MSG_ERROR, "Unable to launch editor on protein product.");
848       }
849       return FALSE;
850     }
851   }
852   return TRUE;
853 }
854 
855 static void LaunchProtSeqEd (ButtoN b)
856 
857 {
858   BioseqPtr     bsp;
859   CdRgnFormPtr  cfp;
860   GatherScope   gs;
861   SeqIdPtr      sip;
862   SeqLocPtr     slp;
863 
864   cfp = (CdRgnFormPtr) GetObjectExtra (b);
865   if (cfp != NULL) {
866     slp = DialogToPointer (cfp->product);
867     if (slp != NULL) {
868       sip = SeqLocId (slp);
869       if (sip != NULL) {
870         bsp = BioseqFind (sip);
871         if (bsp != NULL) {
872 Message (MSG_OK, "Please close and reopen the coding region window after editing the sequence");
873           MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
874           gs.seglevels = 1;
875           gs.get_feats_location = TRUE;
876           MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
877           gs.ignore[OBJ_BIOSEQ] = FALSE;
878           gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
879           GatherEntity (cfp->input_entityID, (Pointer) bsp, EdProtSeqLaunchFunc, &gs);
880         }
881       }
882       SeqLocFree (slp);
883     }
884   }
885 }
886 
887 static void LaunchProtFeatEd (ButtoN b)
888 
889 {
890   CdRgnFormPtr  cfp;
891   Int2          handled;
892 
893   cfp = (CdRgnFormPtr) GetObjectExtra (b);
894   if (cfp != NULL && cfp->protFound) {
895     WatchCursor ();
896     SafeHide (cfp->protTextGrp);
897     SafeShow (cfp->protPromptGrp);
898     Update ();
899     handled = GatherProcLaunch (OMPROC_EDIT, FALSE, cfp->protEntityID, cfp->protItemID,
900                                 cfp->protItemtype, 0, 0, cfp->protItemtype, 0);
901     ArrowCursor ();
902     Update ();
903     if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
904       Message (MSG_ERROR, "Unable to launch editor on protein feature.");
905     }
906   }
907 }
908 
909 static void ChangeCdRgnPage (VoidPtr data, Int2 newval, Int2 oldval)
910 
911 {
912   CdRgnFormPtr  cfp;
913 
914   cfp = (CdRgnFormPtr) data;
915   if (cfp != NULL) {
916     cfp->currentPage = newval;
917     SafeHide (cfp->pages [oldval]);
918     SafeShow (cfp->pages [newval]);
919     switch (newval) {
920       case CODING_REGION_PAGE :
921         SendMessageToDialog (cfp->data, VIB_MSG_ENTER);
922         break;
923       case COMMON_PAGE :
924         break;
925       case LOCATION_PAGE :
926         SendMessageToDialog (cfp->location, VIB_MSG_ENTER);
927         cfp->locvisited = TRUE;
928         break;
929       default :
930         break;
931     }
932     SetCdRgnImportExportItems (cfp);
933     Update ();
934   }
935 }
936 
937 typedef struct protgatherlist {
938   ObjMgrPtr  omp;
939   SeqLocPtr  slp;
940   Int4       min;
941   CharPtr    protName;
942   CharPtr    protDesc;
943   Uint2      entityID;
944   Uint4      itemID;
945   Uint2      itemtype;
946   Boolean    protFound;
947 } ProtGatherList, PNTR ProtGatherPtr;
948 
949 static Boolean ProtMatchFunc (GatherContextPtr gcp)
950 
951 {
952   Int4           diff;
953   ObjMgrTypePtr  omtp;
954   ProtGatherPtr  pgp;
955   ProtRefPtr     prp;
956   SeqFeatPtr     sfp;
957   Char           thislabel [41];
958   ValNodePtr     vnp;
959 
960   if (gcp == NULL) return TRUE;
961 
962   pgp = (ProtGatherPtr) gcp->userdata;
963   if (pgp == NULL) return TRUE;
964 
965   thislabel [0] = '\0';
966 
967   if (gcp->thistype == OBJ_SEQFEAT) {
968     sfp = (SeqFeatPtr) gcp->thisitem;
969     if (sfp != NULL && sfp->data.choice == SEQFEAT_PROT && sfp->data.value.ptrvalue != NULL) {
970       omtp = ObjMgrTypeFind (pgp->omp, gcp->thistype, NULL, NULL);
971       if (omtp == NULL) {
972         return TRUE;
973       }
974       if (omtp->labelfunc != NULL) {
975         (*(omtp->labelfunc)) (gcp->thisitem, thislabel, 40, OM_LABEL_CONTENT);
976       }
977       if (thislabel [0] != '\0') {
978         diff = SeqLocAinB (sfp->location, pgp->slp);
979         if (diff >= 0) {
980           if (diff < pgp->min) {
981             pgp->min = diff;
982             prp = (ProtRefPtr) sfp->data.value.ptrvalue;
983             pgp->protName = MemFree (pgp->protName);
984             pgp->protDesc = MemFree (pgp->protDesc);
985             vnp = prp->name;
986             if (vnp != NULL) {
987               pgp->protName = StringSave ((CharPtr) vnp->data.ptrvalue);
988             }
989             pgp->protDesc = StringSave (prp->desc);
990             pgp->entityID = gcp->entityID;
991             pgp->itemID = gcp->itemID;
992             pgp->itemtype = gcp->thistype;
993             pgp->protFound = TRUE;
994           }
995         }
996       }
997     }
998   }
999 
1000   return TRUE;
1001 }
1002 
1003 static void SetBestProteinFeature (CdRgnFormPtr cfp, SeqLocPtr product)
1004 
1005 {
1006   GatherScope     gs;
1007   ProtGatherList  pgl;
1008 
1009   if (cfp == NULL) return;
1010   pgl.protName = NULL;
1011   pgl.protDesc = NULL;
1012   pgl.entityID = 0;
1013   pgl.itemID = 0;
1014   pgl.itemtype = 0;
1015   pgl.protFound = FALSE;
1016   if (product != NULL) {
1017     pgl.omp = ObjMgrGet ();
1018     pgl.slp = product;
1019     pgl.min = INT4_MAX;
1020     MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
1021     gs.seglevels = 1;
1022     gs.get_feats_location = TRUE;
1023     MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
1024     gs.ignore[OBJ_BIOSEQ] = FALSE;
1025     gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
1026     gs.ignore[OBJ_SEQFEAT] = FALSE;
1027     gs.ignore[OBJ_SEQANNOT] = FALSE;
1028     GatherEntity (cfp->input_entityID, (Pointer) &pgl, ProtMatchFunc, &gs);
1029   }
1030   SafeSetTitle (cfp->protNameText, pgl.protName);
1031   SafeSetTitle (cfp->protDescText, pgl.protDesc);
1032   cfp->protEntityID = pgl.entityID;
1033   cfp->protItemID = pgl.itemID;
1034   cfp->protItemtype = pgl.itemtype;
1035   cfp->protFound = pgl.protFound;
1036   MemFree (pgl.protName);
1037   MemFree (pgl.protDesc);
1038 }
1039 
1040 static void SetProteinLengthDisplay (PrompT p, Int4 length)
1041 
1042 {
1043   Char  len [32];
1044 
1045   if (p == NULL) return;
1046   if (length > 0) {
1047     sprintf (len, "%ld", (long) length);
1048     SetTitle (p, len);
1049   } else {
1050     SetTitle (p, "");
1051   }
1052 }
1053 
1054 static void CdRegionPtrToForm (ForM f, Pointer data)
1055 
1056 {
1057   BioseqPtr       bsp;
1058   CdRgnFormPtr    cfp;
1059   Char            id [41];
1060   MolInfoPtr      mip;
1061   SeqEntryPtr     oldsep;
1062   ProtRefPtr      prp;
1063   ValNodePtr      sdp;
1064   SeqEntryPtr     sep;
1065   SeqFeatPtr      sfp;
1066   SeqIdPtr        sip;
1067   ValNodePtr      vnp;
1068   SeqFeatXrefPtr  xref;
1069 
1070   cfp = (CdRgnFormPtr) GetObjectExtra (f);
1071   if (cfp != NULL) {
1072     sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
1073     oldsep = SeqEntrySetScope (sep);
1074     cfp->locvisited = TRUE;  /* even passing NULL will clear this protection */
1075     sfp = (SeqFeatPtr) data;
1076     if (sfp != NULL) {
1077       PointerToDialog (cfp->location, sfp->location);
1078       PointerToDialog (cfp->product, sfp->product);
1079       PointerToDialog (cfp->data, sfp->data.value.ptrvalue);
1080       SeqFeatPtrToCommon ((FeatureFormPtr) cfp, sfp);
1081       SetBestProteinFeature (cfp, sfp->product);
1082       if (! cfp->protFound) {
1083         xref = sfp->xref;
1084         while (xref != NULL && xref->data.choice != SEQFEAT_PROT) {
1085           xref = xref->next;
1086         }
1087         if (xref != NULL) {
1088           prp = (ProtRefPtr) xref->data.value.ptrvalue;
1089           if (prp != NULL) {
1090             vnp = prp->name;
1091             if (vnp != NULL) {
1092               SafeSetTitle (cfp->protNameText, (CharPtr) vnp->data.ptrvalue);
1093             }
1094             SafeSetTitle (cfp->protDescText, prp->desc);
1095           }
1096         }
1097       }
1098       if (sfp->product != NULL) {
1099         SafeHide (cfp->protSeqIdGrp);
1100         sip = SeqLocId (sfp->product);
1101         if (sip != NULL) {
1102           bsp = BioseqFind (sip);
1103           if (bsp != NULL) {
1104             PointerToDialog (cfp->protseq, bsp);
1105             SetProteinLengthDisplay (cfp->protlen, bsp->length);
1106             SafeEnable (cfp->launchBtn);
1107             SafeEnable (cfp->edProtBtn);
1108             SafeEnable (cfp->edProtBtn2);
1109             SafeEnable (cfp->edSeqBtn);
1110             SafeSetStatus (cfp->conceptTransA, FALSE);
1111             sep = SeqMgrGetSeqEntryForData (bsp);
1112             if (sep == NULL) return;
1113             sdp = SeqEntryGetSeqDescr (sep, Seq_descr_molinfo, NULL);
1114             if (sdp == NULL) return;
1115             mip = (MolInfoPtr) sdp->data.ptrvalue;
1116             if (mip == NULL) return;
1117             SafeSetStatus (cfp->conceptTransA, (Boolean) (mip->tech == 13));
1118             SeqEntrySetScope (oldsep);
1119             return;
1120           } else {
1121             SeqIdWrite (sip, id, PRINTID_FASTA_LONG, sizeof (id));
1122             SafeSetTitle (cfp->protSeqIdTxt, id);
1123             SafeShow (cfp->protSeqIdGrp);
1124             SafeDisable (cfp->launchBtn);
1125             SafeDisable (cfp->edProtBtn);
1126             SafeDisable (cfp->edProtBtn2);
1127             SafeDisable (cfp->edSeqBtn);
1128             SafeSetStatus (cfp->conceptTransA, FALSE);
1129             SeqEntrySetScope (oldsep);
1130             return;
1131           }
1132         }
1133       }
1134     }
1135     SafeSetTitle (cfp->protSeqIdTxt, "");
1136     SafeShow (cfp->protSeqIdGrp);
1137     SafeDisable (cfp->launchBtn);
1138     SafeDisable (cfp->edProtBtn);
1139     SafeDisable (cfp->edProtBtn2);
1140     SafeDisable (cfp->edSeqBtn);
1141     SafeSetStatus (cfp->conceptTransA, FALSE);
1142     SeqEntrySetScope (oldsep);
1143   }
1144 }
1145 
1146 typedef struct productpage {
1147   DIALOG_MESSAGE_BLOCK
1148   Int2          count;
1149   SeqEntryPtr   PNTR bsptr;
1150   Handle        product;
1151   Boolean       usePopupForProduct;
1152   Int2          oldval;
1153   Boolean       nucProducts;
1154   CdRgnFormPtr  cfp;
1155   RnaFormPtr    rfp;
1156   BaseFormPtr   bfp;
1157 } ProductPage, PNTR ProductPagePtr;
1158 
1159 static void FillInProducts (SeqEntryPtr sep, Pointer mydata,
1160                             Int4 index, Int2 indent)
1161 
1162 {
1163   ProductPagePtr  ppp;
1164 
1165   if (sep != NULL && mydata != NULL) {
1166     ppp = (ProductPagePtr) mydata;
1167     ppp->bsptr [index] = sep;
1168   }
1169 }
1170 
1171 static void PopulateProductControl (Handle pr, ProductPagePtr ppp)
1172 
1173 {
1174   BioseqPtr    bsp;
1175   Int2         i;
1176   size_t       len;
1177   Boolean      okay;
1178   SeqEntryPtr  sep;
1179   Char         str [128];
1180   /*
1181   Char         ch;
1182   CharPtr      ttl;
1183   */
1184 
1185   if (pr != NULL && ppp != NULL && ppp->bsptr != NULL) {
1186     if (ppp->usePopupForProduct) {
1187       PopupItem (pr, "     ");
1188     } else {
1189       ListItem (pr, "     ");
1190     }
1191     for (i = 0; i < ppp->count; i++) {
1192       sep = ppp->bsptr [i];
1193       if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) {
1194         bsp = (BioseqPtr) sep->data.ptrvalue;
1195         okay = FALSE;
1196         if (ppp->nucProducts) {
1197           if (ISA_na (bsp->mol)) {
1198             okay = TRUE;
1199           }
1200         } else {
1201           if (ISA_aa (bsp->mol)) {
1202             okay = TRUE;
1203           }
1204         }
1205         if (okay) {
1206           SeqIdWrite (bsp->id, str, PRINTID_REPORT, sizeof (str));
1207           /*
1208           StringCat (str, " ");
1209           len = StringLen (str);
1210           ttl = BioseqGetTitle (bsp);
1211           StringNCat (str, ttl, sizeof (str) - len - 2);
1212           ttl = str;
1213           ch = *ttl;
1214           while (ch != '\0') {
1215             if (ch == ';') {
1216               *ttl = ',';
1217             }
1218             ttl++;
1219             ch = *ttl;
1220           }
1221           */
1222           len = StringLen (str);
1223           if (len > 60) {
1224             StringCpy (str + 60, "...");
1225           }
1226           if (ppp->usePopupForProduct) {
1227             PopupItem (pr, str);
1228           } else {
1229             ListItem (pr, str);
1230           }
1231         }
1232       }
1233     }
1234     SetValue (pr, 1);
1235     ppp->oldval = 1;
1236   }
1237 }
1238 
1239 static void SeqLocPtrToProduct (DialoG d, Pointer data)
1240 
1241 {
1242   BaseFormPtr     bfp;
1243   BioseqPtr       bsp;
1244   Int2            found;
1245   Int2            i;
1246   Boolean         okay;
1247   SeqEntryPtr     oldsep;
1248   ProductPagePtr  ppp;
1249   Int2            prots;
1250   SeqEntryPtr     sep;
1251   SeqIdPtr        sip;
1252   SeqLocPtr       slp;
1253   BioseqPtr       theBsp;
1254 
1255   ppp = (ProductPagePtr) GetObjectExtra (d);
1256   slp = (SeqLocPtr) data;
1257   if (ppp != NULL) {
1258     found = 0;
1259     if (slp != NULL) {
1260       sip = SeqLocId (slp);
1261       if (sip != NULL) {
1262         bfp = ppp->bfp;
1263         if (bfp != NULL) {
1264           sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1265           oldsep = SeqEntrySetScope (sep);
1266         }
1267         theBsp = BioseqFind (sip);
1268         if (bfp != NULL) {
1269           SeqEntrySetScope (oldsep);
1270         }
1271         if (theBsp != NULL) {
1272           prots = 0;
1273           for (i = 0; i < ppp->count; i++) {
1274             sep = ppp->bsptr [i];
1275             if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) {
1276               bsp = (BioseqPtr) sep->data.ptrvalue;
1277               okay = FALSE;
1278               if (ppp->nucProducts) {
1279                 if (ISA_na (bsp->mol)) {
1280                   okay = TRUE;
1281                 }
1282               } else {
1283                 if (ISA_aa (bsp->mol)) {
1284                   okay = TRUE;
1285                 }
1286               }
1287               if (okay) {
1288                 prots++;
1289                 if (bsp == theBsp) {
1290                   found = prots;
1291                 }
1292               }
1293             }
1294           }
1295         }
1296       }
1297     }
1298     SetValue (ppp->product, found + 1);
1299     ppp->oldval = found + 1;
1300     if (! ppp->usePopupForProduct) {
1301       SetOffset (ppp->product, 0, found);
1302     }
1303   }
1304 }
1305 
1306 static Pointer ProductToSeqLocPtr (DialoG d)
1307 
1308 {
1309   BioseqPtr       bsp;
1310   CdRgnFormPtr    cfp = NULL;
1311   Int2            i;
1312   Char            id [128];
1313   Boolean         okay;
1314   ProductPagePtr  ppp;
1315   Int2            prots;
1316   RnaFormPtr      rfp = NULL;
1317   SeqEntryPtr     sep;
1318   SeqIdPtr        sip;
1319   SeqLocPtr       slp;
1320   BioseqPtr       theBsp;
1321   Int2            val;
1322 
1323   slp = NULL;
1324   ppp = (ProductPagePtr) GetObjectExtra (d);
1325   if (ppp != NULL && ppp->cfp != NULL) {
1326     cfp = ppp->cfp;
1327     if (cfp->saveAsMiscFeat) {
1328       return NULL;
1329     }
1330   }
1331 
1332   if (ppp == NULL) return NULL;  
1333 
1334   if (ppp->bsptr != NULL) {
1335     if (ppp->nucProducts) {
1336       if (! Visible (d)) return NULL; /* not an mRNA, do not make product */
1337     }
1338     rfp = ppp->rfp;
1339     val = GetValue (ppp->product) - 1;
1340     prots = 0;
1341     theBsp = NULL;
1342     for (i = 0; i < ppp->count; i++) {
1343       sep = ppp->bsptr [i];
1344       if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) {
1345         bsp = (BioseqPtr) sep->data.ptrvalue;
1346         okay = FALSE;
1347         if (ppp->nucProducts) {
1348           if (ISA_na (bsp->mol)) {
1349             okay = TRUE;
1350           }
1351         } else {
1352           if (ISA_aa (bsp->mol)) {
1353             okay = TRUE;
1354           }
1355         }
1356         if (okay) {
1357           prots++;
1358           if (prots == val) {
1359             theBsp = bsp;
1360           }
1361         }
1362       }
1363     }
1364     if (ppp->cfp != NULL && ppp->cfp->usethisbioseq != NULL) {
1365       theBsp = ppp->cfp->usethisbioseq;
1366     }
1367     if (theBsp != NULL && theBsp->id != NULL) {
1368       slp = ValNodeNew (NULL);
1369       if (slp != NULL) {
1370         slp->choice = 3;
1371         slp->data.ptrvalue = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (theBsp->id, 0)));
1372       }
1373     } else if (cfp != NULL) {
1374       if (Visible (cfp->protSeqIdGrp) && (! GetStatus (cfp->forceNear))) {
1375         GetTitle (cfp->protSeqIdTxt, id, sizeof (id) - 1);
1376         if ((! StringHasNoText (id)) && StringChr (id, '|') != NULL) {
1377           sip = MakeSeqID (id);
1378           if (sip != NULL) {
1379             slp = ValNodeNew (NULL);
1380             if (slp != NULL) {
1381               slp->choice = 3;
1382               slp->data.ptrvalue = SeqIdStripLocus (sip);
1383             }
1384           }
1385         }
1386       }
1387     }
1388   }
1389   return (Pointer) slp;
1390 }
1391 
1392 static void CleanupProductPage (GraphiC g, VoidPtr data)
1393 
1394 {
1395   ProductPagePtr  ppp;
1396 
1397   ppp = (ProductPagePtr) data;
1398   if (ppp != NULL) {
1399     MemFree (ppp->bsptr);
1400   }
1401   MemFree (data);
1402 }
1403 
1404 static CharPtr protChangeMsg =
1405 "This will change the protein product assigned to this CDS.\n\
1406 It should only be done if the assignment was incorrect.\n\
1407 Are you really sure you want to do this?";
1408 
1409 static void ChangeProteinView (Handle obj)
1410 
1411 {
1412   MsgAnswer       ans;
1413   BioseqPtr       bsp;
1414   CdRgnFormPtr    cfp;
1415   ProductPagePtr  ppp;
1416   SeqIdPtr        sip;
1417   SeqLocPtr       slp;
1418 
1419   ppp = GetObjectExtra (obj);
1420   if (ppp != NULL && ppp->cfp != NULL) {
1421     if (ppp->nucProducts) return; /* using for mRNA product */
1422     ans = Message (MSG_OKC, "%s", protChangeMsg);
1423     if (ans == ANS_CANCEL) {
1424       SetValue (obj, ppp->oldval);
1425       return;
1426     }
1427     cfp = ppp->cfp;
1428     if (GetValue (obj) == 1) {
1429       SafeSetTitle (cfp->protSeqIdTxt, "");
1430       SafeShow (cfp->protSeqIdGrp);
1431       SafeDisable (cfp->launchBtn);
1432       SafeDisable (cfp->edProtBtn);
1433       SafeDisable (cfp->edProtBtn2);
1434       SafeDisable (cfp->edSeqBtn);
1435       SetBestProteinFeature (cfp, NULL);
1436       PointerToDialog (cfp->protseq, NULL);
1437       SetProteinLengthDisplay (cfp->protlen, 0);
1438       Update ();
1439       return;
1440     }
1441     SafeHide (cfp->protSeqIdGrp);
1442     slp = (SeqLocPtr) ProductToSeqLocPtr (ppp->dialog);
1443     SetBestProteinFeature (cfp, slp);
1444     if (slp != NULL) {
1445       sip = SeqLocId (slp);
1446       if (sip != NULL) {
1447         bsp = BioseqFind (sip);
1448         if (bsp != NULL) {
1449           PointerToDialog (cfp->protseq, bsp);
1450           SetProteinLengthDisplay (cfp->protlen, bsp->length);
1451           SafeEnable (cfp->launchBtn);
1452           SafeEnable (cfp->edProtBtn);
1453           SafeEnable (cfp->edProtBtn2);
1454           SafeEnable (cfp->edSeqBtn);
1455         }
1456       }
1457       SeqLocFree (slp);
1458     }
1459     Update ();
1460   }
1461 }
1462 
1463 
1464 static DialoG CreateProteinOrMRNAProductDialog (GrouP h, CharPtr title,
1465                                                 CharPtr label, Boolean nucProducts,
1466                                                 SeqEntryPtr sep, CdRgnFormPtr cfp,
1467                                                 RnaFormPtr rfp, BaseFormPtr bfp)
1468 
1469 {
1470   GrouP           m;
1471   GrouP           p;
1472   ProductPagePtr  ppp;
1473   GrouP           s;
1474 
1475   p = HiddenGroup (h, -1, 0, NULL);
1476   SetGroupSpacing (p, 10, 10);
1477 
1478   ppp = (ProductPagePtr) MemNew (sizeof (ProductPage));
1479   if (ppp != NULL) {
1480 
1481     SetObjectExtra (p, ppp, CleanupProductPage);
1482     ppp->dialog = (DialoG) p;
1483     ppp->todialog = SeqLocPtrToProduct;
1484     ppp->fromdialog = ProductToSeqLocPtr;
1485     ppp->testdialog = NULL;
1486     ppp->nucProducts = nucProducts;
1487 
1488     if (title != NULL && title [0] != '\0') {
1489       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
1490     } else {
1491       s = HiddenGroup (p, 0, -2, NULL);
1492     }
1493     m = HiddenGroup (s, -2, 0, NULL);
1494     /*
1495     SetGroupSpacing (m, 10, 10);
1496     */
1497 
1498     StaticPrompt (m, label, 0, popupMenuHeight, programFont, 'l');
1499     ppp->count = (Int2) BioseqCount (sep);
1500     ppp->bsptr = MemNew (sizeof (BioseqPtr) * ppp->count);
1501     if (ppp->bsptr != NULL) {
1502       BioseqExplore (sep, (Pointer) ppp, FillInProducts);
1503     }
1504     ppp->cfp = cfp;
1505     ppp->rfp = rfp;
1506     ppp->bfp = bfp;
1507     if (ppp->count < 32) {
1508       ppp->usePopupForProduct = TRUE;
1509       ppp->product = (Handle) PopupList (m, TRUE, (PupActnProc) ChangeProteinView);
1510     } else {
1511       ppp->usePopupForProduct = FALSE;
1512       ppp->product = (Handle) SingleList (m, 10, 3, (LstActnProc) ChangeProteinView);
1513     }
1514     SetObjectExtra (ppp->product, ppp, NULL);
1515     PopulateProductControl (ppp->product, ppp);
1516   }
1517 
1518   return (DialoG) p;
1519 }
1520 
1521 
1522 typedef struct rnatranscriptiddlg {
1523   DIALOG_MESSAGE_BLOCK
1524   DialoG               product;
1525   Boolean              usePopupForProduct;
1526   GrouP                far_id_grp;
1527   TexT                 far_id;
1528   Nlm_ChangeNotifyProc change_notify;
1529   Pointer              change_userdata;
1530 } RnaTranscriptIDDlgData, PNTR RnaTranscriptIdDlgPtr;
1531 
1532 static void ChangeTranscriptIDSequenceSelection (Pointer userdata)
1533 {
1534   RnaTranscriptIdDlgPtr  dlg;
1535   ValNodePtr             vnp;
1536 
1537   dlg = (RnaTranscriptIdDlgPtr) userdata;
1538   if (dlg == NULL) return;
1539 
1540   if (dlg->far_id_grp != NULL)
1541   {
1542     vnp = DialogToPointer (dlg->product);
1543     if (vnp == NULL || vnp->data.ptrvalue == NULL) 
1544     {
1545       Enable (dlg->far_id_grp);
1546     }
1547     else 
1548     {
1549       Disable (dlg->far_id_grp);
1550     }
1551     vnp = ValNodeFree (vnp);
1552   }
1553 
1554   if (dlg->change_notify != NULL)
1555   {
1556     (dlg->change_notify) (dlg->change_userdata);
1557   }
1558 }
1559 
1560 static void ChangeTranscriptIDText (TexT t)
1561 {
1562   RnaTranscriptIdDlgPtr  dlg;
1563 
1564   dlg = (RnaTranscriptIdDlgPtr) GetObjectExtra (t);
1565   if (dlg == NULL) return;
1566 
1567   if (dlg->change_notify != NULL)
1568   {
1569     (dlg->change_notify) (dlg->change_userdata);
1570   }  
1571 }
1572 
1573 
1574 static void LocToTranscriptIDDialog (DialoG d, Pointer data)
1575 {
1576   RnaTranscriptIdDlgPtr  dlg;
1577   SeqLocPtr              slp;
1578   BioseqPtr              bsp;
1579   ValNode                vn;
1580   SeqIdPtr               sip;
1581   Char                   str [128];
1582 
1583   dlg = (RnaTranscriptIdDlgPtr) GetObjectExtra (d);
1584   if (dlg == NULL) return;
1585   slp = (SeqLocPtr) data;
1586 
1587   if (slp == NULL)
1588   {
1589     PointerToDialog (dlg->product, NULL);
1590     SafeSetTitle (dlg->far_id, "");
1591   }
1592   else
1593   {
1594     sip = SeqLocId (slp);
1595     bsp = BioseqFind (sip);
1596     if (bsp == NULL)
1597     {
1598       PointerToDialog (dlg->product, NULL);
1599       SeqIdWrite (sip, str, PRINTID_FASTA_LONG, sizeof (str));
1600       SafeSetTitle (dlg->far_id, str);
1601     }
1602     else
1603     {
1604       vn.choice = 0;
1605       vn.data.ptrvalue = sip;
1606       vn.next = NULL;
1607       PointerToDialog (dlg->product, &vn);
1608       SafeSetTitle (dlg->far_id, "");
1609     }    
1610   }
1611 }
1612 
1613 
1614 static Pointer TranscriptIDDialogToLoc (DialoG d)
1615 {
1616   RnaTranscriptIdDlgPtr  dlg;
1617   SeqLocPtr              slp = NULL;
1618   ValNodePtr             vnp;
1619   SeqIdPtr               sip = NULL;
1620   CharPtr                str;
1621 
1622   dlg = (RnaTranscriptIdDlgPtr) GetObjectExtra (d);
1623   if (dlg == NULL) return NULL;
1624 
1625   vnp = DialogToPointer (dlg->product);
1626   if (vnp == NULL || vnp->data.ptrvalue == NULL)
1627   {
1628     if (!TextHasNoText (dlg->far_id))
1629     {
1630       str = SaveStringFromText (dlg->far_id);
1631       sip = MakeSeqID (str);
1632       str = MemFree (str);
1633     }
1634   }
1635   else
1636   {
1637     sip = SeqIdDup (vnp->data.ptrvalue);
1638   }
1639   vnp = ValNodeFree (vnp);
1640   
1641   if (sip != NULL)
1642   {
1643     slp = ValNodeNew (NULL);
1644     slp->choice = SEQLOC_WHOLE;
1645     slp->data.ptrvalue = SeqIdStripLocus (sip);
1646   }
1647 
1648   return slp;
1649 }
1650 
1651 
1652 static DialoG CreateRNATranscriptIDDialog (GrouP h, Uint2 entityID, Boolean allow_far_id, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
1653 {
1654   GrouP                  p;
1655   RnaTranscriptIdDlgPtr  dlg;
1656 
1657   p = HiddenGroup (h, 3, 0, NULL);
1658   SetGroupSpacing (p, 10, 10);
1659 
1660   dlg = (RnaTranscriptIdDlgPtr) MemNew (sizeof (RnaTranscriptIDDlgData));
1661   if (dlg == NULL) return NULL;
1662 
1663   SetObjectExtra (p, dlg, StdCleanupExtraProc);
1664   dlg->dialog = (DialoG) p;
1665   dlg->todialog = LocToTranscriptIDDialog;
1666   dlg->fromdialog = TranscriptIDDialogToLoc;
1667 
1668   dlg->change_notify = change_notify;
1669   dlg->change_userdata = change_userdata;
1670 
1671   StaticPrompt (p, "Transcript Sequence ID", 0, popupMenuHeight, programFont, 'l');
1672   dlg->product = SequenceSelectionDialogEx (p, ChangeTranscriptIDSequenceSelection, dlg, FALSE, TRUE, TRUE, FALSE, entityID, SHORT_SELECTION_LIST);
1673   if (allow_far_id) 
1674   {
1675     dlg->far_id_grp = HiddenGroup (p, 2, 0, NULL);
1676     StaticPrompt (dlg->far_id_grp, "Far ID", 0, dialogTextHeight, programFont, 'l');
1677     dlg->far_id = DialogText (dlg->far_id_grp, "", 5, ChangeTranscriptIDText);
1678     SetObjectExtra (dlg->far_id, dlg, NULL);
1679   }
1680 
1681   return (DialoG) p;
1682 }
1683 
1684 
1685 extern SeqLocPtr PredictCodingRegion (BioseqPtr nuc, BioseqPtr prot, Int2 genCode)
1686 
1687 {
1688   BioseqPtr    bsp;
1689   SeqLocPtr    oldslp;
1690   SeqAnnotPtr  sap;
1691   SeqFeatPtr   sfp;
1692   SeqIdPtr     sip;
1693   SeqLocPtr    slp;
1694 
1695   if (nuc == NULL || prot == NULL) return NULL;
1696   if (nuc->length + 5 >= MAXALLOC) {
1697     Message (MSG_OK, "Nucleotide sequence is too large for coding region prediction.");
1698     return NULL;
1699   }
1700   slp = NULL;
1701   /*
1702   slp = FindSingleCodingInterval (nuc, prot, genCode);
1703   */
1704   if (slp == NULL) {
1705     sap = SuggestCodingRegion (nuc, prot, genCode);
1706     if (sap != NULL && sap->type == 1) {
1707       sfp = (SeqFeatPtr) sap->data;
1708       if (sfp != NULL && sfp->data.choice == SEQFEAT_CDREGION) {
1709         slp = sfp->location;
1710         sfp->location = NULL;
1711         sip = SeqLocId (slp);
1712         if (sip != NULL) {
1713           bsp = BioseqFind (sip);
1714           if (bsp != NULL) {
1715             if (bsp->repr == Seq_repr_seg) {
1716               oldslp = slp;
1717               slp = SegLocToParts (bsp, oldslp);
1718               FreeAllFuzz (slp);
1719               SeqLocFree (oldslp);
1720             }
1721           }
1722         }
1723       }
1724     }
1725     sap = SeqAnnotFree (sap);
1726   }
1727   StripLocusFromSeqLoc (slp);
1728   return slp;
1729 }
1730 
1731 static void DoPredictCdRegion (CdRgnFormPtr cfp)
1732 
1733 {
1734   Int2          code;
1735   CdRgnPagePtr  cpp;
1736   BioseqPtr     nucbsp;
1737   BioseqPtr     protbsp;
1738   SeqEntryPtr   psep;
1739   SeqEntryPtr   sep;
1740   SeqLocPtr     slp;
1741   Int2          val;
1742 
1743   if (cfp != NULL) {
1744     WatchCursor ();
1745     Update ();
1746     code = 0;
1747     cpp = (CdRgnPagePtr) GetObjectExtra (cfp->data);
1748     if (cpp != NULL) {
1749       val = gcIndexToId [GetValue (cpp->geneticCode)];
1750       if (val > 0 && val < NUM_GENETIC_CODES) {
1751         code = val;
1752       }
1753     }
1754     psep = SeqEntryNew ();
1755     if (psep != NULL) {
1756       protbsp = (BioseqPtr) DialogToPointer (cfp->protseq);
1757       psep->choice = 1;
1758       psep->data.ptrvalue = protbsp;
1759       SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) protbsp, psep);
1760       sep = GetBestTopParentForItemID (cfp->input_entityID,
1761                                        cfp->input_itemID,
1762                                        cfp->input_itemtype);
1763       /*
1764       sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
1765       */
1766       if (sep != NULL) {
1767         sep = FindNucSeqEntry (sep);
1768       }
1769       if (sep != NULL && sep->data.ptrvalue != NULL &&
1770           protbsp != NULL && protbsp->length > 0) {
1771         nucbsp = (BioseqPtr) sep->data.ptrvalue;
1772         slp = PredictCodingRegion (nucbsp, protbsp, code);
1773         if (slp != NULL && SeqLocStop (slp) > nucbsp->length - 1) {
1774           Message (MSG_ERROR, "Warning!  Nucleotide is not long enough for protein sequence!");
1775         }
1776         PointerToDialog (cfp->location, slp);
1777         if (slp != NULL) {
1778           cfp->locvisited = TRUE;
1779         }
1780         SeqLocFree (slp);
1781       }
1782       SeqEntryFree (psep);
1783     }
1784     ArrowCursor ();
1785     Update ();
1786   }
1787 }
1788 
1789 static void PredictCdRegion (ButtoN b)
1790 
1791 {
1792   CdRgnFormPtr  cfp;
1793 
1794   cfp = (CdRgnFormPtr) GetObjectExtra (b);
1795   DoPredictCdRegion (cfp);
1796 }
1797 
1798 static void DoTranslateProtein (CdRgnFormPtr cfp)
1799 
1800 {
1801   ByteStorePtr  bs;
1802   BioseqPtr     bsp;
1803   Char          ch;
1804   CharPtr       prot;
1805   CharPtr       ptr;
1806   SeqFeatPtr    sfp;
1807   Int4          star_at_end = 0;
1808 
1809   if (cfp != NULL) {
1810     sfp = SeqFeatNew ();
1811     if (sfp != NULL) {
1812       sfp->data.choice = SEQFEAT_CDREGION;
1813       sfp->data.value.ptrvalue = DialogToPointer (cfp->data);
1814       sfp->location = DialogToPointer (cfp->location);
1815       if (sfp->location != NULL) {
1816         bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
1817         if (bs != NULL) {
1818           prot = BSMerge (bs, NULL);
1819           bs = BSFree (bs);
1820           if (prot != NULL) {
1821             ptr = prot;
1822             ch = *ptr;
1823             while (ch != '\0') {
1824               *ptr = TO_UPPER (ch);
1825               if (ch == '*') {
1826                 star_at_end = 1;
1827               } else {
1828                 star_at_end = 0;
1829               }
1830               ptr++;
1831               ch = *ptr;
1832             }
1833             bs = BSNew (1000);
1834             if (bs != NULL) {
1835               ptr = prot;
1836               /*
1837               if (prot [0] == '-') {
1838                 ptr++;
1839               }
1840               */
1841               BSWrite (bs, (VoidPtr) ptr, (Int4) StringLen (ptr));
1842             }
1843           }
1844           bsp = BioseqNew ();
1845           if (bsp != NULL) {
1846             bsp->id = SeqIdParse ("lcl|CdRgnTransl");
1847             bsp->repr = Seq_repr_raw;
1848             bsp->mol = Seq_mol_aa;
1849             bsp->seq_data_type = Seq_code_ncbieaa;
1850             bsp->seq_data = (SeqDataPtr) bs;
1851             bsp->length = BSLen (bs);
1852             PointerToDialog (cfp->protseq, bsp);
1853             SetProteinLengthDisplay (cfp->protlen, bsp->length - star_at_end);
1854             bsp->seq_data = NULL;
1855             BioseqFree (bsp);
1856           }
1857           MemFree (prot);
1858         }
1859         BSFree (bs);
1860       }
1861     }
1862     SeqFeatFree (sfp);
1863   }
1864 }
1865 
1866 extern void CdRgnTranslateWithFrame (ForM f, Uint1 frame)
1867 
1868 {
1869   CdRgnFormPtr  cfp;
1870   CdRgnPagePtr  cpp;
1871 
1872   cfp = (CdRgnFormPtr) GetObjectExtra (f);
1873   if (cfp != NULL) {
1874     cpp = (CdRgnPagePtr) GetObjectExtra (cfp->data);
1875     if (cpp != NULL) {
1876       if (frame < 2) {
1877         SafeSetValue (cpp->frame, frame + 1);
1878       } else {
1879         SafeSetValue (cpp->frame, 0);
1880       }
1881     }
1882     DoTranslateProtein (cfp);
1883   }
1884 }
1885 
1886 static void TranslateProtein (ButtoN b)
1887 
1888 {
1889   CdRgnFormPtr  cfp;
1890 
1891   cfp = (CdRgnFormPtr) GetObjectExtra (b);
1892   if (cfp != NULL) {
1893     DoTranslateProtein (cfp);
1894   }
1895 }
1896 
1897 static void SetSynchProc (ButtoN b)
1898 
1899 {
1900   CdRgnFormPtr  cfp;
1901 
1902   cfp = (CdRgnFormPtr) GetObjectExtra (b);
1903   if (cfp != NULL) {
1904     cfp->autoUpdatePartials = GetStatus (b);
1905   }
1906 }
1907 
1908 static void SetRetransProc (ButtoN b)
1909 
1910 {
1911   CdRgnFormPtr  cfp;
1912 
1913   cfp = (CdRgnFormPtr) GetObjectExtra (b);
1914   if (cfp != NULL) {
1915     cfp->autoRetranslate = GetStatus (b);
1916   }
1917 }
1918 
1919 EnumFieldAssocPtr codebreak_alists [] = {
1920   NULL, NULL
1921 };
1922 
1923 Uint2 codebreak_types [] = {
1924   TAGLIST_TEXT, TAGLIST_POPUP
1925 };
1926 
1927 Uint2 codebreak_widths [] = {
1928   5, 0
1929 };
1930 
1931 static void CreateCodeBreakAlist (CdRgnPagePtr cpp)
1932 
1933 {
1934   Char             ch;
1935   Int2             count;
1936   Uint1            first;
1937   Uint1            i;
1938   Int2             j;
1939   Char             item [77];
1940   Uint1            last;
1941   SeqCodeTablePtr  sctp;
1942   CharPtr          str;
1943 
1944   if (cpp != NULL) {
1945     sctp = SeqCodeTableFind (Seq_code_ncbieaa);
1946     first = FirstResidueInCode (sctp);
1947     last = LastResidueInCode (sctp);
1948     count = last - 65 + 4;
1949     cpp->alist = MemNew (sizeof (EnumFieldAssoc) * (size_t) count);
1950     cpp->count = count;
1951     if (cpp->alist != NULL) {
1952       j = 0;
1953       cpp->alist [j].name = StringSave ("     ");
1954       cpp->alist [j].value = (UIEnum) 0;
1955       j++;
1956       for (i = 65; i <= last; i++) {
1957         /*
1958         if (i == 74 || i == 79) {
1959           continue;
1960         }
1961         */
1962         ch = GetSymbolForResidue (sctp, i);
1963         str = (CharPtr) GetNameForResidue (sctp, i);
1964         cpp->alist [j].name = StringSave (str);
1965         cpp->alist [j].value = (UIEnum) ch;
1966         sprintf (item, "%c    %s", ch, str);
1967         j++;
1968       }
1969       i = 42;
1970       ch = GetSymbolForResidue (sctp, i);
1971       str = (CharPtr) GetNameForResidue (sctp, i);
1972       cpp->alist [j].name = StringSave (str);
1973       cpp->alist [j].value = (UIEnum) ch;
1974       sprintf (item, "%c    %s", ch, str);
1975       j++;
1976       cpp->alist [j].name = NULL;
1977       cpp->alist [j].value = (UIEnum) 0;
1978     }
1979     cpp->alists [0] = NULL;
1980     cpp->alists [1] = cpp->alist;
1981   }
1982 }
1983 
1984 static void CodeBreakPtrToCodeBreakDialog (DialoG d, Pointer data)
1985 
1986 {
1987   Uint1           aa;
1988   BioseqPtr       bsp;
1989   ValNodePtr      head;
1990   Int2            j;
1991   CodeBreakPtr    list;
1992   Int4            pos;
1993   SeqIdPtr        sip;
1994   SeqMapTablePtr  smtp;
1995   Char            str [64];
1996   TagListPtr      tlp;
1997   Char            tmp [32];
1998   ValNodePtr      vnp;
1999 
2000   tlp = (TagListPtr) GetObjectExtra (d);
2001   list = (CodeBreakPtr) data;
2002   if (tlp != NULL) {
2003     head = NULL;
2004     while (list != NULL) {
2005       if (list->loc != NULL) {
2006         vnp = ValNodeNew (head);
2007         if (head == NULL) {
2008           head = vnp;
2009         }
2010         if (vnp != NULL) {
2011           pos = 0;
2012           sip = SeqLocId (list->loc);
2013           if (sip != NULL) {
2014             bsp = BioseqFind (sip);
2015             if (bsp != NULL) {
2016               pos = GetOffsetInBioseq (list->loc, bsp, SEQLOC_START);
2017               aa = 0;
2018               switch (list->aa.choice) {
2019                 case 1 :
2020                   aa = (Uint1) list->aa.value.intvalue;
2021                   break;
2022                 case 2 :
2023                   smtp = SeqMapTableFind (Seq_code_ncbieaa, Seq_code_ncbi8aa);
2024                   if (smtp != NULL) {
2025                     aa = SeqMapTableConvert (smtp, (Uint1) list->aa.value.intvalue);
2026                   }
2027                   break;
2028                 case 3 :
2029                   smtp = SeqMapTableFind (Seq_code_ncbieaa, Seq_code_ncbistdaa);
2030                   if (smtp != NULL) {
2031                     aa = SeqMapTableConvert (smtp, (Uint1) list->aa.value.intvalue);
2032                   }
2033                   break;
2034                 default :
2035                   aa = (Uint1) list->aa.value.intvalue;
2036                   break;
2037               }
2038               sprintf (tmp, "%ld", (long) (pos + 1));
2039               StringCpy (str, tmp);
2040               StringCat (str, "\t");
2041               sprintf (tmp, "%d", (int) list->aa.value.intvalue);
2042               StringCat (str, tmp);
2043               StringCat (str, "\n");
2044               vnp->data.ptrvalue = StringSave (str);
2045             }
2046           }
2047         }
2048       }
2049       list = list->next;
2050     }
2051     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
2052     tlp->vnp = head;
2053     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
2054     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
2055     }
2056     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
2057     CorrectBarMax (tlp->bar, tlp->max);
2058     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
2059   }
2060 }
2061 
2062 static Pointer CodeBreakDialogToCodeBreakPtr (DialoG d)
2063 
2064 {
2065   Uint1         aa;
2066   CodeBreakPtr  cbp;
2067   CodeBreakPtr  cbplast;
2068   Char          ch;
2069   CodeBreakPtr  head;
2070   Int2          j;
2071   Int2          len;
2072   Boolean       okay;
2073   SeqLocPtr     slp;
2074   SeqPntPtr     spntp;
2075   CharPtr       str;
2076   TagListPtr    tlp;
2077   CharPtr       tmp;
2078   int           val;
2079   ValNodePtr    vnp;
2080 
2081   head = NULL;
2082   tlp = (TagListPtr) GetObjectExtra (d);
2083   if (tlp != NULL && tlp->vnp != NULL) {
2084     cbp = NULL;
2085     cbplast = NULL;
2086     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
2087       str = (CharPtr) vnp->data.ptrvalue;
2088       okay = FALSE;
2089       len = StringLen (str);
2090       for (j = 0; j < len; j++) {
2091         ch = str [j];
2092         if (ch != ' ' && ch != '\t' && ch != '\n') {
2093           okay = TRUE;
2094         }
2095       }
2096       if (okay) {
2097         tmp = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
2098         if (tmp != NULL && sscanf (tmp, "%d", &val) == 1 && val != 0) {
2099           aa = (Uint1) val;
2100           MemFree (tmp);
2101           tmp = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
2102           if (tmp != NULL && sscanf (tmp, "%d", &val) == 1 && val != 0) {
2103             cbp = CodeBreakNew ();
2104             if (cbplast == NULL) {
2105               head = cbp;
2106             } else {
2107               cbplast->next = cbp;
2108             }
2109             cbplast = cbp;
2110             if (cbp != NULL) {
2111               if (globalid != NULL) {
2112                 spntp = SeqPntNew ();
2113                 slp = ValNodeNew (NULL);
2114                 slp->choice = SEQLOC_PNT;
2115                 slp->data.ptrvalue = (Pointer) spntp;
2116                 spntp->point = (Int4) (val - 1);
2117                 spntp->id = SeqIdStripLocus (SeqIdDup (globalid));
2118                 cbp->loc = slp;
2119               }
2120               cbp->aa.value.intvalue = aa;
2121               cbp->aa.choice = 1;
2122             }
2123           } else {
2124             MemFree (tmp);
2125           }
2126         } else {
2127           MemFree (tmp);
2128         }
2129       }
2130     }
2131   }
2132   return (Pointer) head;
2133 }
2134 
2135 static CharPtr cdsToMiscFeatWarning =
2136 "You are indicating that this CDS is non-functional.\n\
2137 Database policy is to convert this into a misc_feature,\n\
2138 and to remove any protein product attached to the CDS.\n\
2139 If this is the case, you should add some explanatory\n\
2140 text as a comment before pressing the Accept button.\n\
2141 Are you sure you want to check this box?";
2142 
2143 static void ConvMiscFeatWarn (ButtoN b)
2144 
2145 {
2146   MsgAnswer     ans;
2147   CdRgnFormPtr  cfp;
2148 
2149   cfp = (CdRgnFormPtr) GetObjectExtra (b);
2150   if (cfp == NULL) return;
2151   if (GetStatus (b)) {
2152     ans = Message (MSG_YN, "%s", cdsToMiscFeatWarning);
2153     if (ans == ANS_NO) {
2154       SetStatus (b, FALSE);
2155     }
2156   }
2157 }
2158 
2159 static Int4 AccessionToGi (CharPtr string)
2160 {
2161    /*
2162    CharPtr str;
2163    LinkSetPtr lsp;
2164    Int4 gi;
2165 
2166    str = MemNew (StringLen (string) + 10);
2167    sprintf (str, "\"%s\" [ACCN]", string);
2168    lsp = EntrezTLEvalString (str, TYP_NT, -1, NULL, NULL);
2169    MemFree (str);
2170    if (lsp == NULL) return 0;
2171    if (lsp->num <= 0) {
2172        LinkSetFree (lsp);
2173        return 0;
2174    }
2175    gi = lsp->uids [0];
2176    LinkSetFree (lsp);
2177    return gi;
2178    */
2179    Int4      gi;
2180    SeqIdPtr  sip;
2181 
2182    sip = SeqIdFromAccessionDotVersion (string);
2183    if (sip == NULL) return 0;
2184    gi = GetGIForSeqId (sip);
2185    SeqIdFree (sip);
2186    return gi;
2187 }
2188 
2189 static void SetGeneAndProtFields (CdRgnFormPtr cfp, CharPtr title);
2190 
2191 static BioseqPtr GetProteinFromSep (SeqEntryPtr sep)
2192 {
2193   BioseqPtr query_bsp;
2194 
2195   query_bsp = NULL;
2196   SeqEntryExplore(sep, &query_bsp, FindProt);
2197   return query_bsp;
2198 }
2199 
2200 typedef struct proteinimportformdata {
2201   CdRgnFormPtr cfp;
2202   WindoW       w;
2203   TexT         accession;
2204   GrouP        accntype;
2205   ButtoN       DownloadProtein;
2206 } ProteinImportFormData, PNTR ProteinImportFormPtr;
2207 
2208 static void AddProteinToCDSDialog (
2209   BioseqPtr bsp,
2210   CdRgnFormPtr  cfp
2211 )
2212 {
2213   ValNodePtr vnp;
2214   CharPtr    vnpstr;
2215   SeqLocPtr  slp;
2216   Char          str [128];
2217 
2218   PointerToDialog (cfp->protseq, bsp);
2219   SetProteinLengthDisplay (cfp->protlen, bsp->length);
2220   SeqIdWrite (bsp->id, str, PRINTID_REPORT, sizeof (str));
2221   SafeSetTitle (cfp->protSeqIdTxt, str);
2222   if (bsp->descr != NULL) {
2223     vnp = ValNodeFindNext (bsp->descr, NULL, Seq_descr_title);
2224     if (vnp != NULL && vnp->data.ptrvalue != NULL) {
2225       vnpstr = (CharPtr) vnp->data.ptrvalue;
2226       SetGeneAndProtFields (cfp, vnpstr);
2227     }
2228   }
2229   slp = DialogToPointer (cfp->location);
2230   if (slp == NULL || (! cfp->locvisited)) {
2231     DoPredictCdRegion (cfp);
2232   }
2233   SeqLocFree (slp);
2234 }
2235 
2236 static void DownloadProteinFromEntrez (ButtoN b)
2237 {
2238   SeqEntryPtr   sep = NULL;
2239   Int4          uid;
2240   BioseqPtr     bsp;
2241   CdRgnFormPtr  cfp;
2242   Char          str [128];
2243   ProteinImportFormPtr pif;
2244  
2245   pif = (ProteinImportFormPtr) GetObjectExtra (b);
2246   if (pif == NULL) return; 
2247   cfp = pif->cfp;
2248   if (cfp == NULL) return;
2249   GetTitle (pif->accession, str, sizeof (str));
2250   if (StringHasNoText (str))
2251   {
2252     return;
2253   }
2254   WatchCursor ();
2255   if (GetValue (pif->accntype) == 1) {
2256     uid = AccessionToGi (str);
2257   } else {
2258     if (! StrToLong (str, &uid)) {
2259      uid = 0;
2260     }
2261   }
2262 
2263   if (uid > 0) {
2264     sep = PubSeqSynchronousQuery (uid, 0, -1);
2265     if (sep == NULL) {
2266       Message (MSG_OK, "Unable to find this record in the database.");
2267       return;
2268     }
2269     if (IS_Bioseq (sep)) {
2270     } else if (IS_Bioseq_set (sep)) {
2271     } else {
2272       Message (MSG_OK, "Unable to find this record in the database.");
2273       return;
2274     }
2275   }
2276   bsp = GetProteinFromSep (sep);
2277   if (bsp == NULL)
2278   {
2279     Message (MSG_ERROR, "No protein in record!");
2280   }
2281   else
2282   {
2283     AddProteinToCDSDialog (bsp, cfp);
2284   }
2285   SeqEntryFree (sep);
2286   Remove (pif->w);
2287   ArrowCursor ();
2288   Update ();
2289 }
2290 
2291 static void FetchTextProc (TexT t)
2292 
2293 {
2294   Boolean       alldigits;
2295   Char          ch;
2296   ProteinImportFormPtr  pif;
2297   CharPtr       ptr;
2298   Char          str [32];
2299 
2300   pif = (ProteinImportFormPtr) GetObjectExtra (t);
2301   if (pif == NULL) return;
2302   GetTitle (t, str, sizeof (str));
2303   if (StringHasNoText (str)) {
2304     SafeDisable (pif->DownloadProtein);
2305   } else {
2306     SafeEnable (pif->DownloadProtein);
2307     TrimSpacesAroundString (str);
2308     alldigits = TRUE;
2309     ptr = str;
2310     ch = *ptr;
2311     while (ch != '\0') {
2312       if (! IS_DIGIT (ch)) {
2313         alldigits = FALSE;
2314       }
2315       ptr++;
2316       ch = *ptr;
2317     }
2318     if (alldigits) {
2319       SafeSetValue (pif->accntype, 2);
2320     } else {
2321       SafeSetValue (pif->accntype, 1);
2322     }
2323   }
2324 }
2325 
2326 static void LoadFASTAProteinFromFile (ButtoN b)
2327 {
2328   CdRgnFormPtr  cfp;
2329   CharPtr       extension;
2330   FILE *        fp;
2331   SeqEntryPtr   sep;
2332   BioseqPtr     bsp;
2333   Char          path [PATH_MAX];
2334   ProteinImportFormPtr pif;
2335   Char          tmp [128];
2336  
2337   pif = (ProteinImportFormPtr) GetObjectExtra (b);
2338   if (pif == NULL) return; 
2339   cfp = pif->cfp;
2340   if (cfp == NULL) return;
2341 
2342   path [0] = 0;
2343   extension = GetAppProperty ("FastaProtExtension");
2344   if (GetInputFileName (path, sizeof (path), extension, "TEXT"))
2345   {
2346     fp = FileOpen (path, "r");
2347     if (fp != NULL) {
2348       sep = FastaToSeqEntry (fp, FALSE);
2349       if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) {
2350         bsp = (BioseqPtr) sep->data.ptrvalue;
2351         if (BioseqFind (bsp->id) != bsp)
2352         {
2353           SeqIdWrite (bsp->id, tmp, PRINTID_REPORT, sizeof (tmp));
2354           bsp->id = SeqIdFree (bsp->id);
2355           bsp->id = MakeUniqueSeqID (tmp);
2356         }
2357         AddProteinToCDSDialog (bsp, cfp);
2358       }
2359       SeqEntryFree (sep);
2360     }
2361     FileClose (fp);
2362   }
2363   Remove (pif->w);
2364 }
2365 
2366 static void ShowImportProteinDialog ( CdRgnFormPtr  cfp)
2367 {
2368   WindoW w;
2369   GrouP  c, f, g, h;
2370   ButtoN b;
2371   ProteinImportFormPtr pif;
2372 
2373   pif = (ProteinImportFormPtr) MemNew ( sizeof (ProteinImportFormData));
2374   if (pif == NULL) return;
2375   pif->cfp = cfp;
2376   w = FixedWindow (-50, -33, -10, -10, "Import Protein", StdCloseWindowProc);
2377   pif->w = w;
2378   SetObjectExtra (w, pif, NULL);
2379 
2380   h = HiddenGroup (w, -1, 0, NULL);
2381   SetGroupSpacing (h, 10, 10);
2382 
2383   g = HiddenGroup (h, 4, 0, NULL);
2384 
2385   pif->accntype = HiddenGroup (g, 4, 0, NULL);
2386   RadioButton (pif->accntype, "Accession");
2387   RadioButton (pif->accntype, "GI");
2388   SetValue (pif->accntype, 1);
2389   pif->accession = DialogText (g, "", 6, FetchTextProc);
2390   SetObjectExtra (pif->accession, pif, NULL);
2391   pif->DownloadProtein = PushButton (g, "Download Protein From Entrez",
2392                                      DownloadProteinFromEntrez);
2393   SetObjectExtra (pif->DownloadProtein, pif, NULL);
2394   Disable (pif->DownloadProtein);
2395 
2396   f = HiddenGroup (h, 4, 0, NULL);
2397   b = PushButton (f, "Load FASTA Protein From File", LoadFASTAProteinFromFile);
2398   SetObjectExtra (b, pif, NULL);
2399 
2400   c = HiddenGroup (w, 2, 0, NULL);
2401   PushButton (c, "Cancel", StdCancelButtonProc);
2402   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) f, (HANDLE) c, NULL);
2403   RealizeWindow (w);
2404   Show (w);
2405   Update ();
2406 
2407 }
2408 
2409 static void SwitchToProtFeatEd (ButtoN b)
2410 
2411 {
2412   CdRgnFormPtr  cfp;
2413   Int2          handled;
2414 
2415   cfp = (CdRgnFormPtr) GetObjectExtra (b);
2416   if (cfp != NULL && cfp->protFound) {
2417     WatchCursor ();
2418     Update ();
2419     handled = GatherProcLaunch (OMPROC_EDIT, FALSE, cfp->protEntityID, cfp->protItemID,
2420                                 cfp->protItemtype, 0, 0, cfp->protItemtype, 0);
2421     ArrowCursor ();
2422     Update ();
2423     if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
2424       Message (MSG_ERROR, "Unable to launch editor on protein feature.");
2425     }
2426     else
2427     {
2428       SendMessageToForm (cfp->form, VIB_MSG_CLOSE);
2429       Update ();
2430     }
2431   }
2432 }
2433 
2434 
2435 static CharPtr GetProteinString (CdRgnFormPtr cfp, SeqLocPtr location)
2436 {
2437   SeqFeatPtr   sfp;
2438   ByteStorePtr bs;
2439   CharPtr      prot = NULL;
2440 
2441   if (cfp == NULL || location == NULL) return NULL;
2442   sfp = SeqFeatNew ();
2443   if (sfp == NULL) return NULL;
2444 
2445   sfp->data.choice = SEQFEAT_CDREGION;
2446   sfp->data.value.ptrvalue = DialogToPointer (cfp->data);
2447   sfp->location = location;
2448   bs = ProteinFromCdRegionEx (sfp, TRUE, FALSE);
2449   if (bs != NULL) {
2450     prot = BSMerge (bs, NULL);
2451     bs = BSFree (bs);
2452   }
2453   /* IMPORTANT - do not free the location that was passed in */
2454   sfp->location = NULL;
2455   SeqFeatFree (sfp);
2456   return prot;
2457 }
2458 
2459 
2460 extern SeqLocPtr TruncateLocation (SeqLocPtr head, Int4 len)
2461 {
2462     SeqLocPtr slp = NULL;
2463     SeqIdPtr sip;
2464     Int4 from = 0, to = 0;
2465     Boolean changed = FALSE;
2466     Int4       loc_len = 0;
2467     Int4       cum_len = 0;
2468     SeqLocPtr  del_slp;
2469     ValNodePtr del_slp_list = NULL, vnp;
2470     Uint1      strand;
2471 
2472     if (head == NULL || len < 1)
2473         return head;
2474 
2475   slp = SeqLocFindNext (head, slp);
2476   while (slp != NULL)
2477   {
2478     if (cum_len >= len)
2479     {
2480       del_slp = AsnIoMemCopy(slp,
2481                     (AsnReadFunc) SeqLocAsnRead, (AsnWriteFunc) SeqLocAsnWrite);
2482       ValNodeAddPointer (&del_slp_list, 0, del_slp);
2483     }
2484     else
2485     {
2486           sip = SeqLocId(slp);
2487           from = SeqLocStart(slp);
2488           to = SeqLocStop(slp);
2489           loc_len = (to - from + 1);
2490       cum_len += loc_len;
2491       if (cum_len > len)
2492       {
2493         strand = SeqLocStrand (slp);
2494         /* remove part of this location */
2495         if (strand == Seq_strand_minus)
2496         {
2497           to = cum_len - len + from - 1;
2498         }
2499         else
2500         {
2501           from = to - (cum_len - len) + 1;
2502         }
2503         del_slp = SeqLocIntNew (from, to, strand, sip);
2504         ValNodeAddPointer (&del_slp_list, 0, del_slp);
2505       }
2506     }
2507         slp = SeqLocFindNext (head, slp);
2508   }
2509   
2510   for (vnp = del_slp_list; vnp != NULL; vnp = vnp->next)
2511   {
2512     slp = (SeqLocPtr) vnp->data.ptrvalue;
2513     if (slp == NULL) continue;
2514         sip = SeqLocId(slp);
2515         from = SeqLocStart(slp);
2516         to = SeqLocStop(slp);
2517         head = SeqLocDelete(head, sip, from, to, FALSE, &changed);    
2518   }
2519   
2520     return head;
2521 }
2522 
2523 
2524 static Boolean LengthenLocation (SeqLocPtr head, Int4 len)
2525 {
2526     SeqLocPtr slp = NULL, last_slp = NULL;
2527   SeqIntPtr sintp;
2528   SeqPntPtr spp;
2529   Int4        orig_len, len_diff;
2530   Boolean     rval = FALSE;
2531   BioseqPtr   bsp;
2532 
2533     if (head == NULL || len < 1)
2534         return FALSE;
2535 
2536   orig_len = SeqLocLen (head);
2537   len_diff = len - orig_len;
2538   if (len_diff <= 0) return FALSE;
2539 
2540   slp = SeqLocFindNext (head, slp);
2541   while (slp != NULL)
2542   {
2543     last_slp = slp;
2544     slp = SeqLocFindNext (head, slp);
2545   }
2546 
2547   if (last_slp != NULL && last_slp->choice == SEQLOC_INT) {
2548     sintp = (SeqIntPtr) last_slp->data.ptrvalue;
2549     if (sintp->strand == Seq_strand_minus) {
2550       if (sintp->from - len_diff >= 0) {
2551         sintp->from -= len_diff;
2552         rval = TRUE;
2553       }
2554     } else {
2555       bsp = BioseqFind (sintp->id);
2556       if (bsp != NULL && sintp->to + len_diff < bsp->length) {
2557         sintp->to += len_diff;
2558         rval = TRUE;
2559       }
2560     }      
2561   } else if (last_slp != NULL && last_slp->choice == SEQLOC_PNT) {
2562     spp = (SeqPntPtr) last_slp->data.ptrvalue;
2563     rval = TRUE;
2564     if (spp->strand == Seq_strand_minus) {
2565       if (spp->point - len_diff < 0) {
2566         rval = FALSE;
2567       }
2568     } else {
2569       bsp = BioseqFind (spp->id);
2570       if (bsp == NULL || spp->point + len_diff >= bsp->length) {
2571         rval = FALSE;
2572       }
2573     }
2574     if (rval) {
2575       sintp = SeqIntNew ();
2576       sintp->id = SeqIdDup (spp->id);
2577       sintp->strand = spp->strand;
2578       sintp->if_from = AsnIoMemCopy (spp->fuzz, (AsnReadFunc) IntFuzzAsnRead, (AsnWriteFunc) IntFuzzAsnWrite);
2579       sintp->if_from = AsnIoMemCopy (spp->fuzz, (AsnReadFunc) IntFuzzAsnRead, (AsnWriteFunc) IntFuzzAsnWrite);
2580       if (sintp->strand == Seq_strand_minus) {
2581         sintp->from = spp->point - len_diff;
2582         sintp->to = spp->point;
2583       } else {
2584         sintp->from = spp->point;
2585         sintp->to = spp->point + len_diff;
2586       }
2587       spp = SeqPntFree (spp);
2588       last_slp->data.ptrvalue = sintp;
2589       last_slp->choice = SEQLOC_INT;
2590     }
2591   }
2592   
2593   return rval;
2594 }
2595 
2596 
2597 static void AdjustForStopCodon (ButtoN b)
2598 
2599 {
2600   CdRgnFormPtr  cfp;
2601   SeqLocPtr     orig_slp;
2602   BioseqPtr     nucBsp;
2603   Boolean       partial5, partial3;
2604   Uint1         strand;
2605   CharPtr       prot, cp;
2606   Int4          desired_cds_len, loc_len, max_len;
2607   CdRegionPtr   crp;
2608   Uint1         frame = 0;
2609 
2610   cfp = (CdRgnFormPtr) GetObjectExtra (b);
2611   if (cfp == NULL) {
2612     return;
2613   }
2614 
2615   orig_slp = DialogToPointer (cfp->location);
2616   if (orig_slp == NULL) {
2617     Message (MSG_ERROR, "No location to adjust!");
2618     return;
2619   }
2620 
2621   CheckSeqLocForPartial (orig_slp, &partial5, &partial3);
2622 
2623   nucBsp = GetBioseqGivenSeqLoc (orig_slp, cfp->input_entityID);
2624   if (nucBsp == NULL) {
2625     Message (MSG_ERROR, "Unable to find Bioseq for coding region location");
2626     orig_slp = SeqLocFree (orig_slp);
2627     return;
2628   }
2629 
2630   crp = DialogToPointer (cfp->data);
2631   if (crp != NULL) {
2632     frame = crp->frame;
2633     if (frame > 0) {
2634       frame--;
2635     }
2636     crp = CdRegionFree (crp);
2637   }
2638 
2639   prot = GetProteinString (cfp, orig_slp);
2640   if (StringHasNoText (prot)) {
2641     Message (MSG_ERROR, "Translation failed");
2642     prot = MemFree (prot);
2643     orig_slp = SeqLocFree (orig_slp);
2644     return;
2645   } 
2646 
2647   cp = StringChr (prot, '*');
2648 
2649   if (cp == NULL) {
2650     /* lengthen coding region, look for stop codon */
2651     strand = SeqLocStrand (orig_slp);
2652     loc_len = SeqLocLen (orig_slp);
2653     if (strand == Seq_strand_minus) {
2654       max_len = loc_len + SeqLocStart (orig_slp);
2655     } else {
2656       max_len = loc_len + nucBsp->length - SeqLocStop (orig_slp) - 1;
2657     }
2658     
2659     if (LengthenLocation (orig_slp, max_len)) {
2660       prot = MemFree (prot);
2661       prot = GetProteinString (cfp, orig_slp);
2662       cp = StringChr (prot, '*');
2663       if (cp == NULL) {
2664         if (ANS_YES == Message (MSG_YN, "No stop codon found - extend to full length of sequence (and make partial)?")) {
2665           SetSeqLocPartial (orig_slp, partial5, TRUE);
2666           PointerToDialog (cfp->location, orig_slp);
2667           DoTranslateProtein (cfp);
2668         }
2669         prot = MemFree (prot);
2670         orig_slp = SeqLocFree (orig_slp);
2671         return;
2672       }
2673     } else {
2674       Message (MSG_ERROR, "Unable to lengthen location!");
2675       prot = MemFree (prot);
2676       orig_slp = SeqLocFree (orig_slp);
2677       return;
2678     }
2679   }
2680 
2681   desired_cds_len = ((cp - prot) + 1) * 3;
2682   if (frame > 0) {
2683     desired_cds_len += frame;
2684   }
2685     
2686   loc_len = SeqLocLen (orig_slp);
2687   if (desired_cds_len < loc_len) {
2688     /* truncate to correct length */
2689     orig_slp = TruncateLocation (orig_slp, desired_cds_len);
2690   }
2691   SetSeqLocPartial (orig_slp, partial5, FALSE);
2692 
2693   PointerToDialog (cfp->location, orig_slp);
2694   DoTranslateProtein (cfp);
2695   prot = MemFree (prot);
2696   orig_slp = SeqLocFree (orig_slp);
2697 }
2698 
2699 
2700 static SeqEntryPtr GetSeqEntryForLocation (SeqLocPtr slp, Uint2 entityID)
2701 {
2702   BioseqPtr bsp;
2703 
2704   if (slp == NULL) 
2705   {
2706     return GetTopSeqEntryForEntityID (entityID);
2707   }
2708 
2709   bsp = BioseqFindFromSeqLoc (slp);
2710   if (bsp == NULL)
2711   {
2712     return GetTopSeqEntryForEntityID (entityID);
2713   }
2714 
2715   return GetBestTopParentForData (entityID, bsp);   
2716 }
2717 
2718 
2719 static void SetCdRegionPageGeneticCode (DialoG d)
2720 {
2721   CdRgnPagePtr  cpp;
2722   SeqLocPtr     slp;
2723   Int2          genCode;
2724 
2725   cpp = (CdRgnPagePtr) GetObjectExtra (d);
2726   if (cpp != NULL) {
2727     slp = DialogToPointer (cpp->cfp->location);
2728     genCode = SeqEntryToGeneticCode (GetSeqEntryForLocation (slp, cpp->cfp->input_entityID), NULL, NULL, 0);
2729     slp = SeqLocFree (slp);
2730     SetValue (cpp->geneticCode, gcIdToIndex [genCode]);
2731   }
2732 }
2733 
2734 
2735 static DialoG CreateCdRgnDialog (GrouP h, CharPtr title, Int2 genCode,
2736                                  SeqFeatPtr sfp, CdRgnFormPtr cfp)
2737 
2738 {
2739   ButtoN        b;
2740   GrouP         c;
2741   CdRgnPagePtr  cpp;
2742   GrouP         f;
2743   GrouP         g;
2744   Boolean       internalVersion;
2745   GrouP         j;
2746   GrouP         k;
2747   GrouP         m;
2748   GrouP         n;
2749   GrouP         p;
2750   PrompT        p2;
2751   GrouP         q;
2752   GrouP         s;
2753   DialoG        tbs;
2754   TagListPtr    tlp;
2755   GrouP         v;
2756   GrouP         x;
2757   GrouP         y;
2758   GrouP         z;
2759 
2760   p = HiddenGroup (h, 1, 0, NULL);
2761   SetGroupSpacing (p, 10, 10);
2762 
2763   cpp = (CdRgnPagePtr) MemNew (sizeof (CdRgnPage));
2764   if (cpp != NULL) {
2765 
2766     SetObjectExtra (p, cpp, CleanupCdRgnPage);
2767     cpp->dialog = (DialoG) p;
2768     cpp->todialog = CdRegionPtrToCdRgnPage;
2769     cpp->fromdialog = CdRgnPageToCdRegionPtr;
2770     cpp->testdialog = NULL;
2771 
2772     if (title != NULL && title [0] != '\0') {
2773       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
2774     } else {
2775       s = HiddenGroup (p, 0, -2, NULL);
2776     }
2777     m = HiddenGroup (s, -1, 0, NULL);
2778     SetGroupSpacing (m, 10, 10);
2779 
2780     cpp->cfp = cfp;
2781     tbs = CreateFolderTabs (m, cdRgnTabs, 0, 0, 0,
2782                             PROGRAM_FOLDER_TAB,
2783                             ChangeCdRgnSubPage, (Pointer) cpp);
2784     cpp->currentPage = 0;
2785     k = HiddenGroup (m, 0, 0, NULL);
2786 
2787     j = HiddenGroup (k, -1, 0, NULL);
2788     SetGroupSpacing (j, 10, 10);
2789     n = HiddenGroup (j, 0, 0, NULL);
2790 
2791     cpp->cdRgnGrp [0] = HiddenGroup (k, -1, 0, NULL);
2792     g = HiddenGroup (cpp->cdRgnGrp [0], -1, 0, NULL);
2793 
2794     y = HiddenGroup (g, 0, -2, NULL);
2795     StaticPrompt (y, "Genetic Code", 0, popupMenuHeight, programFont, 'l');
2796     StaticPrompt (y, "Reading Frame", 0, popupMenuHeight, programFont, 'l');
2797     cpp->geneticCode = PopupList (y, TRUE, NULL);
2798     PopulateGeneticCodePopup (cpp->geneticCode);
2799     SetValue (cpp->geneticCode, gcIdToIndex [genCode]);
2800     v = HiddenGroup (y, 3, 0, NULL);
2801     cpp->frame = PopupList (v, TRUE, NULL);
2802     PopupItem (cpp->frame, " ");
2803     PopupItem (cpp->frame, "One");
2804     PopupItem (cpp->frame, "Two");
2805     PopupItem (cpp->frame, "Three");
2806     SetValue (cpp->frame, 1);
2807     StaticPrompt (v, " Protein Length ", 0, stdLineHeight, programFont, 'l');
2808     cfp->protlen = StaticPrompt (v, "          ", 0, stdLineHeight, systemFont, 'l');
2809 
2810     x = HiddenGroup (g, -1, 0, NULL);
2811     f = HiddenGroup (x, 6, 0, NULL);
2812     cfp->product = CreateProteinOrMRNAProductDialog (f, NULL, "Protein Product", FALSE, cfp->sep, cfp, NULL, (BaseFormPtr) cfp);
2813     cfp->protSeqIdGrp = HiddenGroup (f, -2, 0, NULL);
2814     StaticPrompt (cfp->protSeqIdGrp, "SeqID", 0, dialogTextHeight, programFont, 'l');
2815     cfp->protSeqIdTxt = DialogText (cfp->protSeqIdGrp, "", 6, NULL);
2816     cfp->forceNear = CheckBox (cfp->protSeqIdGrp, "Force Near, Create Product", NULL);
2817 
2818     cfp->protseq = CreateBioseqRawDialog (x, NULL, Seq_mol_aa, cfp);
2819     cfp->usethisbioseq = NULL;
2820 
2821     c = HiddenGroup (g, 3, 0, NULL);
2822     b = PushButton (c, "Predict Interval", PredictCdRegion);
2823     SetObjectExtra (b, cfp, NULL);
2824     b = PushButton (c, "Translate Product", TranslateProtein);
2825     SetObjectExtra (b, cfp, NULL);
2826     cfp->edSeqBtn = PushButton (c, "Edit Protein Sequence", LaunchProtSeqEd);
2827     SetObjectExtra (cfp->edSeqBtn, cfp, NULL);
2828     Disable (cfp->edSeqBtn);
2829     
2830     AlignObjects (ALIGN_LEFT, (HANDLE) f, (HANDLE) cfp->protseq, NULL);
2831     
2832     /* add switch to protein button only if indexer version */
2833     if (GetAppProperty ("InternalNcbiSequin") != NULL)
2834     {
2835       cfp->edProtBtn2 = PushButton (c, "Switch to Protein Feature Editor", SwitchToProtFeatEd);
2836       SetObjectExtra (cfp->edProtBtn2, cfp, NULL);
2837       Disable (cfp->edProtBtn2);      
2838     }
2839     b = PushButton (c, "Adjust for Stop Codon", AdjustForStopCodon);
2840     SetObjectExtra (b, cfp, NULL);
2841 
2842     AlignObjects (ALIGN_CENTER, (HANDLE) x, (HANDLE) c, (HANDLE) y, NULL);
2843 
2844     cpp->cdRgnGrp [1] = HiddenGroup (n, -1, 0, NULL);
2845     f = HiddenGroup (cpp->cdRgnGrp [1], 0, 0, NULL);
2846     cfp->protTextGrp = HiddenGroup (f, -1, 0, NULL);
2847     x = HiddenGroup (cfp->protTextGrp, 2, 0, NULL);
2848     SetGroupSpacing (x, 3, 5);
2849     StaticPrompt (x, "Name", 0, dialogTextHeight, programFont, 'l');
2850     cfp->protNameText = DialogText (x, "", 25, NULL);
2851     StaticPrompt (x, "Description", 0, dialogTextHeight, programFont, 'l');
2852     cfp->protDescText = DialogText (x, "", 25, NULL);
2853     cfp->protPromptGrp = HiddenGroup (f, -1, 0, NULL);
2854     StaticPrompt (cfp->protPromptGrp,
2855                   "Press Edit Protein Feature to change protein name",
2856                   0, 0, programFont, 'l');
2857     Hide (cfp->protPromptGrp);
2858 
2859     cfp->makemRNAMatch = CheckBox (cfp->protTextGrp, "Make overlapping mRNA product match protein name", NULL);
2860     Hide (cfp->makemRNAMatch);
2861     AlignObjects (ALIGN_CENTER, (HANDLE) x, (HANDLE) cfp->makemRNAMatch, NULL);
2862 
2863     z = HiddenGroup (cpp->cdRgnGrp [1], 3, 0, NULL);
2864     cfp->edProtBtn = PushButton (z, "Edit Protein Feature", LaunchProtFeatEd);
2865     SetObjectExtra (cfp->edProtBtn, cfp, NULL);
2866     Disable (cfp->edProtBtn);
2867     cfp->launchBtn = PushButton (z, "Launch Product Viewer", LaunchProteinViewer);
2868     SetObjectExtra (cfp->launchBtn, cfp, NULL);
2869     Disable (cfp->launchBtn);
2870     AlignObjects (ALIGN_CENTER, (HANDLE) cfp->protTextGrp, (HANDLE) cfp->protPromptGrp,
2871                   (HANDLE) z, NULL);
2872     Hide (cpp->cdRgnGrp [1]);
2873 
2874     cpp->cdRgnGrp [2] = HiddenGroup (n, -1, 0, NULL);
2875     CreateCodeBreakAlist (cpp);
2876     codebreak_widths [0] = 5;
2877     f = HiddenGroup (cpp->cdRgnGrp [2], 4, 0, NULL);
2878     StaticPrompt (f, "AA Position", 5 * stdCharWidth, 0, programFont, 'c');
2879     p2 = StaticPrompt (f, "Amino Acid", 0, 0, programFont, 'c');
2880     cpp->cdBrk = CreateTagListDialog (cpp->cdRgnGrp [2],
2881                                       3, 2, 2, codebreak_types,
2882                                       codebreak_widths, cpp->alists,
2883                                       CodeBreakPtrToCodeBreakDialog,
2884                                       CodeBreakDialogToCodeBreakPtr);
2885     tlp = (TagListPtr) GetObjectExtra (cpp->cdBrk);
2886     if (tlp != NULL) {
2887       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [1], (HANDLE) p2, NULL);
2888     }
2889     Hide (cpp->cdRgnGrp [2]);
2890 
2891     cpp->cdRgnGrp [3] = HiddenGroup (n, -1, 0, NULL);
2892     SetGroupSpacing (cpp->cdRgnGrp [3], 10, 20);
2893     q = HiddenGroup (cpp->cdRgnGrp [3], -1, 0, NULL);
2894     f = HiddenGroup (q, 0, -2, NULL);
2895 
2896     internalVersion = (Boolean) (GetAppProperty ("InternalNcbiSequin") != NULL);
2897 
2898     g = HiddenGroup (f, 5, 0, NULL);
2899 
2900     p2 = StaticPrompt (g, "Flags", 0, 0, programFont, 'l');
2901     if (! internalVersion) {
2902       Hide (p2);
2903     }
2904     cpp->conflict = CheckBox (g, "Conflict", NULL);
2905     if (! internalVersion) {
2906       Hide (cpp->conflict);
2907     }
2908     cpp->orf = CheckBox (g, "ORF", NULL);
2909     Hide (cpp->orf);
2910 
2911     AlignObjects (ALIGN_MIDDLE, (HANDLE) cpp->orf,
2912                   (HANDLE) cpp->conflict, (HANDLE) p2, NULL);
2913 
2914     cfp->conceptTransA = NULL;
2915     if (internalVersion) {
2916       cfp->conceptTransA = CheckBox (q, "Author-supplied conceptual translation", NULL);
2917     }
2918 
2919     StaticPrompt (q, "", 10, stdLineHeight, programFont, 'l');
2920     cfp->convertToMiscFeat = CheckBox (q, "Non-functional CDS, convert to misc_feature", ConvMiscFeatWarn);
2921     SetObjectExtra (cfp->convertToMiscFeat, cfp, NULL);
2922     cfp->saveAsMiscFeat = FALSE;
2923     Hide (cpp->cdRgnGrp [3]);
2924 
2925     AlignObjects (ALIGN_CENTER, (HANDLE) cpp->cdRgnGrp [0],
2926                   (HANDLE) cpp->cdRgnGrp [1], (HANDLE) cpp->cdRgnGrp [2],
2927                   (HANDLE) cpp->cdRgnGrp [3], NULL);
2928     AlignObjects (ALIGN_CENTER, (HANDLE) tbs, (HANDLE) k, NULL);
2929   }
2930 
2931   return (DialoG) p;
2932 }
2933 
2934 typedef struct genefinddata {
2935   ObjMgrPtr     omp;
2936   CdRgnFormPtr  cfp;
2937   CharPtr       title;
2938   Int2          idx;
2939   Int2          val;
2940   Boolean       geneFound;
2941 } GeneFindData, PNTR GeneFindPtr;
2942 
2943 static Boolean GeneFindFunc (GatherContextPtr gcp)
2944 
2945 {
2946   GeneFindPtr    gfp;
2947   ObjMgrTypePtr  omtp;
2948   SeqFeatPtr     sfp;
2949   Char           thislabel [41];
2950 
2951   if (gcp == NULL) return TRUE;
2952 
2953   gfp = (GeneFindPtr) gcp->userdata;
2954   if (gfp == NULL ) return TRUE;
2955 
2956   thislabel [0] = '\0';
2957 
2958   if (gcp->thistype == OBJ_SEQFEAT) {
2959     sfp = (SeqFeatPtr) gcp->thisitem;
2960     if (sfp != NULL && sfp->data.choice == SEQFEAT_GENE) {
2961       omtp = ObjMgrTypeFind (gfp->omp, gcp->thistype, NULL, NULL);
2962       if (omtp == NULL) {
2963         return TRUE;
2964       }
2965       if (omtp->labelfunc != NULL) {
2966         (*(omtp->labelfunc)) (gcp->thisitem, thislabel, 40, OM_LABEL_CONTENT);
2967       }
2968       if (thislabel [0] != '\0') {
2969         gfp->idx++;
2970         if (StringICmp (thislabel, gfp->title) == 0) {
2971           gfp->val = gfp->idx;
2972           gfp->geneFound = TRUE;
2973           return FALSE;
2974         }
2975       }
2976     }
2977   }
2978   return TRUE;
2979 }
2980 
2981 static void SetGeneAndProtFields (CdRgnFormPtr cfp, CharPtr title)
2982 
2983 {
2984   GeneFindData  gfd;
2985   GatherScope   gs;
2986   CharPtr       ptr;
2987   Char          str [128];
2988 
2989   if (cfp != NULL && title != NULL) {
2990     ptr = StringStr (title, "[prot=");
2991     if (ptr != NULL) {
2992       StringNCpy_0 (str, ptr + 6, sizeof (str));
2993       ptr = StringChr (str, ']');
2994       if (ptr != NULL) {
2995         *ptr = '\0';
2996         ptr = StringChr (str, ';');
2997         if (ptr != NULL) {
2998           *ptr = '\0';
2999           ptr++;
3000         }
3001         if (! StringHasNoText (str)) {
3002           SetTitle (cfp->protNameText, str);
3003         }
3004         if (! StringHasNoText (ptr)) {
3005           SetTitle (cfp->protDescText, ptr);
3006         }
3007       }
3008     }
3009     ptr = StringStr (title, "[gene=");
3010     if (ptr != NULL) {
3011       StringNCpy_0 (str, ptr + 6, sizeof (str));
3012       ptr = StringChr (str, ']');
3013       if (ptr != NULL) {
3014         *ptr = '\0';
3015         ptr = StringChr (str, ';');
3016         if (ptr != NULL) {
3017           *ptr = '\0';
3018           ptr++;
3019         }
3020         if (! StringHasNoText (str)) {
3021           SetTitle (cfp->geneSymbol, str);
3022         }
3023         if (! StringHasNoText (ptr)) {
3024           SetTitle (cfp->geneDesc, ptr);
3025         }
3026       }
3027       gfd.omp = ObjMgrGet ();
3028       gfd.cfp = cfp;
3029       gfd.title = str;
3030       gfd.idx = 2;
3031       gfd.val = 1;
3032       gfd.geneFound = FALSE;
3033       MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
3034       gs.seglevels = 1;
3035       gs.get_feats_location = TRUE;
3036       MemSet ((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
3037       gs.ignore[OBJ_BIOSEQ] = FALSE;
3038       gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
3039       gs.ignore[OBJ_SEQFEAT] = FALSE;
3040       gs.ignore[OBJ_SEQANNOT] = FALSE;
3041       gs.scope = GetBestTopParentForItemID (cfp->input_entityID,
3042                                             cfp->input_itemID,
3043                                             cfp->input_itemtype);
3044       GatherEntity (cfp->input_entityID, (Pointer) &gfd, GeneFindFunc, &gs);
3045       if (gfd.geneFound) {
3046         SetValue (cfp->gene, gfd.val);
3047         SafeHide (cfp->newGeneGrp);
3048         SafeShow (cfp->editGeneBtn);
3049       } else if (TextHasNoText (cfp->geneSymbol)) {
3050         SetValue (cfp->gene, 1);
3051         SafeHide (cfp->newGeneGrp);
3052         SafeShow (cfp->editGeneBtn);
3053       } else {
3054         SetValue (cfp->gene, 2);
3055         SafeHide (cfp->editGeneBtn);
3056         SafeShow (cfp->newGeneGrp);
3057       }
3058     }
3059   }
3060 }
3061 static Boolean ImportCdRgnForm (ForM f, CharPtr filename)
3062 
3063 {
3064   CdRgnFormPtr  cfp;
3065   Char          path [PATH_MAX];
3066 
3067   path [0] = '\0';
3068   StringNCpy_0 (path, filename, sizeof (path));
3069   cfp = (CdRgnFormPtr) GetObjectExtra (f);
3070   if (cfp != NULL) {
3071     switch (cfp->currentPage) {
3072       case CODING_REGION_PAGE :
3073         ShowImportProteinDialog ( cfp);
3074         break;
3075       case COMMON_PAGE :
3076         break;
3077       case LOCATION_PAGE :
3078         return ImportDialog (cfp->location, filename);
3079       default :
3080         break;
3081     }
3082   }
3083   return FALSE;
3084 }
3085 
3086 static Boolean ExportCdRgnForm (ForM f, CharPtr filename)
3087 
3088 {
3089   BioseqPtr     bsp;
3090   CdRgnFormPtr  cfp;
3091   FILE          *fp;
3092   ErrSev        oldErrSev;
3093   Char          path [PATH_MAX];
3094   SeqEntryPtr   sep;
3095 
3096   path [0] = '\0';
3097   StringNCpy_0 (path, filename, sizeof (path));
3098   cfp = (CdRgnFormPtr) GetObjectExtra (f);
3099   if (cfp != NULL) {
3100     switch (cfp->currentPage) {
3101       case CODING_REGION_PAGE :
3102         if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
3103 #ifdef WIN_MAC
3104           fp = FileOpen (path, "r");
3105           if (fp != NULL) {
3106             FileClose (fp);
3107           } else {
3108             FileCreate (path, "TEXT", "ttxt");
3109           }
3110 #endif
3111           fp = FileOpen (path, "w");
3112           if (fp != NULL) {
3113             sep = SeqEntryNew ();
3114             if (sep != NULL) {
3115               bsp = DialogToPointer (cfp->protseq);
3116               sep->choice = 1;
3117               sep->data.ptrvalue = (Pointer) bsp;
3118               oldErrSev = ErrSetMessageLevel (SEV_MAX);
3119               /*
3120               SeqEntryToFasta (sep, fp, FALSE);
3121               */
3122               BioseqFastaStream (bsp, fp, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, 70, 0, 0, TRUE);
3123               ErrSetMessageLevel (oldErrSev);
3124             }
3125             FileClose (fp);
3126             SeqEntryFree (sep);
3127             return TRUE;
3128           }
3129         }
3130         break;
3131       case COMMON_PAGE :
3132         break;
3133       case LOCATION_PAGE :
3134         return ExportDialog (cfp->location, filename);
3135       default :
3136         break;
3137     }
3138   }
3139   return FALSE;
3140 }
3141 
3142 static CharPtr  cdRgnFormTabs [] = {
3143   "Coding Region", "Properties", "Location", NULL
3144 };
3145 
3146 static void CdRgnFormMessage (ForM f, Int2 mssg)
3147 
3148 {
3149   CdRgnFormPtr  cfp;
3150 
3151   cfp = (CdRgnFormPtr) GetObjectExtra (f);
3152   if (cfp != NULL) {
3153     switch (mssg) {
3154       case VIB_MSG_INIT :
3155         StdInitFeatFormProc (f);
3156         break;
3157       case VIB_MSG_IMPORT :
3158         ImportCdRgnForm (f, NULL);
3159         break;
3160       case VIB_MSG_EXPORT :
3161         ExportCdRgnForm (f, NULL);
3162         break;
3163       case VIB_MSG_PRINT :
3164         break;
3165       case VIB_MSG_CLOSE :
3166         Remove (f);
3167         break;
3168       case VIB_MSG_CUT :
3169         StdCutTextProc (NULL);
3170         break;
3171       case VIB_MSG_COPY :
3172         StdCopyTextProc (NULL);
3173         break;
3174       case VIB_MSG_PASTE :
3175         StdPasteTextProc (NULL);
3176         break;
3177       case VIB_MSG_DELETE :
3178         if (cfp->currentPage == LOCATION_PAGE) {
3179           PointerToDialog (cfp->location, NULL);
3180         } else {
3181           StdDeleteTextProc (NULL);
3182         }
3183         break;
3184       default :
3185         if (cfp->appmessage != NULL) {
3186           cfp->appmessage (f, mssg);
3187         }
3188         break;
3189     }
3190   }
3191 }
3192 
3193 static CharPtr noLocMessage =
3194 "Feature must have a location!  You can import a\n\
3195 FASTA protein file from the Product subpage, which\n\
3196 will generate a location from the protein sequence.";
3197 
3198 static CharPtr cdsToMiscFeatMsg =
3199 "You have indicated that this CDS is non-functional.\n\
3200 Database policy is to convert this into a misc_feature,\n\
3201 and to remove any protein product attached to the CDS.\n\
3202 Are you sure you want to trigger this conversion now?";
3203 
3204 static void SetComment (CharPtr new_comment, WindoW w)
3205 {
3206   FeatureFormPtr ffp;
3207   CharPtr        old_comment;
3208   CharPtr        cp;
3209   CharPtr        complete_comment;
3210   Int4           old_len, new_len;
3211   
3212   if (new_comment == NULL || w == NULL) return;
3213   ffp = (FeatureFormPtr) GetObjectExtra (w);
3214   if (ffp == NULL) return;
3215 
3216   old_comment = SaveStringFromText (ffp->comment);
3217   if (StringHasNoText (old_comment))
3218   {
3219     SafeSetTitle (ffp->comment, new_comment);
3220   }
3221   else 
3222   {
3223     old_len = StringLen (old_comment);
3224     cp = StringStr (old_comment, new_comment);
3225     if (cp != NULL
3226         && (cp == old_comment || *(cp - 1) == ';')
3227         && (*(cp + old_len) == 0 || *(cp + old_len) == ';'))
3228     {
3229       /* do nothing, protein title already present */
3230     }
3231     else
3232     {
3233       new_len = StringLen (new_comment);
3234       
3235       complete_comment = (CharPtr) MemNew ((old_len + new_len + 2) * sizeof (Char));
3236       if (complete_comment != NULL)
3237       {
3238         StringCpy (complete_comment, new_comment);
3239         StringCat (complete_comment, ";");
3240         StringCat (complete_comment, old_comment);
3241         SafeSetTitle (ffp->comment, complete_comment);
3242       }
3243     }
3244   }
3245   old_comment = MemFree (old_comment); 
3246 }
3247 
3248 static Boolean FixCdRegionFormProteinFeatures (CdRgnFormPtr cfp, BioseqPtr newprot)
3249 {
3250   SeqLocPtr slp;
3251   SeqIdPtr  sip;
3252   BioseqPtr target;
3253   Boolean   rval = TRUE;
3254   
3255   if (cfp == NULL || newprot == NULL)
3256   {
3257     return FALSE;
3258   }
3259   if (!cfp->protFound)
3260   {
3261     return TRUE;
3262   }
3263   
3264   slp = DialogToPointer (cfp->product);
3265   sip = SeqLocId (slp);
3266   target = BioseqFind (sip);
3267   if (target != NULL) {
3268     if (!SeqEdFixProteinFeatures (target, newprot, FALSE, Sequin_GlobalAlign2Seq))
3269     {
3270       if (ANS_CANCEL == Message (MSG_OKC, "Unable to construct alignment between old and new proteins.\nYou will need to adjust the protein features manually if you continue."))
3271       {
3272         rval = FALSE;
3273       }
3274     }
3275   }
3276   slp = SeqLocFree (slp);
3277   return rval;
3278 }
3279 
3280 static CharPtr infWarning1 =
3281 "Bad inference qualifier!  You must conform to international nucleotide sequence database\nconventions for inference qualifiers!";
3282 
3283 static CharPtr infWarning2 =
3284 "Still has bad inference!  You must conform to international nucleotide sequence database\nconventions for inference qualifiers!";
3285 
3286 static CharPtr infAccept =
3287 "Do you want to accept changes with bad inference data?  The bad qualifier will be converted to a note!";
3288 
3289 static void CdRgnFormAcceptButtonProc (ButtoN b)
3290 
3291 {
3292   MsgAnswer      ans;
3293   Int2           attempts = 3;
3294   Char           badInfMssg [32];
3295   Char           badInfQual [256];
3296   BioseqPtr      bsp;
3297   CdRgnFormPtr   cfp;
3298   GBQualPtr      gbq;
3299   SeqEntryPtr    old;
3300   OMProcControl  ompc;
3301   Boolean        pseudo;
3302   GBQualPtr      qual;
3303   SeqEntryPtr    sep;
3304   SeqIdPtr       sip;
3305   SeqLocPtr      slp = NULL;
3306   Char           str [128];
3307   WindoW         w;
3308   SeqLocPtr      prod_slp;
3309   Boolean        delete_old_product = FALSE;
3310   ValNodePtr     err_list = NULL;
3311   SeqEntryPtr    oldscope;
3312 
3313   if (b != NULL) {
3314     w = ParentWindow (b);
3315     cfp = (CdRgnFormPtr) GetObjectExtra (b);
3316     if (cfp != NULL && cfp->form != NULL && cfp->actproc != NULL) {
3317       sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
3318       oldscope = SeqEntrySetScope (sep);
3319       if (! cfp->locvisited) {
3320         ErrPostEx (SEV_ERROR, 0, 0, "%s", noLocMessage);
3321         SeqEntrySetScope (oldscope);
3322         return;
3323       }
3324       if ((! cfp->acceptBadInf) && (! TestInference ((FeatureFormPtr) cfp, badInfQual, sizeof (badInfQual), badInfMssg))) {
3325         (cfp->badInfAttempts)++;
3326         if (GetAppProperty ("InternalNcbiSequin") != NULL) {
3327           attempts = 2;
3328         }
3329         if (cfp->badInfAttempts < attempts) {
3330           if (cfp->badInfAttempts == 2) {
3331             Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning2, badInfMssg, badInfQual);
3332           } else {
3333             Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning1, badInfMssg, badInfQual);
3334           }
3335           return;
3336         } else {
3337           if (Message (MSG_YN, "%s", infAccept) == ANS_NO) return;
3338           cfp->acceptBadInf = TRUE;
3339         }
3340       }
3341       slp = DialogToPointer (cfp->location);
3342       if (slp == NULL) {
3343         ErrPostEx (SEV_ERROR, 0, 0, "%s", noLocMessage);
3344         err_list = TestDialog (cfp->location);
3345         DisplayErrorMessages ("Location Errors", err_list);
3346         err_list = ValNodeFree (err_list);
3347         SeqEntrySetScope (oldscope);
3348         return;
3349       }
3350 
3351       cfp->saveAsMiscFeat = FALSE;
3352       if (GetStatus (cfp->convertToMiscFeat)) {
3353         ans = Message (MSG_OKC, "%s", cdsToMiscFeatMsg);
3354         if (ans == ANS_CANCEL) return;
3355         SeqLocFree (slp);
3356         Hide (w);
3357         Update ();
3358         bsp = NULL;
3359         slp = DialogToPointer (cfp->product); /* need to get current product reference */
3360         if (slp != NULL) {
3361           sip = SeqLocId (slp);
3362           if (sip != NULL) {
3363             bsp = BioseqFind (sip);
3364           }
3365         }
3366         SeqLocFree (slp);
3367         cfp->this_itemtype = OBJ_SEQFEAT;
3368         cfp->this_subtype = FEATDEF_IMP;
3369         cfp->saveAsMiscFeat = TRUE; /* now cfp->product dialog will return NULL */
3370         FeatFormReplaceWithoutUpdateProc (cfp->form);
3371         GetRidOfEmptyFeatsDescStrings (cfp->input_entityID, NULL);
3372         if (GetAppProperty ("InternalNcbiSequin") != NULL) {
3373           ExtendGeneFeatIfOnMRNA (cfp->input_entityID, NULL);
3374         }
3375         if (bsp != NULL) {
3376           MemSet ((Pointer) (&ompc), 0, sizeof (OMProcControl));
3377           ompc.do_not_reload_from_cache = TRUE;
3378           ompc.input_entityID = cfp->input_entityID;
3379           ompc.input_itemID = GetItemIDGivenPointer (cfp->input_entityID, OBJ_BIOSEQ, (Pointer) bsp);
3380           ompc.input_itemtype = OBJ_BIOSEQ;
3381           if (! DetachDataForProc (&ompc, FALSE)) {
3382             Message (MSG_ERROR, "DetachDataForProc failed");
3383           }
3384           sep = GetBestTopParentForItemID (cfp->input_entityID,
3385                                            cfp->input_itemID,
3386                                            cfp->input_itemtype);
3387           RenormalizeNucProtSets (sep, TRUE);
3388         }
3389         ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID,
3390                        cfp->input_itemID, cfp->input_itemtype);
3391         ObjMgrDeSelect (0, 0, 0, 0, NULL);
3392         SeqEntrySetScope (oldscope);
3393         Update ();
3394         Remove (w);
3395         return;
3396       }
3397 
3398       ans = ANS_OK;
3399       if (cfp->autoRetranslate) {
3400         DoTranslateProtein (cfp);
3401       }
3402       
3403       pseudo = FALSE;
3404       if (GetStatus (cfp->pseudo))
3405       {
3406         pseudo = TRUE;
3407       }
3408       else
3409       {
3410         qual = (GBQualPtr) DialogToPointer (cfp->gbquals);
3411         gbq = qual;
3412         while (gbq != NULL) {
3413           if (StringICmp (gbq->qual, "pseudo") == 0) {
3414             pseudo = TRUE;
3415           }
3416           gbq = gbq->next;
3417         }
3418         GBQualFree (qual);
3419       }
3420       
3421       if (pseudo)
3422       {
3423         Hide (w);
3424         /* remove old product, if there is one */
3425         prod_slp = DialogToPointer (cfp->product);
3426         if (prod_slp != NULL)
3427         {
3428           bsp = BioseqFind (SeqLocId (prod_slp));
3429           if (bsp != NULL) {
3430             bsp->idx.deleteme = TRUE;
3431             delete_old_product = TRUE;
3432           }
3433           prod_slp = SeqLocFree (prod_slp);
3434         }
3435         /* do not create new product */
3436         PointerToDialog (cfp->product, NULL);
3437         PointerToDialog (cfp->protseq, NULL);
3438         
3439         /* if the protein name is set, move it to a note */
3440         GetTitle (cfp->protNameText, str, sizeof (str) - 1);
3441         if (! StringHasNoText (str))
3442         {
3443           SetComment (str, w);
3444           SetTitle (cfp->protNameText, "");
3445         }
3446       }
3447       else
3448       {
3449         bsp = (BioseqPtr) DialogToPointer (cfp->protseq);
3450         if (bsp == NULL) 
3451         {
3452           ans = Message (MSG_OKC, "The coding region has no peptide sequence.  Are you sure?");
3453           if (ans != ANS_OK)
3454           {
3455             SeqLocFree (slp);
3456             SeqEntrySetScope (oldscope);
3457             return;
3458           }
3459         }
3460         else
3461         {
3462           if (!FixCdRegionFormProteinFeatures (cfp, bsp))
3463           {
3464             SeqLocFree (slp);
3465             BioseqFree (bsp);
3466             SeqEntrySetScope (oldscope);
3467             return;
3468           }
3469         }
3470       
3471         bsp = BioseqFree (bsp);
3472         Hide (w);
3473         Update ();
3474         if (Visible (cfp->protSeqIdGrp)) {
3475           GetTitle (cfp->protSeqIdTxt, str, sizeof (str) - 1);
3476           if (StringHasNoText (str)) {
3477             sep = GetBestTopParentForItemID (cfp->input_entityID,
3478                                              cfp->input_itemID,
3479                                              cfp->input_itemtype);
3480             old = SeqEntrySetScope (sep);
3481             sip = MakeNewProteinSeqId (slp, NULL);
3482             SeqEntrySetScope (old);
3483             if (sip != NULL) {
3484               SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str));
3485               SafeSetTitle (cfp->protSeqIdTxt, str);
3486             }
3487             SeqIdFree (sip);
3488           } else {
3489             cfp->protXrefName = cfp->protNameText;
3490             cfp->protXrefDesc = cfp->protDescText;
3491           }
3492         }
3493       }
3494       
3495       (cfp->actproc) (cfp->form);
3496       SeqEntrySetScope (oldscope);
3497     }
3498     SeqLocFree (slp);
3499     if (delete_old_product)
3500     {
3501       DeleteMarkedObjects (cfp->input_entityID, 0, NULL);
3502       sep = GetBestTopParentForItemID (cfp->input_entityID,
3503                                        cfp->input_itemID,
3504                                        cfp->input_itemtype);
3505       RenormalizeNucProtSets (sep, TRUE);
3506       ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID,
3507                        cfp->input_itemID, cfp->input_itemtype);
3508       ObjMgrDeSelect (0, 0, 0, 0, NULL);
3509     }
3510     
3511     Update ();
3512     Remove (w);
3513   }
3514 }
3515 
3516 static void CdRgnFormActivate (WindoW w)
3517 
3518 {
3519   CdRgnFormPtr  cfp;
3520 
3521   cfp = (CdRgnFormPtr) GetObjectExtra (w);
3522   if (cfp != NULL) {
3523     if (cfp->activate != NULL) {
3524       cfp->activate (w);
3525     }
3526     SetCdRgnImportExportItems (cfp);
3527   }
3528 }
3529 
3530 extern ForM CreateCdRgnForm (Int2 left, Int2 top, CharPtr title,
3531                              SeqFeatPtr sfp, SeqEntryPtr sep,
3532                              FormActnFunc actproc)
3533 
3534 {
3535   ButtoN             b;
3536   GrouP              c;
3537   CdRgnFormPtr       cfp;
3538   CdRgnPagePtr       cpp;
3539   GrouP              g;
3540   Int2               genCode;
3541   GrouP              h;
3542   GrouP              s;
3543   StdEditorProcsPtr  sepp;
3544   WindoW             w;
3545   GrouP              x;
3546   GrouP              y;
3547 
3548   w = NULL;
3549   cfp = (CdRgnFormPtr) MemNew (sizeof (CdRgnForm));
3550   if (cfp != NULL) {
3551     w = FixedWindow (left, top, -10, -10, title, StdCloseWindowProc);
3552     SetObjectExtra (w, cfp, StdFeatFormCleanupProc);
3553     cfp->form = (ForM) w;
3554     cfp->actproc = actproc;
3555     cfp->toform = CdRegionPtrToForm;
3556     cfp->fromform = NULL;
3557     cfp->formmessage = CdRgnFormMessage;
3558     cfp->testform = NULL;
3559     cfp->importform = ImportCdRgnForm;
3560     cfp->exportform = ExportCdRgnForm;
3561 
3562 #ifndef WIN_MAC
3563     CreateStdEditorFormMenus (w);
3564 #endif
3565 
3566     cfp->activate = NULL;
3567     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
3568     if (sepp != NULL) {
3569       cfp->activate = sepp->activateForm;
3570       cfp->appmessage = sepp->handleMessages;
3571     }
3572     SetActivate (w, CdRgnFormActivate);
3573 
3574     g = HiddenGroup (w, -1, 0, NULL);
3575     SetGroupSpacing (g, 3, 10);
3576 
3577     cfp->sep = sep;
3578     cfp->foldertabs = CreateFolderTabs (g, cdRgnFormTabs, CODING_REGION_PAGE,
3579                                         0, 0, SYSTEM_FOLDER_TAB,
3580                                         ChangeCdRgnPage, (Pointer) cfp);
3581     cfp->currentPage = CODING_REGION_PAGE;
3582 
3583     h = HiddenGroup (g, 0, 0, NULL);
3584 
3585     s = HiddenGroup (h, -1, 0, NULL);
3586     genCode = SeqEntryToGeneticCode (sep, NULL, NULL, 0);
3587     cfp->data = CreateCdRgnDialog (s, NULL, genCode, sfp, cfp);
3588     cfp->pages [CODING_REGION_PAGE] = s;
3589     Hide (cfp->pages [CODING_REGION_PAGE]);
3590 
3591     s = HiddenGroup (h, -1, 0, NULL);
3592     /* tell dialog to have canned explanation popup */
3593     cfp->this_itemtype = OBJ_SEQFEAT;
3594     cfp->this_subtype = FEATDEF_CDS;
3595     CreateCommonFeatureGroup (s, (FeatureFormPtr) cfp, sfp, TRUE, TRUE);
3596     cfp->pages [COMMON_PAGE] = s;
3597     Hide (cfp->pages [COMMON_PAGE]);
3598 
3599     s = HiddenGroup (h, -1, 0, NULL);
3600     cfp->location = CreateIntervalEditorDialogEx (s, NULL, 4, 2, sep, TRUE, FALSE,
3601                                                   TRUE, TRUE, FALSE,
3602                                                   (FeatureFormPtr) cfp,
3603                                                   StdFeatIntEdPartialCallback);
3604     cfp->pages [LOCATION_PAGE] = s;
3605     Hide (cfp->pages [LOCATION_PAGE]);
3606     cfp->locvisited = TRUE;
3607 
3608     AlignObjects (ALIGN_CENTER, (HANDLE) cfp->pages [CODING_REGION_PAGE],
3609                   (HANDLE) cfp->pages [COMMON_PAGE],
3610                   (HANDLE) cfp->pages [LOCATION_PAGE], NULL);
3611     AlignObjects (ALIGN_CENTER, (HANDLE) cfp->foldertabs, (HANDLE) h, NULL);
3612 
3613     cpp = (CdRgnPagePtr) GetObjectExtra (cfp->data);
3614     cpp->commonGrp = HiddenGroup (w, -1, 0, NULL);
3615     SetGroupSpacing (cpp->commonGrp, 3, 5);
3616     y = HiddenGroup (cpp->commonGrp, 3, 0, NULL);
3617     x = HiddenGroup (cpp->commonGrp, 2, 0, NULL);
3618     b = CheckBox (x, "Retranslate on Accept", SetRetransProc);
3619     SetObjectExtra (b, cfp, NULL);
3620     cfp->autoRetranslate = FALSE;
3621     b = CheckBox (x, "Synchronize Partials", SetSynchProc);
3622     SetObjectExtra (b, cfp, NULL);
3623     SetStatus (b, TRUE);
3624     cfp->autoUpdatePartials = TRUE;
3625     AlignObjects (ALIGN_CENTER, (HANDLE) x, (HANDLE) y, NULL);
3626 
3627     c = HiddenGroup (w, 2, 0, NULL);
3628     b = PushButton (c, "Accept", CdRgnFormAcceptButtonProc);
3629     SetObjectExtra (b, cfp, NULL);
3630     PushButton (c, "Cancel", StdCancelButtonProc);
3631     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) cpp->commonGrp, NULL);
3632     RealizeWindow (w);
3633 
3634     SendMessageToDialog (cfp->data, VIB_MSG_INIT);
3635     SendMessageToDialog (cfp->location, VIB_MSG_INIT);
3636     SendMessageToDialog (cfp->product, VIB_MSG_INIT);
3637     Show (cfp->pages [cfp->currentPage]);
3638     SendMessageToDialog (cfp->data, VIB_MSG_ENTER);
3639     Update ();
3640   }
3641   return (ForM) w;
3642 }
3643 
3644 typedef struct partialtrio {
3645   Boolean       partial;
3646   Boolean       partial5;
3647   Boolean       partial3;
3648   SeqEntryPtr   sep;
3649 } PartialTrio, PNTR PartialTrioPtr;
3650 
3651 static Boolean SetProteinPartial (GatherContextPtr gcp)
3652 
3653 {
3654   SeqFeatPtr      sfp;
3655   PartialTrioPtr  trioPtr;
3656 
3657   trioPtr = (PartialTrioPtr) gcp->userdata;
3658   sfp = (SeqFeatPtr) gcp->thisitem;
3659   if (sfp != NULL && trioPtr != NULL) {
3660     sfp->partial = trioPtr->partial;
3661     if (trioPtr->sep != NULL) {
3662       sfp->location = SeqLocFree (sfp->location);
3663       sfp->location =  CreateWholeInterval (trioPtr->sep);
3664     }
3665     SetSeqLocPartial (sfp->location, trioPtr->partial5, trioPtr->partial3);
3666   }
3667   return TRUE;
3668 }
3669 
3670 static Boolean UpdateProteinName (GatherContextPtr gcp)
3671 
3672 {
3673   CdRgnFormPtr  cfp;
3674   ProtRefPtr    prp;
3675   SeqFeatPtr    sfp;
3676   ValNodePtr    vnp;
3677 
3678   cfp = (CdRgnFormPtr) gcp->userdata;
3679   sfp = (SeqFeatPtr) gcp->thisitem;
3680   if (sfp == NULL || cfp == NULL) return TRUE;
3681   if (sfp->data.choice != SEQFEAT_PROT) return TRUE;
3682   prp = (ProtRefPtr) sfp->data.value.ptrvalue;
3683   if (prp == NULL) return TRUE;
3684   if (prp->name != NULL) {
3685     if (! TextHasNoText (cfp->protNameText)) {
3686       vnp = prp->name;
3687       vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
3688       vnp->data.ptrvalue = SaveStringFromText (cfp->protNameText);
3689     } else {
3690       vnp = prp->name;
3691       vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
3692       prp->name = vnp->next;
3693       MemFree (vnp);
3694     }
3695   } else if (! TextHasNoText (cfp->protNameText)) {
3696     vnp = ValNodeNew (NULL);
3697     prp->name = vnp;
3698     if (vnp != NULL) {
3699       vnp->data.ptrvalue = SaveStringFromText (cfp->protNameText);
3700     }
3701   }
3702       
3703   prp->desc = MemFree (prp->desc);
3704   prp->desc = SaveStringFromText (cfp->protDescText);
3705   return TRUE;
3706 }
3707 
3708 static void LookForRefTrack (
3709   SeqDescrPtr sdp,
3710   Pointer userdata
3711 )
3712 
3713 {
3714   BoolPtr        is_refseqP;
3715   ObjectIdPtr    oip;
3716   UserObjectPtr  uop;
3717 
3718   if (sdp->choice != Seq_descr_user) return;
3719   uop = (UserObjectPtr) sdp->data.ptrvalue;
3720   if (uop == NULL) return;
3721   oip = uop->type;
3722   if (oip == NULL || StringICmp (oip->str, "RefGeneTracking") != 0) return;
3723   is_refseqP = (BoolPtr) userdata;
3724   *is_refseqP = TRUE;
3725 }
3726 
3727 static Boolean SeeIfProtTitleNeedsFixing (BioseqPtr bsp, Uint2 entityID)
3728 
3729 {
3730   MsgAnswer          ans = ANS_YES;
3731   BioseqSetPtr       bssp;
3732   CharPtr            buf;
3733   size_t             buflen = 1001;
3734   Boolean            indexerVersion;
3735   Boolean            is_refseq = FALSE;
3736   Boolean            rsult = FALSE;
3737   SeqEntryPtr        sep;
3738   CharPtr            title;
3739   ValNodePtr         vnp;
3740 
3741   if (bsp == NULL || (! ISA_aa (bsp->mol))) return FALSE;
3742   vnp = BioseqGetSeqDescr (bsp, Seq_descr_title, NULL);
3743   if (vnp == NULL) return FALSE;
3744   if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
3745     bssp = (BioseqSetPtr) bsp->idx.parentptr;
3746     while (bssp != NULL && bssp->_class != BioseqseqSet_class_nuc_prot) {
3747       if (bssp->idx.parenttype == OBJ_BIOSEQSET) {
3748         bssp = (BioseqSetPtr) bssp->idx.parentptr;
3749       } else {
3750         bssp = NULL;
3751       }
3752     }
3753     if (bssp != NULL && bssp->_class == BioseqseqSet_class_nuc_prot) {
3754       title = (CharPtr) vnp->data.ptrvalue;
3755       buf = MemNew (sizeof (Char) * (buflen + 1));
3756       if (buf != NULL && NewCreateDefLineBuf (NULL, bsp, buf, buflen, TRUE, FALSE)) {
3757         if (StringICmp (buf, title) != 0) {
3758           indexerVersion = (Boolean) (GetAppProperty ("InternalNcbiSequin") != NULL);
3759           if (! indexerVersion) {
3760             ans = Message (MSG_YN, "Do you want to remove and recreate inconsistent title?");
3761           } else {
3762             sep = GetTopSeqEntryForEntityID (entityID);
3763             VisitDescriptorsInSep (sep, (Pointer) &is_refseq, LookForRefTrack);
3764             if (! is_refseq) {
3765               /* refseq wants to automatically fix, genbank wants to wait for AutoDef */
3766               ans = ANS_NO;
3767             }
3768           }
3769           if (ans == ANS_YES) {
3770             vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
3771             vnp->data.ptrvalue = StringSave (buf);
3772             rsult = TRUE;
3773             /*
3774             if (vnp->extended != 0) {
3775               ovp = (ObjValNodePtr) vnp;
3776               ovp->idx.deleteme = TRUE;
3777               DeleteMarkedObjects (entityID, 0, NULL);
3778               rsult = TRUE;
3779             }
3780             */
3781           }
3782         }
3783       }
3784       MemFree (buf);
3785     }
3786   }
3787   return rsult;
3788 }
3789 
3790 
3791 extern void CdRgnFeatFormActnProc (ForM f)
3792 
3793 {
3794   Char          badInfMssg [32];
3795   Char          badInfQual [256];
3796   BioseqPtr     bsp;
3797   CdRgnFormPtr  cfp;
3798   Char          desc [128];
3799   ValNodePtr    descr;
3800   GBQualPtr     gbq;
3801   MolInfoPtr    mip;
3802   Char          name [128];
3803   Boolean       partial;
3804   Boolean       partial5;
3805   Boolean       partial3;
3806   SeqEntryPtr   prot;
3807   ProtRefPtr    prp;
3808   GBQualPtr     quals;
3809   SeqEntryPtr   sep;
3810   Uint1         seq_data_type;
3811   SeqFeatPtr    sfp, mrna;
3812   SeqIdPtr      sip;
3813   SeqLocPtr     slp;
3814   BioseqPtr     target = NULL;
3815   PartialTrio   trio;
3816   ValNodePtr    vnp, err_list;
3817   SeqMgrFeatContext fcontext;
3818   RnaRefPtr         rrp;
3819 
3820   cfp = (CdRgnFormPtr) GetObjectExtra (f);
3821   sep = NULL;
3822   if (cfp != NULL) {
3823     if (! cfp->locvisited) {
3824       ErrPostEx (SEV_ERROR, 0, 0, "Feature must have a location!");
3825       return;
3826     }
3827     if ((! cfp->acceptBadInf) && (! TestInference ((FeatureFormPtr) cfp, badInfQual, sizeof (badInfQual), badInfMssg))) {
3828       (cfp->badInfAttempts)++;
3829       if (cfp->badInfAttempts < 3) {
3830           if (cfp->badInfAttempts == 2) {
3831             Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning2, badInfMssg, badInfQual);
3832           } else {
3833             Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning1, badInfMssg, badInfQual);
3834           }
3835         return;
3836       } else {
3837         if (Message (MSG_YN, "%s", infAccept) == ANS_NO) return;
3838         cfp->acceptBadInf = TRUE;
3839       }
3840     }
3841     slp = DialogToPointer (cfp->location);
3842     if (slp == NULL) {
3843       ErrPostEx (SEV_ERROR, 0, 0, "Feature must have a location!");
3844       err_list = TestDialog (cfp->location);
3845       DisplayErrorMessages ("Location Errors", err_list);
3846       err_list = ValNodeFree (err_list);    
3847       return;
3848     }
3849     /** this was causing a coredump ***
3850     SeqLocFree (slp);
3851     **********************************/
3852     /*
3853     if (cfp->autoRetranslate) {
3854       DoTranslateProtein (cfp);
3855     }
3856     */
3857 
3858     /* adjust mRNA product name */
3859     if (GetStatus (cfp->makemRNAMatch)) {
3860       mrna = SeqMgrGetOverlappingmRNA (slp, &fcontext);
3861       if (mrna != NULL && mrna->idx.subtype == FEATDEF_mRNA) {
3862         rrp = (RnaRefPtr) mrna->data.value.ptrvalue;
3863         if (rrp == NULL) {
3864           rrp = RnaRefNew();
3865           mrna->data.value.ptrvalue = rrp;
3866         }
3867         rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
3868         if (TextHasNoText (cfp->protNameText)) {
3869           rrp->ext.choice = 0;
3870         } else {
3871           rrp->ext.choice = 1;
3872           rrp->ext.value.ptrvalue = SaveStringFromText (cfp->protNameText);
3873         }
3874       }
3875     }
3876 
3877 
3878     CheckSeqLocForPartial (slp, &partial5, &partial3);
3879     SeqLocFree (slp);
3880     partial = GetStatus (cfp->partial);
3881     slp = DialogToPointer (cfp->product);
3882     if (slp != NULL) {
3883       quals = DialogToPointer (cfp->gbquals);
3884       cfp->usethisbioseq = NULL;
3885       gbq = quals;
3886       while (gbq != NULL) {
3887         if (StringICmp (gbq->qual, "pseudo") == 0) {
3888           GBQualFree (quals);
3889           SeqLocFree (slp);
3890           FeatFormReplaceWithoutUpdateProc (f);
3891           GetRidOfEmptyFeatsDescStrings (cfp->input_entityID, NULL);
3892           if (GetAppProperty ("InternalNcbiSequin") != NULL) {
3893             ExtendGeneFeatIfOnMRNA (cfp->input_entityID, NULL);
3894           }
3895           ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID,
3896                          cfp->input_itemID, cfp->input_itemtype);
3897           return;
3898         }
3899         gbq = gbq->next;
3900       }
3901       GBQualFree (quals);
3902       if (cfp->protFound) {
3903         sip = SeqLocId (slp);
3904         if (sip != NULL) {
3905           target = BioseqFind (sip);
3906           if (target != NULL) {
3907             trio.sep = NULL;
3908             bsp = (BioseqPtr) DialogToPointer (cfp->protseq);
3909             if (bsp != NULL) {
3910               seq_data_type = target->seq_data_type;
3911               target->length = bsp->length;
3912               target->seq_data = SeqDataFree (target->seq_data, target->seq_data_type);
3913               target->seq_data = bsp->seq_data;
3914               target->seq_data_type = bsp->seq_data_type;
3915               bsp->seq_data = NULL;
3916               BioseqConvert (target, seq_data_type);
3917               /*BioseqConvert (target, Seq_code_ncbistdaa);*/
3918             }
3919             BioseqFree (bsp);
3920             trio.sep = SeqMgrGetSeqEntryForData (target);
3921             if (cfp->autoUpdatePartials) {
3922               partial = (Boolean) (partial || partial5 || partial3);
3923               trio.partial = partial;
3924               trio.partial5 = partial5;
3925               trio.partial3 = partial3;
3926               GatherItem (cfp->protEntityID, cfp->protItemID,
3927                           cfp->protItemtype, (Pointer) &trio, SetProteinPartial);
3928             }
3929             if (Visible (cfp->protTextGrp)) {
3930               GatherItem (cfp->protEntityID, cfp->protItemID,
3931                           cfp->protItemtype, (Pointer) cfp, UpdateProteinName);
3932             }
3933           }
3934         }
3935       }
3936       FeatFormReplaceWithoutUpdateProc (f);
3937       sip = SeqLocId (slp);
3938       if (sip != NULL) {
3939         target = BioseqFind (sip);
3940         if (target != NULL) {
3941           bsp = (BioseqPtr) DialogToPointer (cfp->protseq);
3942           if (bsp != NULL) {
3943             seq_data_type = target->seq_data_type;
3944             target->length = bsp->length;
3945             target->seq_data = SeqDataFree (target->seq_data, target->seq_data_type);
3946             target->seq_data = bsp->seq_data;
3947             target->seq_data_type = bsp->seq_data_type;
3948             bsp->seq_data = NULL;
3949             BioseqConvert (target, seq_data_type);
3950             /*BioseqConvert (target, Seq_code_ncbistdaa);*/
3951           }
3952           BioseqFree (bsp);
3953           if ((! cfp->protFound) && Visible (cfp->protTextGrp)) {
3954             GetTitle (cfp->protNameText, name, sizeof (name));
3955             GetTitle (cfp->protDescText, desc, sizeof (desc));
3956             prp = CreateNewProtRef (name, desc, NULL, NULL);
3957             if (prp != NULL) {
3958               sep = SeqMgrGetSeqEntryForData (target);
3959               if (sep != NULL) {
3960                 sfp = CreateNewFeature (sep, NULL, SEQFEAT_PROT, NULL);
3961                 if (sfp != NULL) {
3962                   sfp->data.value.ptrvalue = (Pointer) prp;
3963                   if (cfp->autoUpdatePartials) {
3964                     sfp->partial = (Boolean) (partial || partial5 || partial3);
3965                     if (sfp->partial) {
3966                       SetSeqLocPartial (sfp->location, partial5, partial3);
3967                     }
3968                   }
3969                 }
3970               }
3971             }
3972           }
3973           sep = SeqMgrGetSeqEntryForData (target);
3974           if (sep != NULL && cfp->autoUpdatePartials) {
3975             vnp = SeqEntryGetSeqDescr (sep, Seq_descr_molinfo, NULL);
3976             if (vnp == NULL) {
3977               vnp = CreateNewDescriptor (sep, Seq_descr_molinfo);
3978               if (vnp != NULL) {
3979                 mip = MolInfoNew ();
3980                 vnp->data.ptrvalue = (Pointer) mip;
3981                 if (mip != NULL) {
3982                   mip->biomol = 8;
3983                   mip->tech = 13;
3984                 }
3985               }
3986             }
3987             if (vnp != NULL) {
3988               mip = (MolInfoPtr) vnp->data.ptrvalue;
3989               if (mip != NULL) {
3990                 if (cfp->conceptTransA != NULL) {
3991                   if (GetStatus (cfp->conceptTransA)) {
3992                     mip->tech = 13;
3993                   } else {
3994                     if (mip->tech == 13) {
3995                       mip->tech = 8;
3996                     }
3997                   }
3998                 }
3999                 if (partial5 && partial3) {
4000                   mip->completeness = 5;
4001                 } else if (partial5) {
4002                   mip->completeness = 3;
4003                 } else if (partial3) {
4004                   mip->completeness = 4;
4005                 } else if (partial) {
4006                   mip->completeness = 2;
4007                 } else {
4008                   mip->completeness = 0;
4009                 }
4010               }
4011             }
4012           }
4013         }
4014       }
4015     } else {
4016       bsp = (BioseqPtr) DialogToPointer (cfp->protseq);
4017       cfp->usethisbioseq = bsp;
4018       FeatFormReplaceWithoutUpdateProc (f);
4019       if (bsp != NULL) {
4020         prot = SeqEntryNew ();
4021         if (prot != NULL) {
4022           prot->choice = 1;
4023           prot->data.ptrvalue = (Pointer) bsp;
4024           SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, prot);
4025           sep = GetBestTopParentForItemID (cfp->input_entityID,
4026                                            cfp->input_itemID,
4027                                            cfp->input_itemtype);
4028           /*
4029           sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
4030           */
4031           descr = ExtractBioSourceAndPubs (sep);
4032           AddSeqEntryToSeqEntry (sep, prot, TRUE);
4033           ReplaceBioSourceAndPubs (sep, descr);
4034           cfp->input_entityID = ObjMgrGetEntityIDForChoice (sep);
4035           mip = MolInfoNew ();
4036           if (mip != NULL) {
4037             mip->biomol = 8;
4038             mip->tech = 13;
4039             if (cfp->conceptTransA != NULL) {
4040               if (! GetStatus (cfp->conceptTransA)) {
4041                 mip->tech = 8;
4042               }
4043             }
4044             if (partial5 && partial3) {
4045               mip->completeness = 5;
4046             } else if (partial5) {
4047               mip->completeness = 3;
4048             } else if (partial3) {
4049               mip->completeness = 4;
4050             } else if (partial) {
4051               mip->completeness = 2;
4052             } else {
4053               mip->completeness = 0;
4054             }
4055             vnp = CreateNewDescriptor (prot, Seq_descr_molinfo);
4056             if (vnp != NULL) {
4057               vnp->data.ptrvalue = (Pointer) mip;
4058             }
4059           }
4060         }
4061         if (bsp != NULL && Visible (cfp->protTextGrp)) {
4062           GetTitle (cfp->protNameText, name, sizeof (name));
4063           GetTitle (cfp->protDescText, desc, sizeof (desc));
4064           prp = CreateNewProtRef (name, desc, NULL, NULL);
4065           if (prp != NULL) {
4066             sep = SeqMgrGetSeqEntryForData (bsp);
4067             if (sep != NULL) {
4068               sfp = CreateNewFeature (sep, NULL, SEQFEAT_PROT, NULL);
4069               if (sfp != NULL) {
4070                 sfp->data.value.ptrvalue = (Pointer) prp;
4071                 sfp->partial = (Boolean) (partial || partial5 || partial3);
4072                 if (sfp->partial) {
4073                   SetSeqLocPartial (sfp->location, partial5, partial3);
4074                 }
4075               }
4076             }
4077           }
4078         }
4079       }
4080     }
4081     SeqLocFree (slp);
4082     GetRidOfEmptyFeatsDescStrings (cfp->input_entityID, NULL);
4083     if (GetAppProperty ("InternalNcbiSequin") != NULL) {
4084       ExtendGeneFeatIfOnMRNA (cfp->input_entityID, NULL);
4085     }
4086     ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID,
4087                    cfp->input_itemID, cfp->input_itemtype);
4088     if (target != NULL) {
4089       if (SeeIfProtTitleNeedsFixing (target, cfp->input_entityID)) {
4090         ObjMgrSendMsg (OM_MSG_UPDATE, cfp->input_entityID,
4091                        cfp->input_itemID, cfp->input_itemtype);
4092       }
4093     }
4094   }
4095 }
4096 
4097 
4098 static Int4 GuessFrameFromLocation (SeqLocPtr slp, BioseqPtr bsp)
4099 {
4100   Int4 loc_len, loc_start;
4101   Int4 frame = 0;
4102   Uint1 strand;
4103   Boolean partial5, partial3;
4104 
4105   if (slp == NULL || bsp == NULL) return 0;
4106 
4107   CheckSeqLocForPartial (slp, &partial5, &partial3);
4108   if (!partial5 || partial3) return 0;
4109 
4110   strand = SeqLocStrand (slp);
4111   if (strand == Seq_strand_minus)
4112   {
4113     loc_start = SeqLocStop (slp);
4114   } 
4115   else
4116   {
4117     loc_start = SeqLocStart (slp);
4118   }
4119   if ((strand == Seq_strand_minus && loc_start == bsp->length -1)
4120       || (strand != Seq_strand_minus && loc_start == 0))
4121   {
4122     loc_len = SeqLocLen (slp);
4123     frame = 1 + loc_len %3;
4124   } 
4125   return frame;
4126 }
4127 
4128 
4129 extern Int2 LIBCALLBACK CdRgnGenFunc (Pointer data)
4130 
4131 {
4132   BioseqPtr         bsp;
4133   CdRgnFormPtr      cfp;
4134   HelpMessageFunc   helpfunc;
4135   OMProcControlPtr  ompcp;
4136   OMUserDataPtr     omudp;
4137   SelStructPtr      sel;
4138   SeqEntryPtr       sep;
4139   SeqFeatPtr        sfp;
4140   WindoW            w;
4141   CdRgnPagePtr      cpp;
4142   Int4              frame = 0;
4143 
4144   ompcp = (OMProcControlPtr) data;
4145   sfp = NULL;
4146   sep = NULL;
4147   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
4148   switch (ompcp->input_itemtype) {
4149     case OBJ_SEQFEAT :
4150       sfp = (SeqFeatPtr) ompcp->input_data;
4151       if (sfp != NULL && sfp->data.choice != SEQFEAT_CDREGION) {
4152         return OM_MSG_RET_ERROR;
4153       }
4154       break;
4155     case OBJ_BIOSEQ :
4156       break;
4157     case OBJ_BIOSEQSET :
4158       break;
4159     case 0 :
4160       break;
4161     default :
4162       return OM_MSG_RET_ERROR;
4163   }
4164   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
4165                                 ompcp->input_itemtype, ompcp->proc->procid);
4166   if (omudp != NULL) {
4167     cfp = (CdRgnFormPtr) omudp->userdata.ptrvalue;
4168     if (cfp != NULL) {
4169       Select (cfp->form);
4170     }
4171     return OM_MSG_RET_DONE;
4172   }
4173   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
4174   w = (WindoW) CreateCdRgnForm (-50, -33, "Coding Region", sfp, sep,
4175                                 CdRgnFeatFormActnProc);
4176   cfp = (CdRgnFormPtr) GetObjectExtra (w);
4177   if (cfp != NULL) {
4178     cfp->input_entityID = ompcp->input_entityID;
4179     cfp->input_itemID = ompcp->input_itemID;
4180     cfp->input_itemtype = ompcp->input_itemtype;
4181     cfp->this_itemtype = OBJ_SEQFEAT;
4182     cfp->this_subtype = FEATDEF_CDS;
4183     cfp->procid = ompcp->proc->procid;
4184     cfp->proctype = ompcp->proc->proctype;
4185     cfp->userkey = OMGetNextUserKey ();
4186     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
4187                                OMPROC_EDIT, cfp->userkey);
4188     if (omudp != NULL) {
4189       omudp->userdata.ptrvalue = (Pointer) cfp;
4190       omudp->messagefunc = StdVibrantEditorMsgFunc;
4191     }
4192     SendMessageToForm (cfp->form, VIB_MSG_INIT);
4193     if (sfp != NULL) {
4194       PointerToForm (cfp->form, (Pointer) sfp);
4195       if (SetClosestParentIfDuplicating ((BaseFormPtr) cfp)) {
4196         SetBestProteinFeature (cfp, NULL);
4197         PointerToDialog (cfp->product, NULL);
4198         PointerToDialog (cfp->protseq, NULL);
4199         SetProteinLengthDisplay (cfp->protlen, 0);
4200       }
4201     } else {
4202       /* restored, but locvisited flag protects against accidental CDS */
4203       SetNewFeatureDefaultInterval ((FeatureFormPtr) cfp);
4204       SetCdRegionPageGeneticCode (cfp->data);
4205       sel = ObjMgrGetSelected ();
4206       if (sel != NULL && sel->next == NULL && sel->entityID == cfp->input_entityID &&
4207           sel->itemID == cfp->input_itemID && sel->itemtype == cfp->input_itemtype) {
4208         if (sel->regiontype == 1 && sel->region != NULL) {
4209           bsp = GetBioseqGivenIDs (cfp->input_entityID, cfp->input_itemID, cfp->input_itemtype);
4210           if (bsp != NULL && GetBioseqGivenSeqLoc ((SeqLocPtr) sel->region, cfp->input_entityID) == bsp) {
4211             cpp = (CdRgnPagePtr) GetObjectExtra (cfp->data);
4212             if (cpp != NULL) {
4213               frame = GuessFrameFromLocation (sel->region, bsp);
4214               SetValue (cpp->frame, frame + 1);
4215             }
4216             DoTranslateProtein (cfp);
4217           }
4218         }
4219       }
4220     }
4221   }
4222   Show (w);
4223   Select (w);
4224   helpfunc = (HelpMessageFunc) GetAppProperty ("HelpMessageProc");
4225   if (helpfunc != NULL) {
4226     helpfunc ("Features", "CDS");
4227   }
4228   return OM_MSG_RET_DONE;
4229 }
4230 
4231 typedef struct geneuserpage {
4232   DIALOG_MESSAGE_BLOCK
4233   TexT          symbol;
4234   TexT          name;
4235   TexT          source;
4236   GrouP         status;
4237 } GeneUserData, PNTR GeneUserPtr;
4238 
4239 static void UserObjectPtrToGene (DialoG d, Pointer data)
4240 
4241 {
4242   GeneUserPtr    gup;
4243   ObjectIdPtr    oip;
4244   CharPtr        str;
4245   UserFieldPtr   ufp;
4246   UserObjectPtr  uop;
4247 
4248   gup = (GeneUserPtr) GetObjectExtra (d);
4249   uop = (UserObjectPtr) data;
4250   if (gup != NULL) {
4251     if (uop != NULL && uop->type != NULL && StringICmp (uop->type->str, "OfficialNomenclature") == 0) {
4252       for (ufp = uop->data; ufp != NULL; ufp = ufp->next) {
4253         oip = ufp->label;
4254         if (oip == NULL || oip->str == NULL) continue;
4255         if (StringICmp (oip->str, "Symbol") == 0) {
4256           if (ufp->choice == 1) {
4257             str = (CharPtr) ufp->data.ptrvalue;
4258             if (str != NULL) {
4259               SetTitle (gup->symbol, str);
4260             }
4261           }
4262         } else if (StringICmp (oip->str, "Name") == 0) {
4263           if (ufp->choice == 1) {
4264             str = (CharPtr) ufp->data.ptrvalue;
4265             if (str != NULL) {
4266               SetTitle (gup->name, str);
4267             }
4268           }
4269         } else if (StringICmp (oip->str, "DataSource") == 0) {
4270           if (ufp->choice == 1) {
4271             str = (CharPtr) ufp->data.ptrvalue;
4272             if (str != NULL) {
4273               SetTitle (gup->source, str);
4274             }
4275           }
4276         } else if (StringICmp (oip->str, "Status") == 0) {
4277           if (ufp->choice == 1) {
4278             str = (CharPtr) ufp->data.ptrvalue;
4279             if (str != NULL) {
4280               if (StringICmp (str, "Official") == 0) {
4281                 SetValue (gup->status, 1);
4282               } else if (StringICmp (str, "Interim") == 0) {
4283                 SetValue (gup->status, 2);
4284               }
4285             }
4286           }
4287         }
4288       }
4289       ufp = uop->data;
4290       if (ufp != NULL && ufp->choice == 1) {
4291         oip = ufp->label;
4292         if (oip != NULL && oip->str != NULL && StringICmp (oip->str, "Symbol") == 0) {
4293           str = (CharPtr) ufp->data.ptrvalue;
4294           if (str != NULL) {
4295             SetTitle (gup->symbol, str);
4296           }
4297         }
4298       }
4299     }
4300   }
4301 }
4302 
4303 static UserObjectPtr CreateGeneUserObject (
4304   GeneUserPtr gup
4305 )
4306 
4307 {
4308   UserFieldPtr   last = NULL;
4309   ObjectIdPtr    oip;
4310   UserFieldPtr   ufp;
4311   UserObjectPtr  uop;
4312   Int2           val;
4313 
4314   if (gup == NULL) return NULL;
4315   if (TextHasNoText (gup->symbol)) return NULL;
4316 
4317   uop = UserObjectNew ();
4318   oip = ObjectIdNew ();
4319   oip->str = StringSave ("OfficialNomenclature");
4320   uop->type = oip;
4321 
4322   ufp = UserFieldNew ();
4323   oip = ObjectIdNew ();
4324   oip->str = StringSave ("Symbol");
4325   ufp->label = oip;
4326   ufp->choice = 1; /* visible string */
4327   ufp->data.ptrvalue = (Pointer) SaveStringFromText (gup->symbol);
4328 
4329   uop->data = ufp;
4330   last = ufp;
4331 
4332   if (! TextHasNoText (gup->name)) {
4333     ufp = UserFieldNew ();
4334     oip = ObjectIdNew ();
4335     oip->str = StringSave ("Name");
4336     ufp->label = oip;
4337     ufp->choice = 1; /* visible string */
4338     ufp->data.ptrvalue = (Pointer) SaveStringFromText (gup->name);
4339     last->next = ufp;
4340     last = ufp;
4341   }
4342 
4343   if (! TextHasNoText (gup->source)) {
4344     ufp = UserFieldNew ();
4345     oip = ObjectIdNew ();
4346     oip->str = StringSave ("DataSource");
4347     ufp->label = oip;
4348     ufp->choice = 1; /* visible string */
4349     ufp->data.ptrvalue = (Pointer) SaveStringFromText (gup->source);
4350     last->next = ufp;
4351     last = ufp;
4352   }
4353 
4354   val = GetValue (gup->status);
4355   if (val == 1 || val == 2) {
4356     ufp = UserFieldNew ();
4357     oip = ObjectIdNew ();
4358     oip->str = StringSave ("Status");
4359     ufp->label = oip;
4360     ufp->choice = 1; /* visible string */
4361     if (val == 1) {
4362       ufp->data.ptrvalue = (Pointer) StringSave ("Official");
4363     } else if (val == 2) {
4364       ufp->data.ptrvalue = (Pointer) StringSave ("Interim");
4365     }
4366     last->next = ufp;
4367     last = ufp;
4368   }
4369 
4370   return uop;
4371 }
4372 
4373 static Pointer GeneToUserObjectPtr (DialoG d)
4374 
4375 {
4376   GeneUserPtr    gup;
4377   UserObjectPtr  uop;
4378 
4379   uop = NULL;
4380   gup = (GeneUserPtr) GetObjectExtra (d);
4381   if (gup != NULL) {
4382     uop = CreateGeneUserObject (gup);
4383   }
4384   return (Pointer) uop;
4385 }
4386 
4387 static DialoG CreateGeneUserObjectDialog (GrouP h)
4388 
4389 {
4390   GrouP        g;
4391   GeneUserPtr  gup;
4392   GrouP        p;
4393 
4394   p = HiddenGroup (h, -1, 0, NULL);
4395   SetGroupSpacing (p, 10, 10);
4396 
4397   gup = (GeneUserPtr) MemNew (sizeof (GeneUserData));
4398   if (gup != NULL) {
4399     SetObjectExtra (p, gup, StdCleanupExtraProc);
4400     gup->dialog = (DialoG) p;
4401     gup->todialog = UserObjectPtrToGene;
4402     gup->fromdialog = GeneToUserObjectPtr;
4403     gup->testdialog = NULL;
4404     g = HiddenGroup (p, 2, 0, NULL);
4405     StaticPrompt (g, "Symbol", 0, 0, programFont, 'l');
4406     gup->symbol = DialogText (g, "", 15, NULL);
4407     StaticPrompt (g, "Name", 0, 0, programFont, 'l');
4408     gup->name = DialogText (g, "", 15, NULL);
4409     StaticPrompt (g, "Data Source", 0, 0, programFont, 'l');
4410     gup->source = DialogText (g, "", 15, NULL);
4411     StaticPrompt (g, "Status", 0, 0, programFont, 'l');
4412     gup->status = HiddenGroup (g, 3, 0, NULL);
4413     RadioButton (gup->status, "Official");
4414     RadioButton (gup->status, "Interim");
4415   }
4416 
4417   return (DialoG) p;
4418 }
4419 
4420 typedef struct genepage {
4421   DIALOG_MESSAGE_BLOCK
4422   TexT          locus;
4423   TexT          allele;
4424   TexT          desc;
4425   TexT          maploc;
4426   TexT          locus_tag;
4427   ButtoN        pseudo;
4428   DialoG        db;
4429   DialoG        syn;
4430   GrouP         geneGrp [4];
4431 } GenePage, PNTR GenePagePtr;
4432 
4433 typedef struct geneform {
4434   FEATURE_FORM_BLOCK
4435   SeqEntryPtr   sep;
4436   GrouP         pages [NUM_PAGES];
4437   DialoG        foldertabs;
4438   Int2          currentPage;
4439 } GeneForm, PNTR GeneFormPtr;
4440 
4441 static void GeneRefPtrToGenePage (DialoG d, Pointer data)
4442 
4443 {
4444   GenePagePtr  gpp;
4445   GeneRefPtr   grp;
4446 
4447   gpp = (GenePagePtr) GetObjectExtra (d);
4448   grp = (GeneRefPtr) data;
4449   if (gpp != NULL) {
4450     if (grp != NULL) {
4451       SafeSetTitle (gpp->locus, grp->locus);
4452       SafeSetTitle (gpp->allele, grp->allele);
4453       SafeSetTitle (gpp->desc, grp->desc);
4454       SafeSetTitle (gpp->maploc, grp->maploc);
4455       SafeSetTitle (gpp->locus_tag, grp->locus_tag);
4456       PointerToDialog (gpp->db, grp->db);
4457       PointerToDialog (gpp->syn, grp->syn);
4458     } else {
4459       SafeSetTitle (gpp->locus, "");
4460       SafeSetTitle (gpp->allele, "");
4461       SafeSetTitle (gpp->desc, "");
4462       SafeSetTitle (gpp->maploc, "");
4463       SafeSetTitle (gpp->locus_tag, "");
4464       PointerToDialog (gpp->db, NULL);
4465       PointerToDialog (gpp->syn, NULL);
4466     }
4467   }
4468 }
4469 
4470 static Pointer GenePageToGeneRefPtr (DialoG d)
4471 
4472 {
4473   GenePagePtr  gpp;
4474   GeneRefPtr   grp;
4475 
4476   grp = NULL;
4477   gpp = (GenePagePtr) GetObjectExtra (d);
4478   if (gpp != NULL) {
4479     grp = GeneRefNew ();
4480     if (grp != NULL) {
4481       grp->locus = SaveStringFromText (gpp->locus);
4482       grp->allele = SaveStringFromText (gpp->allele);
4483       grp->desc = SaveStringFromText (gpp->desc);
4484       grp->maploc = SaveStringFromText (gpp->maploc);
4485       grp->locus_tag = SaveStringFromText (gpp->locus_tag);
4486       grp->db = DialogToPointer (gpp->db);
4487       grp->syn = DialogToPointer (gpp->syn);
4488     }
4489   }
4490   return (Pointer) grp;
4491 }
4492 
4493 static CharPtr geneTabs1 [] = {
4494   "General", "Synonyms", NULL
4495 };
4496 
4497 static CharPtr geneTabs2 [] = {
4498   "General", "Synonyms", "Cross-Refs", NULL
4499 };
4500 
4501 static CharPtr geneTabs3 [] = {
4502   "General", "Synonyms", "Nomenclature", NULL
4503 };
4504 
4505 static CharPtr geneTabs4 [] = {
4506   "General", "Synonyms", "Nomenclature", "Cross-Refs", NULL
4507 };
4508 
4509 static void ChangeGeneSubPage (VoidPtr data, Int2 newval, Int2 oldval)
4510 
4511 {
4512   GenePagePtr  gpp;
4513 
4514   gpp = (GenePagePtr) data;
4515   if (gpp != NULL) {
4516     if (oldval >= 0 && oldval <= 3) {
4517       SafeHide (gpp->geneGrp [oldval]);
4518     }
4519     if (newval >= 0 && newval <= 3) {
4520       SafeShow (gpp->geneGrp [newval]);
4521     }
4522     Update ();
4523   }
4524 }
4525 
4526 static void LookForRefSeq (BioseqPtr bsp, Pointer userdata)
4527 
4528 {
4529   BoolPtr   isRefSeqP;
4530   SeqIdPtr  sip;
4531 
4532   if (bsp == NULL || userdata == NULL) return;
4533   isRefSeqP = (BoolPtr) userdata;
4534   for (sip = bsp->id; sip != NULL; sip = sip->next) {
4535     if (sip->choice == SEQID_OTHER) {
4536       *isRefSeqP = TRUE;
4537       return;
4538     }
4539   }
4540 }
4541 
4542 static Boolean GeneIsInRefSeq (SeqEntryPtr sep)
4543 
4544 {
4545   Boolean  is_refseq = FALSE;
4546 
4547   if (sep == NULL) return FALSE;
4548   VisitBioseqsInSep (sep, (Pointer) &is_refseq, LookForRefSeq);
4549   return is_refseq;
4550 }
4551 
4552 static DialoG CreateGeneDialog (GrouP h, CharPtr title, GeneRefPtr grp, GeneFormPtr gfp)
4553 
4554 {
4555   GrouP         f;
4556   GrouP         g;
4557   GenePagePtr   gpp;
4558   Char          just;
4559   GrouP         k;
4560   GrouP         m;
4561   GrouP         p;
4562   GrouP         q;
4563   GrouP         s;
4564   Boolean       showNomen = FALSE;
4565   Boolean       showXrefs = FALSE;
4566   GrouP         t;
4567   CharPtr PNTR  tabs = NULL;
4568   DialoG        tbs;
4569   Int2          x;
4570 
4571   p = HiddenGroup (h, 1, 0, NULL);
4572   SetGroupSpacing (p, 10, 10);
4573 
4574   gpp = (GenePagePtr) MemNew (sizeof (GenePage));
4575   if (gpp != NULL) {
4576 
4577     SetObjectExtra (p, gpp, StdCleanupExtraProc);
4578     gpp->dialog = (DialoG) p;
4579     gpp->todialog = GeneRefPtrToGenePage;
4580     gpp->fromdialog = GenePageToGeneRefPtr;
4581     gpp->testdialog = NULL;
4582 
4583     if (title != NULL && title [0] != '\0') {
4584       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
4585     } else {
4586       s = HiddenGroup (p, 0, -2, NULL);
4587     }
4588     m = HiddenGroup (s, -1, 0, NULL);
4589     SetGroupSpacing (m, 10, 10);
4590 
4591     if (grp != NULL && grp->db != NULL) {
4592       showXrefs = TRUE;
4593     }
4594     if (gfp != NULL && GeneIsInRefSeq (gfp->sep)) {
4595       showNomen = TRUE;
4596     }
4597 
4598     tabs = geneTabs1;
4599     if (showXrefs) {
4600       if (showNomen) {
4601         tabs = geneTabs4;
4602       } else {
4603         tabs = geneTabs2;
4604       }
4605     } else if (showNomen) {
4606       tabs = geneTabs3;
4607     }
4608 
4609     tbs = CreateFolderTabs (m, tabs, 0, 0, 0,
4610                             PROGRAM_FOLDER_TAB,
4611                             ChangeGeneSubPage, (Pointer) gpp);
4612     k = HiddenGroup (m, 0, 0, NULL);
4613 
4614     for (x = 0; x < 4; x++) {
4615       gpp->geneGrp [x] = NULL;
4616     }
4617     x = 0;
4618 
4619     gpp->geneGrp [x] = HiddenGroup (k, -1, 0, NULL);
4620     f = HiddenGroup (gpp->geneGrp [x], 2, 0, NULL);
4621     StaticPrompt (f, "Locus", 0, dialogTextHeight, programFont, 'l');
4622     gpp->locus = DialogText (f, "", 15, NULL);
4623     StaticPrompt (f, "Allele", 0, dialogTextHeight, programFont, 'l');
4624     gpp->allele = DialogText (f, "", 15, NULL);
4625     StaticPrompt (f, "Description", 0, dialogTextHeight, programFont, 'l');
4626     gpp->desc = DialogText (f, "", 15, NULL);
4627     StaticPrompt (f, "Map Location", 0, dialogTextHeight, programFont, 'l');
4628     gpp->maploc = DialogText (f, "", 15, NULL);
4629     StaticPrompt (f, "Locus Tag", 0, dialogTextHeight, programFont, 'l');
4630     gpp->locus_tag = DialogText (f, "", 15, NULL);
4631 
4632     x++;
4633 
4634     gpp->geneGrp [x] = HiddenGroup (k, -1, 0, NULL);
4635     g = HiddenGroup (gpp->geneGrp [x], 0, 2, NULL);
4636     StaticPrompt (g, "Synonyms", 0, 0, programFont, 'c');
4637     gpp->syn = CreateVisibleStringDialog (g, 3, -1, 15);
4638     Hide (gpp->geneGrp [x]);
4639     x++;
4640 
4641     if (showNomen) {
4642       gpp->geneGrp [x] = HiddenGroup (k, -1, 0, NULL);
4643       gfp->usrobjext = CreateGeneUserObjectDialog (gpp->geneGrp [x]);
4644       Hide (gpp->geneGrp [x]);
4645       x++;
4646     }
4647 
4648     if (showXrefs) {
4649       gpp->geneGrp [x] = HiddenGroup (k, -1, 0, NULL);
4650       q = HiddenGroup (gpp->geneGrp [x], -1, 0, NULL);
4651       if (GetAppProperty ("ReadOnlyDbTags") == NULL) {
4652         just = 'c';
4653       } else {
4654         just = 'l';
4655         StaticPrompt (q, "This page is read-only", 15 * stdCharWidth, 0, programFont, 'c');
4656       }
4657       t = HiddenGroup (q, 2, 0, NULL);
4658       StaticPrompt (t, "Database", 7 * stdCharWidth, 0, programFont, just);
4659       StaticPrompt (t, "Object ID", 8 * stdCharWidth, 0, programFont, just);
4660       gpp->db = CreateDbtagDialog (q, 3, -1, 7, 8);
4661       Hide (gpp->geneGrp [x]);
4662     }
4663 
4664     AlignObjects (ALIGN_CENTER, (HANDLE) tbs,
4665                   (HANDLE) gpp->geneGrp [0], (HANDLE) gpp->geneGrp [1],
4666                   (HANDLE) gpp->geneGrp [2], (HANDLE) gpp->geneGrp [3], NULL);
4667   }
4668 
4669   return (DialoG) p;
4670 }
4671 
4672 static void SetGeneImportExportItems (GeneFormPtr gfp)
4673 
4674 {
4675   IteM  exportItm;
4676   IteM  importItm;
4677 
4678   if (gfp != NULL) {
4679     importItm = FindFormMenuItem ((BaseFormPtr) gfp, VIB_MSG_IMPORT);
4680     exportItm = FindFormMenuItem ((BaseFormPtr) gfp, VIB_MSG_EXPORT);
4681     switch (gfp->currentPage) {
4682       case GENE_PAGE :
4683         SafeSetTitle (importItm, "Import...");
4684         SafeSetTitle (exportItm, "Export...");
4685         SafeDisable (importItm);
4686         SafeDisable (exportItm);
4687         break;
4688       case COMMON_PAGE :
4689         SafeSetTitle (importItm, "Import...");
4690         SafeSetTitle (exportItm, "Export...");
4691         SafeDisable (importItm);
4692         SafeDisable (exportItm);
4693         break;
4694       case LOCATION_PAGE :
4695         SafeSetTitle (importItm, "Import SeqLoc...");
4696         SafeSetTitle (exportItm, "Export SeqLoc...");
4697         SafeEnable (importItm);
4698         SafeEnable (exportItm);
4699         break;
4700       default :
4701         break;
4702     }
4703   }
4704 }
4705 
4706 static void ChangeGenePage (VoidPtr data, Int2 newval, Int2 oldval)
4707 
4708 {
4709   GeneFormPtr   gfp;
4710 
4711   gfp = (GeneFormPtr) data;
4712   if (gfp != NULL) {
4713     gfp->currentPage = newval;
4714     SafeHide (gfp->pages [oldval]);
4715     SafeShow (gfp->pages [newval]);
4716     switch (newval) {
4717       case GENE_PAGE :
4718         SendMessageToDialog (gfp->data, VIB_MSG_ENTER);
4719         break;
4720       case COMMON_PAGE :
4721         break;
4722       case LOCATION_PAGE :
4723         SendMessageToDialog (gfp->location, VIB_MSG_ENTER);
4724         break;
4725       default :
4726         break;
4727     }
4728     SetGeneImportExportItems (gfp);
4729     Update ();
4730   }
4731 }
4732 
4733 static Boolean ImportGeneForm (ForM f, CharPtr filename)
4734 
4735 {
4736   GeneFormPtr  gfp;
4737 
4738   gfp = (GeneFormPtr) GetObjectExtra (f);
4739   if (gfp != NULL) {
4740     switch (gfp->currentPage) {
4741       case LOCATION_PAGE :
4742         return ImportDialog (gfp->location, filename);
4743       default :
4744         break;
4745     }
4746   }
4747   return FALSE;
4748 }
4749 
4750 static Boolean ExportGeneForm (ForM f, CharPtr filename)
4751 
4752 {
4753   GeneFormPtr  gfp;
4754 
4755   gfp = (GeneFormPtr) GetObjectExtra (f);
4756   if (gfp != NULL) {
4757     switch (gfp->currentPage) {
4758       case LOCATION_PAGE :
4759         return ExportDialog (gfp->location, filename);
4760       default :
4761         break;
4762     }
4763   }
4764   return FALSE;
4765 }
4766 
4767 static CharPtr  geneFormTabs [] = {
4768   "Gene", "Properties", "Location", NULL
4769 };
4770 
4771 static void GeneFormMessage (ForM f, Int2 mssg)
4772 
4773 {
4774   GeneFormPtr  gfp;
4775 
4776   gfp = (GeneFormPtr) GetObjectExtra (f);
4777   if (gfp != NULL) {
4778     switch (mssg) {
4779       case VIB_MSG_INIT :
4780         StdInitFeatFormProc (f);
4781         break;
4782       case VIB_MSG_IMPORT :
4783         ImportGeneForm (f, NULL);
4784         break;
4785       case VIB_MSG_EXPORT :
4786         ExportGeneForm (f, NULL);
4787         break;
4788       case VIB_MSG_CLOSE :
4789         Remove (f);
4790         break;
4791       case VIB_MSG_CUT :
4792         StdCutTextProc (NULL);
4793         break;
4794       case VIB_MSG_COPY :
4795         StdCopyTextProc (NULL);
4796         break;
4797       case VIB_MSG_PASTE :
4798         StdPasteTextProc (NULL);
4799         break;
4800       case VIB_MSG_DELETE :
4801         if (gfp->currentPage == LOCATION_PAGE) {
4802           PointerToDialog (gfp->location, NULL);
4803         } else {
4804           StdDeleteTextProc (NULL);
4805         }
4806         break;
4807       default :
4808         if (gfp->appmessage != NULL) {
4809           gfp->appmessage (f, mssg);
4810         }
4811         break;
4812     }
4813   }
4814 }
4815 
4816 static void GeneFormActivate (WindoW w)
4817 
4818 {
4819   GeneFormPtr  gfp;
4820 
4821   gfp = (GeneFormPtr) GetObjectExtra (w);
4822   if (gfp != NULL) {
4823     if (gfp->activate != NULL) {
4824       gfp->activate (w);
4825     }
4826     SetGeneImportExportItems (gfp);
4827   }
4828 }
4829 
4830 extern ForM CreateGeneForm (Int2 left, Int2 top, CharPtr title,
4831                             SeqFeatPtr sfp, SeqEntryPtr sep,
4832                             FormActnFunc actproc)
4833 
4834 {
4835   ButtoN             b;
4836   GrouP              c;
4837   GrouP              g;
4838   GeneFormPtr        gfp;
4839   GeneRefPtr         grp;
4840   GrouP              h;
4841   GrouP              s;
4842   StdEditorProcsPtr  sepp;
4843   WindoW             w;
4844 
4845   w = NULL;
4846   gfp = (GeneFormPtr) MemNew (sizeof (GeneForm));
4847   if (gfp != NULL) {
4848     w = FixedWindow (left, top, -10, -10, title, StdCloseWindowProc);
4849     SetObjectExtra (w, gfp, StdFeatFormCleanupProc);
4850     gfp->form = (ForM) w;
4851     gfp->actproc = actproc;
4852     gfp->toform = StdSeqFeatPtrToFeatFormProc;
4853     gfp->fromform = NULL;
4854     gfp->formmessage = GeneFormMessage;
4855     gfp->testform = NULL;
4856     gfp->importform = ImportGeneForm;
4857     gfp->exportform = ExportGeneForm;
4858 
4859 #ifndef WIN_MAC
4860     CreateStdEditorFormMenus (w);
4861 #endif
4862 
4863     gfp->activate = NULL;
4864     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
4865     if (sepp != NULL) {
4866       gfp->activate = sepp->activateForm;
4867       gfp->appmessage = sepp->handleMessages;
4868     }
4869     SetActivate (w, GeneFormActivate);
4870 
4871     g = HiddenGroup (w, -1, 0, NULL);
4872     SetGroupSpacing (g, 3, 10);
4873 
4874     gfp->sep = sep;
4875     gfp->foldertabs = CreateFolderTabs (g, geneFormTabs, GENE_PAGE,
4876                                         0, 0, SYSTEM_FOLDER_TAB,
4877                                         ChangeGenePage, (Pointer) gfp);
4878     gfp->currentPage = GENE_PAGE;
4879 
4880     h = HiddenGroup (g, 0, 0, NULL);
4881 
4882     s = HiddenGroup (h, -1, 0, NULL);
4883     grp = NULL;
4884     if (sfp != NULL && sfp->data.choice == SEQFEAT_GENE) {
4885       grp = sfp->data.value.ptrvalue;
4886     }
4887     gfp->data = CreateGeneDialog (s, NULL, grp, gfp);
4888     gfp->pages [GENE_PAGE] = s;
4889     Hide (gfp->pages [GENE_PAGE]);
4890 
4891     s = HiddenGroup (h, -1, 0, NULL);
4892     CreateCommonFeatureGroup (s, (FeatureFormPtr) gfp, sfp, FALSE, TRUE);
4893     gfp->pages [COMMON_PAGE] = s;
4894     Hide (gfp->pages [COMMON_PAGE]);
4895 
4896     s = HiddenGroup (h, -1, 0, NULL);
4897     gfp->location = CreateIntervalEditorDialogEx (s, NULL, 4, 2, sep, TRUE, FALSE,
4898                                                   TRUE, TRUE, FALSE,
4899                                                   (FeatureFormPtr) gfp,
4900                                                   StdFeatIntEdPartialCallback);
4901     gfp->pages [LOCATION_PAGE] = s;
4902     Hide (gfp->pages [LOCATION_PAGE]);
4903 
4904     AlignObjects (ALIGN_CENTER, (HANDLE) gfp->pages [GENE_PAGE],
4905                   (HANDLE) gfp->pages [COMMON_PAGE], (HANDLE) gfp->pages [LOCATION_PAGE],
4906                   NULL);
4907     AlignObjects (ALIGN_CENTER, (HANDLE) gfp->foldertabs, (HANDLE) h, NULL);
4908 
4909     c = HiddenGroup (w, 2, 0, NULL);
4910     b = PushButton (c, "Accept", StdFeatFormAcceptButtonProc);
4911     SetObjectExtra (b, gfp, NULL);
4912     PushButton (c, "Cancel", StdCancelButtonProc);
4913     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
4914     RealizeWindow (w);
4915 
4916     SendMessageToDialog (gfp->data, VIB_MSG_INIT);
4917     SendMessageToDialog (gfp->location, VIB_MSG_INIT);
4918     Show (gfp->pages [gfp->currentPage]);
4919     SendMessageToDialog (gfp->data, VIB_MSG_ENTER);
4920     Update ();
4921   }
4922   return (ForM) w;
4923 }
4924 
4925 static Boolean CDSPseudoByGeneFunc (GatherContextPtr gcp, Boolean pseudo)
4926 
4927 {
4928   GBQualPtr   gbq;
4929   GBQualPtr   next;
4930   GBQualPtr PNTR  prev;
4931   GBQualPtr   qual;
4932   SeqFeatPtr  sfp;
4933   SeqLocPtr   slp;
4934 
4935   if (gcp == NULL) return TRUE;
4936   slp = (SeqLocPtr) gcp->userdata;
4937   if (slp == NULL) return TRUE;
4938   if (gcp->thistype == OBJ_SEQFEAT) {
4939     sfp = (SeqFeatPtr) gcp->thisitem;
4940     if (sfp != NULL && sfp->data.choice == SEQFEAT_CDREGION) {
4941       if (SeqLocAinB (sfp->location, slp) >= 0) {
4942         gbq = sfp->qual;
4943         prev = (GBQualPtr PNTR) &(sfp->qual);
4944         while (gbq != NULL) {
4945           next = gbq->next;
4946           if (StringICmp (gbq->qual, "pseudo") == 0) {
4947             if (pseudo) return TRUE;
4948             *(prev) = gbq->next;
4949             gbq->next = NULL;
4950             GBQualFree (gbq);
4951           } else {
4952             prev = (GBQualPtr PNTR) &(gbq->next);
4953           }
4954           gbq = next;
4955         }
4956         if (! pseudo) return TRUE;
4957         qual = GBQualNew ();
4958         if (qual != NULL) {
4959           qual->qual = StringSave ("pseudo");
4960           qual->val = StringSave ("");
4961           gbq = sfp->qual;
4962           if (gbq != NULL) {
4963             while (gbq->next != NULL) {
4964               gbq = gbq->next;
4965             }
4966             gbq->next = qual;
4967           } else {
4968             sfp->qual = qual;
4969           }
4970         }
4971       }
4972     }
4973   }
4974   return TRUE;
4975 }
4976 
4977 static Boolean CDSPseudoOnFunc (GatherContextPtr gcp)
4978 
4979 {
4980   return CDSPseudoByGeneFunc (gcp, TRUE);
4981 }
4982 
4983 static Boolean CDSPseudoOffFunc (GatherContextPtr gcp)
4984 
4985 {
4986   return CDSPseudoByGeneFunc (gcp, FALSE);
4987 }
4988 
4989 static void GeneFeatFormActnProc (ForM f)
4990 
4991 {
4992   GeneFormPtr  gfp;
4993   GenePagePtr  gpp;
4994   GatherScope  gs;
4995   Boolean      pseudo = FALSE;
4996   SeqEntryPtr  sep;
4997   SeqLocPtr    slp = NULL;
4998 
4999   gfp = (GeneFormPtr) GetObjectExtra (f);
5000   if (gfp != NULL) {
5001     slp = DialogToPointer (gfp->location);
5002     gpp = GetObjectExtra (gfp->data);
5003     if (gpp != NULL) {
5004       pseudo = GetStatus (gpp->pseudo);
5005     }
5006   }
5007   if (FeatFormReplaceWithoutUpdateProc (f)) {
5008     if (gfp != NULL) {
5009       sep = GetBestTopParentForItemID (gfp->input_entityID,
5010                                        gfp->input_itemID,
5011                                        gfp->input_itemtype);
5012       if (slp != NULL) {
5013         MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
5014         gs.seglevels = 1;
5015         gs.get_feats_location = FALSE;
5016         MemSet ((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
5017         gs.ignore[OBJ_BIOSEQ] = FALSE;
5018         gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
5019         gs.ignore[OBJ_SEQFEAT] = FALSE;
5020         gs.ignore[OBJ_SEQANNOT] = FALSE;
5021         gs.scope = sep;
5022         if (pseudo) {
5023           GatherEntity (gfp->input_entityID, (Pointer) slp, CDSPseudoOnFunc, &gs);
5024         } else {
5025           GatherEntity (gfp->input_entityID, (Pointer) slp, CDSPseudoOffFunc, &gs);
5026         }
5027       }
5028       GetRidOfEmptyFeatsDescStrings (gfp->input_entityID, NULL);
5029       if (GetAppProperty ("InternalNcbiSequin") != NULL) {
5030         ExtendGeneFeatIfOnMRNA (gfp->input_entityID, NULL);
5031       }
5032       ObjMgrSendMsg (OM_MSG_UPDATE, gfp->input_entityID, 0, 0);
5033     }
5034   }
5035   SeqLocFree (slp);
5036 }
5037 
5038 extern Int2 LIBCALLBACK GeneGenFunc (Pointer data)
5039 
5040 {
5041   GeneFormPtr       gfp;
5042   HelpMessageFunc   helpfunc;
5043   OMProcControlPtr  ompcp;
5044   OMUserDataPtr     omudp;
5045   SeqEntryPtr       sep;
5046   SeqFeatPtr        sfp;
5047   WindoW            w;
5048 
5049   ompcp = (OMProcControlPtr) data;
5050   sfp = NULL;
5051   sep = NULL;
5052   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
5053   switch (ompcp->input_itemtype) {
5054     case OBJ_SEQFEAT :
5055       sfp = (SeqFeatPtr) ompcp->input_data;
5056       if (sfp != NULL && sfp->data.choice != SEQFEAT_GENE) {
5057         return OM_MSG_RET_ERROR;
5058       }
5059       break;
5060     case OBJ_BIOSEQ :
5061       break;
5062     case OBJ_BIOSEQSET :
5063       break;
5064     case 0 :
5065       break;
5066     default :
5067       return OM_MSG_RET_ERROR;
5068   }
5069   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
5070                                 ompcp->input_itemtype, ompcp->proc->procid);
5071   if (omudp != NULL) {
5072     gfp = (GeneFormPtr) omudp->userdata.ptrvalue;
5073     if (gfp != NULL) {
5074       Select (gfp->form);
5075     }
5076     return OM_MSG_RET_DONE;
5077   }
5078   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
5079   w = (WindoW) CreateGeneForm (-50, -33, "Gene", sfp, sep,
5080                                GeneFeatFormActnProc);
5081   gfp = (GeneFormPtr) GetObjectExtra (w);
5082   if (gfp != NULL) {
5083     gfp->input_entityID = ompcp->input_entityID;
5084     gfp->input_itemID = ompcp->input_itemID;
5085     gfp->input_itemtype = ompcp->input_itemtype;
5086     gfp->this_itemtype = OBJ_SEQFEAT;
5087     gfp->this_subtype = FEATDEF_GENE;
5088     gfp->procid = ompcp->proc->procid;
5089     gfp->proctype = ompcp->proc->proctype;
5090     gfp->userkey = OMGetNextUserKey ();
5091     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
5092                                OMPROC_EDIT, gfp->userkey);
5093     if (omudp != NULL) {
5094       omudp->userdata.ptrvalue = (Pointer) gfp;
5095       omudp->messagefunc = StdVibrantEditorMsgFunc;
5096     }
5097     SendMessageToForm (gfp->form, VIB_MSG_INIT);
5098     if (sfp != NULL) {
5099       PointerToForm (gfp->form, (Pointer) sfp);
5100       SetClosestParentIfDuplicating ((BaseFormPtr) gfp);
5101     } else {
5102       SetNewFeatureDefaultInterval ((FeatureFormPtr) gfp);
5103     }
5104   }
5105   Show (w);
5106   Select (w);
5107   helpfunc = (HelpMessageFunc) GetAppProperty ("HelpMessageProc");
5108   if (helpfunc != NULL) {
5109     helpfunc ("Features", "Gene");
5110   }
5111   return OM_MSG_RET_DONE;
5112 }
5113 
5114 typedef struct protpage {
5115   DIALOG_MESSAGE_BLOCK
5116   DialoG        name;
5117   TexT          desc;
5118   DialoG        ec;
5119   DialoG        activity;
5120   DialoG        db;
5121   PopuP         processed;
5122   GrouP         protGrp [4];
5123 } ProtPage, PNTR ProtPagePtr;
5124 
5125 typedef struct protform {
5126   FEATURE_FORM_BLOCK
5127   SeqEntryPtr   sep;
5128   GrouP         pages [NUM_PAGES];
5129   DialoG        foldertabs;
5130   Int2          currentPage;
5131   ButtoN        makemRNAMatch;
5132 } ProtForm, PNTR ProtFormPtr;
5133 
5134 static void ProtRefPtrToProtPage (DialoG d, Pointer data)
5135 
5136 {
5137   ProtPagePtr  ppp;
5138   ProtRefPtr   prp;
5139 
5140   ppp = (ProtPagePtr) GetObjectExtra (d);
5141   prp = (ProtRefPtr) data;
5142   if (ppp != NULL) {
5143     if (prp != NULL) {
5144       PointerToDialog (ppp->name, prp->name);
5145       SafeSetTitle (ppp->desc, prp->desc);
5146       PointerToDialog (ppp->ec, prp->ec);
5147       PointerToDialog (ppp->activity, prp->activity);
5148       PointerToDialog (ppp->db, prp->db);
5149       SafeSetValue (ppp->processed, prp->processed + 1);
5150     } else {
5151       PointerToDialog (ppp->name, NULL);
5152       SafeSetTitle (ppp->desc, "");
5153       PointerToDialog (ppp->ec, NULL);
5154       PointerToDialog (ppp->activity, NULL);
5155       PointerToDialog (ppp->db, NULL);
5156       SafeSetValue (ppp->processed, 1);
5157     }
5158   }
5159 }
5160 
5161 static Pointer ProtPageToProtRefPtr (DialoG d)
5162 
5163 {
5164   ProtPagePtr  ppp;
5165   ProtRefPtr   prp;
5166 
5167   prp = NULL;
5168   ppp = (ProtPagePtr) GetObjectExtra (d);
5169   if (ppp != NULL) {
5170     prp = ProtRefNew ();
5171     if (prp != NULL) {
5172       prp->name = DialogToPointer (ppp->name);
5173       prp->desc = SaveStringFromText (ppp->desc);
5174       prp->ec = DialogToPointer (ppp->ec);
5175       prp->activity = DialogToPointer (ppp->activity);
5176       prp->db = DialogToPointer (ppp->db);
5177       prp->processed = GetValue (ppp->processed) - 1;
5178     }
5179   }
5180   return (Pointer) prp;
5181 }
5182 
5183 static CharPtr protTabs [] = {
5184   "General", "E.C. Number", "Activity", NULL
5185 };
5186 
5187 static CharPtr protTabsXref [] = {
5188   "General", "E.C. Number", "Activity", "Cross-Refs", NULL
5189 };
5190 
5191 static void ChangeProtSubPage (VoidPtr data, Int2 newval, Int2 oldval)
5192 
5193 {
5194   ProtPagePtr  ppp;
5195 
5196   ppp = (ProtPagePtr) data;
5197   if (ppp != NULL) {
5198     if (oldval >= 0 && oldval <= 3) {
5199       SafeHide (ppp->protGrp [oldval]);
5200     }
5201     if (newval >= 0 && newval <= 3) {
5202       SafeShow (ppp->protGrp [newval]);
5203     }
5204     Update ();
5205   }
5206 }
5207 
5208 static void ChangeProtProcessed (PopuP p)
5209 
5210 {
5211   ProtFormPtr  pfp;
5212   Int2         val;
5213 
5214   pfp = (ProtFormPtr) GetObjectExtra (p);
5215   if (pfp == NULL) return;
5216   val = GetValue (p);
5217   switch (val) {
5218     case 1 :
5219       SafeHide (pfp->product);
5220       break;
5221     case 2 :
5222     case 3 :
5223     case 4 :
5224     case 5 :
5225       SafeShow (pfp->product);
5226       break;
5227     default :
5228       break;
5229   }
5230 }
5231 
5232 typedef struct switchtocds 
5233 {
5234   SeqFeatPtr  sfp;
5235   ProtFormPtr pfp;
5236 } SwitchToCDSData, PNTR SwitchToCDSPtr;
5237 
5238 static void LaunchCDSEditorFromProtDialog (ButtoN b)
5239 {
5240   SwitchToCDSPtr    scp;
5241   BioseqPtr         bsp;
5242   SeqFeatPtr        cds_sfp;
5243   SeqEntryPtr       sep;
5244   Uint2             entityID;
5245   SeqMgrFeatContext fcontext;
5246   CdRgnFormPtr      cfp;
5247   HelpMessageFunc   helpfunc;
5248   WindoW            w;
5249   
5250   scp = (SwitchToCDSPtr) GetObjectExtra (b);
5251   if (scp == NULL || scp->sfp == NULL || scp->pfp == NULL)
5252   {
5253       return;
5254   }
5255   
5256   bsp = BioseqFindFromSeqLoc (scp->sfp->location);
5257   if (bsp == NULL) return;
5258   cds_sfp = SeqMgrGetCDSgivenProduct (bsp, &fcontext);
5259   if (cds_sfp == NULL) return;
5260   bsp = BioseqFindFromSeqLoc (cds_sfp->location);
5261   if (bsp == NULL) return;
5262   entityID = ObjMgrGetEntityIDForPointer (bsp);
5263   
5264   sep = GetTopSeqEntryForEntityID (entityID);
5265   w = (WindoW) CreateCdRgnForm (-50, -33, "Coding Region", cds_sfp, sep,
5266                                 CdRgnFeatFormActnProc);
5267   cfp = (CdRgnFormPtr) GetObjectExtra (w);
5268   if (cfp != NULL) {
5269     cfp->input_entityID = entityID;
5270     cfp->input_itemID = cds_sfp->idx.itemID;
5271     cfp->input_itemtype = cds_sfp->idx.itemtype;
5272     cfp->this_itemtype = OBJ_SEQFEAT;
5273     cfp->this_subtype = FEATDEF_CDS;
5274 /*    cfp->procid = ompcp->proc->procid;
5275     cfp->proctype = ompcp->proc->proctype;
5276     cfp->userkey = OMGetNextUserKey ();
5277     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
5278                                OMPROC_EDIT, cfp->userkey);
5279     if (omudp != NULL) {
5280       omudp->userdata.ptrvalue = (Pointer) cfp;
5281       omudp->messagefunc = StdVibrantEditorMsgFunc;
5282     } */
5283     SendMessageToForm (cfp->form, VIB_MSG_INIT);
5284     PointerToForm (cfp->form, (Pointer) cds_sfp);
5285     if (SetClosestParentIfDuplicating ((BaseFormPtr) cfp)) {
5286       SetBestProteinFeature (cfp, NULL);
5287       PointerToDialog (cfp->product, NULL);
5288       PointerToDialog (cfp->protseq, NULL);
5289       SetProteinLengthDisplay (cfp->protlen, 0);
5290     }
5291   }
5292   SendMessageToForm (scp->pfp->form, VIB_MSG_CLOSE);
5293   Show (w);
5294   Select (w);
5295   helpfunc = (HelpMessageFunc) GetAppProperty ("HelpMessageProc");
5296   if (helpfunc != NULL) {
5297     helpfunc ("Features", "CDS");
5298   }
5299 }
5300 
5301 static void CleanupCDSSwitchButton (GraphiC g, VoidPtr data)
5302 {
5303   SwitchToCDSPtr    scp;
5304 
5305   scp = (SwitchToCDSPtr) data;
5306   if (scp == NULL) return;
5307   MemFree (scp);  
5308 }
5309 
5310 static DialoG CreateProtDialog (GrouP h, CharPtr title, ProtRefPtr prp, SeqFeatPtr sfp, ProtFormPtr pfp)
5311 
5312 {
5313   GrouP        f;
5314   GrouP        g;
5315   Char         just;
5316   GrouP        k;
5317   GrouP        m;
5318   GrouP        p;
5319   ProtPagePtr  ppp;
5320   GrouP        q;
5321   GrouP        r;
5322   GrouP        s;
5323   Boolean      showXrefs;
5324   GrouP        t;
5325   DialoG       tbs;
5326   ButtoN       b;
5327   SwitchToCDSPtr    scp;
5328 
5329   p = HiddenGroup (h, 1, 0, NULL);
5330   SetGroupSpacing (p, 10, 10);
5331 
5332   ppp = (ProtPagePtr) MemNew (sizeof (ProtPage));
5333   if (ppp != NULL) {
5334 
5335     SetObjectExtra (p, ppp, StdCleanupExtraProc);
5336     ppp->dialog = (DialoG) p;
5337     ppp->todialog = ProtRefPtrToProtPage;
5338     ppp->fromdialog = ProtPageToProtRefPtr;
5339     ppp->testdialog = NULL;
5340 
5341     if (title != NULL && title [0] != '\0') {
5342       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
5343     } else {
5344       s = HiddenGroup (p, 0, -2, NULL);
5345     }
5346     m = HiddenGroup (s, -1, 0, NULL);
5347     SetGroupSpacing (m, 10, 10);
5348 
5349     showXrefs = FALSE;
5350     if (prp != NULL && prp->db != NULL) {
5351       showXrefs = TRUE;
5352     }
5353 
5354     if (showXrefs) {
5355       tbs = CreateFolderTabs (m, protTabsXref, 0, 0, 0,
5356                               PROGRAM_FOLDER_TAB,
5357                               ChangeProtSubPage, (Pointer) ppp);
5358     } else {
5359       tbs = CreateFolderTabs (m, protTabs, 0, 0, 0,
5360                               PROGRAM_FOLDER_TAB,
5361                               ChangeProtSubPage, (Pointer) ppp);
5362     }
5363     k = HiddenGroup (m, 0, 0, NULL);
5364 
5365     ppp->protGrp [0] = HiddenGroup (k, -1, 0, NULL);
5366     g = HiddenGroup (ppp->protGrp [0], 0, 10, NULL);
5367     StaticPrompt (g, "Protein Names", 0, 0, programFont, 'c');
5368     ppp->name = CreateVisibleStringDialog (g, 3, -1, 25);
5369 
5370     pfp->makemRNAMatch = CheckBox (ppp->protGrp [0], "Make overlapping mRNA product match protein name", NULL);
5371     Hide (pfp->makemRNAMatch);
5372     f = HiddenGroup (ppp->protGrp [0], 0, 4, NULL);
5373     StaticPrompt (f, "Description", 0, dialogTextHeight, programFont, 'c');
5374     ppp->desc = DialogText (f, "", 25, NULL);
5375 
5376     r = HiddenGroup (ppp->protGrp [0], 2, 0, NULL);
5377     StaticPrompt (r, "Processing", 0, dialogTextHeight, programFont, 'l');
5378     ppp->processed = PopupList (r, TRUE, ChangeProtProcessed);
5379     SetObjectExtra (ppp->processed, (Pointer) pfp, NULL);
5380     PopupItem (ppp->processed, " ");
5381     PopupItem (ppp->processed, "Proprotein");
5382     PopupItem (ppp->processed, "Mature");
5383     PopupItem (ppp->processed, "Signal peptide");
5384     PopupItem (ppp->processed, "Transit peptide");
5385     SetValue (ppp->processed, 1);
5386 
5387     pfp->product = CreateProteinOrMRNAProductDialog (ppp->protGrp [0], NULL, "Processing Product", FALSE,
5388                                                      pfp->sep, NULL, NULL, (BaseFormPtr) pfp);
5389     if (sfp == NULL || sfp->product == NULL) {
5390       if (prp == NULL || prp->processed < 2) {
5391         SafeHide (pfp->product);
5392       }
5393     }
5394     
5395     /* button for switching to CDS editor */
5396     if (GetAppProperty ("InternalNcbiSequin") != NULL)
5397     {
5398       scp = (SwitchToCDSPtr) MemNew (sizeof (SwitchToCDSData));
5399       if (scp != NULL)
5400       {
5401         scp->sfp = sfp;
5402         scp->pfp = pfp;
5403         b = PushButton (ppp->protGrp [0], "Switch to CDS Feature Editor", LaunchCDSEditorFromProtDialog);
5404         SetObjectExtra (b, (Pointer) scp, CleanupCDSSwitchButton);    
5405       }
5406     }
5407 
5408     ppp->protGrp [1] = HiddenGroup (k, 0, 10, NULL);
5409     StaticPrompt (ppp->protGrp [1], "Enzyme Commission Number", 0, 0, programFont, 'c');
5410     ppp->ec = CreateVisibleStringDialog (ppp->protGrp [1], 3, -1, 15);
5411     Hide (ppp->protGrp [1]);
5412 
5413     ppp->protGrp [2] = HiddenGroup (k, 0, 10, NULL);
5414     StaticPrompt (ppp->protGrp [2], "Activity", 0, 0, programFont, 'c');
5415     ppp->activity = CreateVisibleStringDialog (ppp->protGrp [2], 3, -1, 25);
5416     Hide (ppp->protGrp [2]);
5417 
5418     ppp->protGrp [3] = HiddenGroup (k, -1, 0, NULL);
5419     if (showXrefs) {
5420       q = HiddenGroup (ppp->protGrp [3], -1, 0, NULL);
5421       if (GetAppProperty ("ReadOnlyDbTags") == NULL) {
5422         just = 'c';
5423       } else {
5424         just = 'l';
5425         StaticPrompt (q, "This page is read-only", 15 * stdCharWidth, 0, programFont, 'c');
5426       }
5427       t = HiddenGroup (q, 2, 0, NULL);
5428       StaticPrompt (t, "Database", 7 * stdCharWidth, 0, programFont, just);
5429       StaticPrompt (t, "Object ID", 8 * stdCharWidth, 0, programFont, just);
5430       ppp->db = CreateDbtagDialog (q, 3, -1, 7, 8);
5431     }
5432     Hide (ppp->protGrp [3]);
5433 
5434     AlignObjects (ALIGN_CENTER, (HANDLE) ppp->protGrp [0],
5435                   (HANDLE) ppp->protGrp [1], (HANDLE) ppp->protGrp [2],
5436                   (HANDLE) ppp->protGrp [3], (HANDLE) tbs,
5437                   (HANDLE) g, (HANDLE) r, NULL);
5438   }
5439 
5440   return (DialoG) p;
5441 }
5442 
5443 static void SetProtImportExportItems (ProtFormPtr pfp)
5444 
5445 {
5446   IteM  exportItm;
5447   IteM  importItm;
5448 
5449   if (pfp != NULL) {
5450     importItm = FindFormMenuItem ((BaseFormPtr) pfp, VIB_MSG_IMPORT);
5451     exportItm = FindFormMenuItem ((BaseFormPtr) pfp, VIB_MSG_EXPORT);
5452     switch (pfp->currentPage) {
5453       case PROT_PAGE :
5454         SafeSetTitle (importItm, "Import...");
5455         SafeSetTitle (exportItm, "Export...");
5456         SafeDisable (importItm);
5457         SafeDisable (exportItm);
5458         break;
5459       case COMMON_PAGE :
5460         SafeSetTitle (importItm, "Import...");
5461         SafeSetTitle (exportItm, "Export...");
5462         SafeDisable (importItm);
5463         SafeDisable (exportItm);
5464         break;
5465       case LOCATION_PAGE :
5466         SafeSetTitle (importItm, "Import SeqLoc...");
5467         SafeSetTitle (exportItm, "Export SeqLoc...");
5468         SafeEnable (importItm);
5469         SafeEnable (exportItm);
5470         break;
5471       default :
5472         break;
5473     }
5474   }
5475 }
5476 
5477 static void ChangeProtPage (VoidPtr data, Int2 newval, Int2 oldval)
5478 
5479 {
5480   ProtFormPtr   pfp;
5481 
5482   pfp = (ProtFormPtr) data;
5483   if (pfp != NULL) {
5484     pfp->currentPage = newval;
5485     SafeHide (pfp->pages [oldval]);
5486     SafeShow (pfp->pages [newval]);
5487     switch (newval) {
5488       case PROT_PAGE :
5489         SendMessageToDialog (pfp->data, VIB_MSG_ENTER);
5490         break;
5491       case COMMON_PAGE :
5492         break;
5493       case LOCATION_PAGE :
5494         SendMessageToDialog (pfp->location, VIB_MSG_ENTER);
5495         break;
5496       default :
5497         break;
5498     }
5499     SetProtImportExportItems (pfp);
5500     Update ();
5501   }
5502 }
5503 
5504 static Boolean ImportProtForm (ForM f, CharPtr filename)
5505 
5506 {
5507   ProtFormPtr  pfp;
5508 
5509   pfp = (ProtFormPtr) GetObjectExtra (f);
5510   if (pfp != NULL) {
5511     switch (pfp->currentPage) {
5512       case LOCATION_PAGE :
5513         return ImportDialog (pfp->location, filename);
5514       default :
5515         break;
5516     }
5517   }
5518   return FALSE;
5519 }
5520 
5521 static Boolean ExportProtForm (ForM f, CharPtr filename)
5522 
5523 {
5524   ProtFormPtr  pfp;
5525 
5526   pfp = (ProtFormPtr) GetObjectExtra (f);
5527   if (pfp != NULL) {
5528     switch (pfp->currentPage) {
5529       case LOCATION_PAGE :
5530         return ExportDialog (pfp->location, filename);
5531       default :
5532         break;
5533     }
5534   }
5535   return FALSE;
5536 }
5537 
5538 static CharPtr  protFormTabs [] = {
5539   "Protein", "Properties", "Location", NULL
5540 };
5541 
5542 static void ProtFormMessage (ForM f, Int2 mssg)
5543 
5544 {
5545   ProtFormPtr  pfp;
5546 
5547   pfp = (ProtFormPtr) GetObjectExtra (f);
5548   if (pfp != NULL) {
5549     switch (mssg) {
5550       case VIB_MSG_INIT :
5551         StdInitFeatFormProc (f);
5552         break;
5553       case VIB_MSG_IMPORT :
5554         ImportProtForm (f, NULL);
5555         break;
5556       case VIB_MSG_EXPORT :
5557         ExportProtForm (f, NULL);
5558         break;
5559       case VIB_MSG_CLOSE :
5560         Remove (f);
5561         break;
5562       case VIB_MSG_CUT :
5563         StdCutTextProc (NULL);
5564         break;
5565       case VIB_MSG_COPY :
5566         StdCopyTextProc (NULL);
5567         break;
5568       case VIB_MSG_PASTE :
5569         StdPasteTextProc (NULL);
5570         break;
5571       case VIB_MSG_DELETE :
5572         if (pfp->currentPage == LOCATION_PAGE) {
5573           PointerToDialog (pfp->location, NULL);
5574         } else {
5575           StdDeleteTextProc (NULL);
5576         }
5577         break;
5578       default :
5579         if (pfp->appmessage != NULL) {
5580           pfp->appmessage (f, mssg);
5581         }
5582         break;
5583     }
5584   }
5585 }
5586 
5587 static void ProtFormActivate (WindoW w)
5588 
5589 {
5590   ProtFormPtr  pfp;
5591 
5592   pfp = (ProtFormPtr) GetObjectExtra (w);
5593   if (pfp != NULL) {
5594     if (pfp->activate != NULL) {
5595       pfp->activate (w);
5596     }
5597     SetProtImportExportItems (pfp);
5598   }
5599 }
5600 
5601 static void ShowHideMakemRNAMatch (ProtFormPtr pfp, SeqFeatPtr sfp)
5602 {
5603   BioseqPtr  bsp;
5604   SeqFeatPtr cds, mrna;
5605   SeqMgrFeatContext fcontext;
5606   if (pfp == NULL) return;
5607 
5608   if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT) {
5609     Hide (pfp->makemRNAMatch);
5610   } else {
5611     /* look for overlapping mRNA */
5612     bsp = BioseqFindFromSeqLoc (sfp->location);
5613     cds = SeqMgrGetCDSgivenProduct (bsp, &fcontext);
5614     if (cds == NULL) {
5615       Hide (pfp->makemRNAMatch);
5616     } else {
5617       mrna = SeqMgrGetOverlappingmRNA (cds->location, &fcontext);
5618       if (mrna == NULL) {
5619         Hide (pfp->makemRNAMatch);
5620       } else {
5621         Show (pfp->makemRNAMatch);
5622       }
5623     }
5624   }
5625 }
5626 
5627 
5628 static void ProtRefPtrToForm (ForM f, Pointer data)
5629 
5630 {
5631   SeqEntryPtr  oldsep;
5632   ProtFormPtr  pfp;
5633   SeqEntryPtr  sep;
5634   SeqFeatPtr   sfp;
5635   Int4         val;
5636 
5637   pfp = (ProtFormPtr) GetObjectExtra (f);
5638   if (pfp != NULL) {
5639     sep = GetTopSeqEntryForEntityID (pfp->input_entityID);
5640     oldsep = SeqEntrySetScope (sep);
5641     sfp = (SeqFeatPtr) data;
5642     if (sfp != NULL) {
5643       switch (sfp->data.choice) {
5644         case SEQFEAT_BOND :
5645         case SEQFEAT_SITE :
5646         case SEQFEAT_PSEC_STR :
5647           val = (Int4) sfp->data.value.intvalue;
5648           PointerToDialog (pfp->data, (Pointer) &(val));
5649           break;
5650         case SEQFEAT_COMMENT:
5651           break;
5652         default :
5653           PointerToDialog (pfp->data, sfp->data.value.ptrvalue);
5654           break;
5655       }
5656       SeqFeatPtrToCommon ((FeatureFormPtr) pfp, sfp);
5657       PointerToDialog (pfp->location, sfp->location);
5658       PointerToDialog (pfp->product, sfp->product);
5659     }
5660     ShowHideMakemRNAMatch (pfp, sfp);
5661     SeqEntrySetScope (oldsep);
5662   }
5663 }
5664 
5665 extern ForM CreateProtForm (Int2 left, Int2 top, CharPtr title,
5666                             SeqFeatPtr sfp, SeqEntryPtr sep,
5667                             FormActnFunc actproc)
5668 
5669 {
5670   ButtoN             b;
5671   GrouP              c;
5672   GrouP              g;
5673   GrouP              h;
5674   ProtFormPtr        pfp;
5675   ProtRefPtr         prp;
5676   GrouP              s;
5677   StdEditorProcsPtr  sepp;
5678   WindoW             w;
5679 
5680   w = NULL;
5681   pfp = (ProtFormPtr) MemNew (sizeof (ProtForm));
5682   if (pfp != NULL) {
5683     w = FixedWindow (left, top, -10, -10, title, StdCloseWindowProc);
5684     SetObjectExtra (w, pfp, StdFeatFormCleanupProc);
5685     pfp->form = (ForM) w;
5686     pfp->actproc = actproc;
5687     pfp->toform = ProtRefPtrToForm;
5688     pfp->fromform = NULL;
5689     pfp->formmessage = ProtFormMessage;
5690     pfp->testform = NULL;
5691     pfp->importform = ImportProtForm;
5692     pfp->exportform = ExportProtForm;
5693 
5694 #ifndef WIN_MAC
5695     CreateStdEditorFormMenus (w);
5696 #endif
5697 
5698     pfp->activate = NULL;
5699     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
5700     if (sepp != NULL) {
5701       pfp->activate = sepp->activateForm;
5702       pfp->appmessage = sepp->handleMessages;
5703     }
5704     SetActivate (w, ProtFormActivate);
5705 
5706     g = HiddenGroup (w, -1, 0, NULL);
5707     SetGroupSpacing (g, 3, 10);
5708 
5709     pfp->sep = sep;
5710     pfp->foldertabs = CreateFolderTabs (g, protFormTabs, PROT_PAGE,
5711                                         0, 0, SYSTEM_FOLDER_TAB,
5712                                         ChangeProtPage, (Pointer) pfp);
5713     pfp->currentPage = PROT_PAGE;
5714 
5715     h = HiddenGroup (g, 0, 0, NULL);
5716 
5717     s = HiddenGroup (h, -1, 0, NULL);
5718     prp = NULL;
5719     if (sfp != NULL && sfp->data.choice == SEQFEAT_PROT) {
5720       prp = sfp->data.value.ptrvalue;
5721     }
5722     pfp->data = CreateProtDialog (s, NULL, prp, sfp, pfp);
5723     pfp->pages [PROT_PAGE] = s;
5724     Hide (pfp->pages [PROT_PAGE]);
5725 
5726     s = HiddenGroup (h, -1, 0, NULL);
5727     CreateCommonFeatureGroupEx (s, (FeatureFormPtr) pfp, sfp, FALSE, TRUE, FALSE);
5728     pfp->pages [COMMON_PAGE] = s;
5729     Hide (pfp->pages [COMMON_PAGE]);
5730 
5731     s = HiddenGroup (h, -1, 0, NULL);
5732     pfp->location = CreateIntervalEditorDialogEx (s, NULL, 4, 2, sep, FALSE, TRUE,
5733                                                   TRUE, TRUE, FALSE,
5734                                                   (FeatureFormPtr) pfp,
5735                                                   StdFeatIntEdPartialCallback);
5736     pfp->pages [LOCATION_PAGE] = s;
5737     Hide (pfp->pages [LOCATION_PAGE]);
5738 
5739     AlignObjects (ALIGN_CENTER, (HANDLE) pfp->pages [PROT_PAGE],
5740                   (HANDLE) pfp->pages [COMMON_PAGE], (HANDLE) pfp->pages [LOCATION_PAGE],
5741                   NULL);
5742     AlignObjects (ALIGN_CENTER, (HANDLE) pfp->foldertabs, (HANDLE) h, NULL);
5743 
5744     c = HiddenGroup (w, 2, 0, NULL);
5745     b = PushButton (c, "Accept", StdFeatFormAcceptButtonProc);
5746     SetObjectExtra (b, pfp, NULL);
5747     PushButton (c, "Cancel", StdCancelButtonProc);
5748     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
5749     RealizeWindow (w);
5750 
5751     SendMessageToDialog (pfp->data, VIB_MSG_INIT);
5752     SendMessageToDialog (pfp->location, VIB_MSG_INIT);
5753     Show (pfp->pages [pfp->currentPage]);
5754     SendMessageToDialog (pfp->data, VIB_MSG_ENTER);
5755     Update ();
5756   }
5757   return (ForM) w;
5758 }
5759 
5760 
5761 static void MakemRNAProductMatchProteinName (SeqFeatPtr prot)
5762 {
5763   BioseqPtr    bsp;
5764   ProtRefPtr   prp;
5765   SeqFeatPtr   cds, mrna;
5766   RnaRefPtr    rrp;
5767   SeqMgrFeatContext fcontext;
5768 
5769   if (prot == NULL || prot->data.choice != SEQFEAT_PROT) return;
5770   bsp = BioseqFindFromSeqLoc (prot->location);
5771   if (bsp == NULL) return;
5772 
5773   cds = SeqMgrGetCDSgivenProduct (bsp, &fcontext);
5774   if (cds != NULL) {
5775     mrna = SeqMgrGetOverlappingmRNA (cds->location, &fcontext);      
5776     if (mrna != NULL && mrna->idx.subtype == FEATDEF_mRNA) {
5777       rrp = (RnaRefPtr) mrna->data.value.ptrvalue;
5778       if (rrp == NULL) {
5779         rrp = RnaRefNew();
5780         mrna->data.value.ptrvalue = rrp;
5781       }
5782       rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
5783       prp = (ProtRefPtr) prot->data.value.ptrvalue;
5784       if (prp == NULL || prp->name == NULL || StringHasNoText (prp->name->data.ptrvalue)) {
5785         rrp->ext.choice = 0;
5786       } else {
5787         rrp->ext.choice = 1;
5788         rrp->ext.value.ptrvalue = StringSave (prp->name->data.ptrvalue);
5789       }
5790     }
5791   }
5792 }
5793 
5794 
5795 static void ProtFeatFormActnProc (ForM f)
5796 
5797 {
5798   BioseqPtr    bsp;
5799   ProtFormPtr  pfp;
5800   SeqFeatPtr   sfp;
5801   Boolean      need_update = FALSE;
5802 
5803   StdFeatFormActnProc (f);
5804   pfp = (ProtFormPtr) GetObjectExtra (f);
5805   if (pfp == NULL) return;
5806   
5807   sfp = SeqMgrGetDesiredFeature (pfp->input_entityID, NULL,
5808                                  pfp->input_itemID, 0, NULL, NULL);
5809   if (sfp == NULL) return;
5810 
5811   bsp = BioseqFindFromSeqLoc (sfp->location);
5812   if (bsp == NULL) return;
5813 
5814   if (GetStatus (pfp->makemRNAMatch)) {    
5815     MakemRNAProductMatchProteinName (sfp);
5816     need_update = TRUE;
5817   }
5818 
5819   if (SeeIfProtTitleNeedsFixing (bsp, pfp->input_entityID)) {
5820     need_update = TRUE;
5821   }
5822   if (need_update) {
5823     ObjMgrSendMsg (OM_MSG_UPDATE, pfp->input_entityID,
5824                    pfp->input_itemID, pfp->input_itemtype);
5825   }  
5826 }
5827 
5828 extern Int2 LIBCALLBACK ProtGenFunc (Pointer data)
5829 
5830 {
5831   ProtFormPtr       pfp;
5832   HelpMessageFunc   helpfunc;
5833   ObjMgrPtr         omp;
5834   OMProcControlPtr  ompcp;
5835   ObjMgrTypePtr     omtp;
5836   OMUserDataPtr     omudp;
5837   ProtPagePtr       ppp;
5838   ObjMgrProcPtr     proc;
5839   SeqEntryPtr       sep;
5840   SeqFeatPtr        sfp;
5841   Uint2             subtype;
5842   WindoW            w;
5843 
5844   ompcp = (OMProcControlPtr) data;
5845   sfp = NULL;
5846   sep = NULL;
5847   subtype = FEATDEF_PROT;
5848   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
5849   proc = ompcp->proc;
5850   switch (ompcp->input_itemtype) {
5851     case OBJ_SEQFEAT :
5852       sfp = (SeqFeatPtr) ompcp->input_data;
5853       if (sfp != NULL && sfp->data.choice != SEQFEAT_PROT) {
5854         return OM_MSG_RET_ERROR;
5855       }
5856       break;
5857     case OBJ_BIOSEQ :
5858       break;
5859     case OBJ_BIOSEQSET :
5860       break;
5861     case 0 :
5862       break;
5863     default :
5864       return OM_MSG_RET_ERROR;
5865   }
5866   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
5867                                 ompcp->input_itemtype, ompcp->proc->procid);
5868   if (omudp != NULL) {
5869     pfp = (ProtFormPtr) omudp->userdata.ptrvalue;
5870     if (pfp != NULL) {
5871       Select (pfp->form);
5872     }
5873     return OM_MSG_RET_DONE;
5874   }
5875   if (sfp == NULL && proc->subinputtype > 0) {
5876     subtype = proc->subinputtype;
5877   }
5878   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
5879   w = (WindoW) CreateProtForm (-50, -33, "Protein", sfp, sep,
5880                                ProtFeatFormActnProc);
5881   pfp = (ProtFormPtr) GetObjectExtra (w);
5882   if (pfp != NULL) {
5883     pfp->input_entityID = ompcp->input_entityID;
5884     pfp->input_itemID = ompcp->input_itemID;
5885     pfp->input_itemtype = ompcp->input_itemtype;
5886     pfp->this_itemtype = OBJ_SEQFEAT;
5887     pfp->this_subtype = subtype;
5888     pfp->procid = ompcp->proc->procid;
5889     pfp->proctype = ompcp->proc->proctype;
5890     pfp->userkey = OMGetNextUserKey ();
5891     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
5892                                OMPROC_EDIT, pfp->userkey);
5893     if (omudp != NULL) {
5894       omudp->userdata.ptrvalue = (Pointer) pfp;
5895       omudp->messagefunc = StdVibrantEditorMsgFunc;
5896     }
5897     if (sfp != NULL) {
5898       omp = ObjMgrGet ();
5899       if (omp != NULL) {
5900         omtp = ObjMgrTypeFind (omp, OBJ_SEQFEAT, NULL, NULL);
5901         if (omtp != NULL && omtp->subtypefunc != NULL) {
5902           pfp->this_subtype = (*(omtp->subtypefunc)) (sfp);
5903         }
5904       }
5905     }
5906     SendMessageToForm (pfp->form, VIB_MSG_INIT);
5907     if (sfp != NULL) {
5908       PointerToForm (pfp->form, (Pointer) sfp);
5909       SetClosestParentIfDuplicating ((BaseFormPtr) pfp);
5910     } else {
5911       ppp = (ProtPagePtr) GetObjectExtra (pfp->data);
5912       if (ppp != NULL) {
5913         if (subtype == FEATDEF_PROT) {
5914           SetValue (ppp->processed, 1);
5915         } else if (subtype >= FEATDEF_preprotein && subtype <= FEATDEF_transit_peptide_aa) {
5916           SetValue (ppp->processed, subtype - FEATDEF_preprotein + 2);
5917         } else {
5918           SetValue (ppp->processed, 1);
5919         }
5920       }
5921       SetNewFeatureDefaultInterval ((FeatureFormPtr) pfp);
5922     }
5923   }
5924   Show (w);
5925   Select (w);
5926   helpfunc = (HelpMessageFunc) GetAppProperty ("HelpMessageProc");
5927   if (helpfunc != NULL) {
5928     helpfunc ("Features", "Protein");
5929   }
5930   return OM_MSG_RET_DONE;
5931 }
5932 
5933 /* rnaform and rnapage moved to top */
5934 
5935 static ENUM_ALIST(rna_type_alist)
5936   {" ",            0},
5937   {"preRna",       1},
5938   {"mRNA",         2},
5939   {"tRNA",         3},
5940   {"rRNA",         4},
5941   {"ncRNA",        8},
5942   {"tmRNA",        9},
5943   {"misc_RNA",     10},
5944   {"otherRNA",    255},
5945 END_ENUM_ALIST
5946 
5947 static Uint1 check_rna_type (Uint1 type)
5948 
5949 {
5950   if (type > 10 && type != 255) return 0;
5951   return type;
5952 }
5953 
5954 typedef struct mrnauserpage {
5955   DIALOG_MESSAGE_BLOCK
5956   DialoG        protein;
5957 } MrnaUserData, PNTR MrnaUserPtr;
5958 
5959 static void UserObjectPtrToProtein (DialoG d, Pointer data)
5960 
5961 {
5962   MrnaUserPtr    mup;
5963   ObjectIdPtr    oip;
5964   SeqIdPtr       sip;
5965   CharPtr        str;
5966   UserFieldPtr   ufp;
5967   UserObjectPtr  uop;
5968   ValNode        vn;
5969 
5970   mup = (MrnaUserPtr) GetObjectExtra (d);
5971   /* uop = (UserObjectPtr) data; */
5972   if (mup != NULL) {
5973     uop = FindUopByTag ((UserObjectPtr) data, "MrnaProteinLink");
5974     if (uop != NULL && uop->type != NULL && StringICmp (uop->type->str, "MrnaProteinLink") == 0) {
5975       ufp = uop->data;
5976       if (ufp != NULL && ufp->choice == 1) {
5977         oip = ufp->label;
5978         if (oip != NULL && oip->str != NULL && StringICmp (oip->str, "protein seqID") == 0) {
5979           str = (CharPtr) ufp->data.ptrvalue;
5980           if (str != NULL) {
5981             sip = MakeSeqID (str);
5982             if (sip != NULL) {
5983               vn.choice = SEQLOC_WHOLE;
5984               vn.data.ptrvalue = (Pointer) sip;
5985               PointerToDialog (mup->protein, (Pointer) (&vn));
5986               SeqIdFree (sip);
5987               return;
5988             }
5989           }
5990         }
5991       }
5992     }
5993     PointerToDialog (mup->protein, NULL);
5994   }
5995 }
5996 
5997 static Pointer ProteinToUserObjectPtr (DialoG d)
5998 
5999 {
6000   BioseqPtr      bsp;
6001   MrnaUserPtr    mup;
6002   SeqIdPtr       sip;
6003   SeqLocPtr      slp;
6004   UserObjectPtr  uop;
6005 
6006   uop = NULL;
6007   mup = (MrnaUserPtr) GetObjectExtra (d);
6008   if (mup != NULL) {
6009     slp = DialogToPointer (mup->protein);
6010     if (slp != NULL) {
6011       sip = SeqLocId (slp);
6012       if (sip != NULL) {
6013         bsp = BioseqFind (sip);
6014         if (bsp != NULL) {
6015           uop = CreateMrnaProteinLinkUserObject (bsp);
6016         }
6017       }
6018       SeqLocFree (slp);
6019     }
6020   }
6021   return (Pointer) uop;
6022 }
6023 
6024 static DialoG CreateMrnaUserObjectDialog (GrouP h, CharPtr label, SeqEntryPtr sep, BaseFormPtr bfp)
6025 
6026 {
6027   MrnaUserPtr  mup;
6028   GrouP        p;
6029 
6030   p = HiddenGroup (h, -1, 0, NULL);
6031   SetGroupSpacing (p, 10, 10);
6032 
6033   mup = (MrnaUserPtr) MemNew (sizeof (MrnaUserData));
6034   if (mup != NULL) {
6035     SetObjectExtra (p, mup, StdCleanupExtraProc);
6036     mup->dialog = (DialoG) p;
6037     mup->todialog = UserObjectPtrToProtein;
6038     mup->fromdialog = ProteinToUserObjectPtr;
6039     mup->testdialog = NULL;
6040     mup->protein = CreateProteinOrMRNAProductDialog (p, NULL, label, FALSE, sep, NULL, NULL, bfp);
6041   }
6042 
6043   return (DialoG) p;
6044 }
6045 
6046 
6047 static Uint1 RnaFeatDefFromRnaRef (RnaRefPtr rrp)
6048 {
6049   if (rrp == NULL) {
6050     return FEATDEF_otherRNA;
6051   }
6052 
6053   switch (rrp->type) 
6054   {
6055     case 1:
6056       return FEATDEF_preRNA;
6057       break;
6058     case 2:
6059       return FEATDEF_mRNA;
6060       break;
6061     case 3:
6062       return FEATDEF_tRNA;
6063       break;
6064     case 4:
6065       return FEATDEF_rRNA;
6066       break;
6067     case 5:
6068       return FEATDEF_snRNA;
6069       break;
6070     case 6:
6071       return FEATDEF_scRNA;
6072       break;
6073     case 7:
6074       return FEATDEF_snoRNA;
6075       break;
6076     case 8:
6077       return FEATDEF_ncRNA;
6078       break;
6079     case 9:
6080       return FEATDEF_tmRNA;
6081       break;
6082     case 10:
6083       return FEATDEF_misc_RNA;
6084       break;
6085 
6086     case 255:
6087     default:
6088       return FEATDEF_otherRNA;
6089       break;
6090   }
6091 }
6092 
6093 
6094 static void RnaRefPtrToRnaPage (DialoG d, Pointer data)
6095 
6096 {
6097   Uint1           aa;
6098   Uint1           codon [4];
6099   Uint1           from;
6100   ValNodePtr      head;
6101   Uint1           i;
6102   Int2            j;
6103   RnaPagePtr      rpp;
6104   RnaRefPtr       rrp;
6105   Uint1           shift;
6106   SeqMapTablePtr  smtp;
6107   Char            str [8];
6108   tRNAPtr         trna;
6109   ValNodePtr      vnp;
6110   RNAGenPtr       rgp;
6111   CharPtr         tag_peptide;
6112   CharPtr         product;
6113 
6114   rpp = (RnaPagePtr) GetObjectExtra (d);
6115   rrp = (RnaRefPtr) data;
6116 
6117   if (rrp != NULL) {
6118 
6119     SetEnumPopup (rpp->type, rna_type_alist, rrp->type);
6120     SafeSetStatus (rpp->pseudo, rrp->pseudo);
6121     switch (rrp->type) {
6122       case 0 :
6123         SafeHide (rpp->trnaGrp);
6124         SafeHide (rpp->nameGrp);
6125         SafeHide (rpp->rrnaPrompt);
6126         SafeHide (rpp->ornaPrompt);
6127         SafeHide (rpp->ncrnaGrp);
6128         SafeHide (rpp->tmrnaGrp);
6129         break;
6130       case 3 :
6131         SafeSetTitle (rpp->name, "");
6132         SafeHide (rpp->nameGrp);
6133         SafeHide (rpp->rrnaPrompt);
6134         SafeHide (rpp->ornaPrompt);
6135         SafeHide (rpp->ncrnaGrp);
6136         SafeHide (rpp->tmrnaGrp);
6137         SafeSetValue (rpp->AAitem, 1);
6138         if (rrp->ext.choice == 2) {
6139           trna = rrp->ext.value.ptrvalue;
6140           if (trna != NULL) {
6141             aa = 0;
6142             if (trna->aatype == 2) {
6143               aa = trna->aa;
6144             } else {
6145               from = 0;
6146               switch (trna->aatype) {
6147                 case 0 :
6148                   from = 0;
6149                   break;
6150                 case 1 :
6151                   from = Seq_code_iupacaa;
6152                   break;
6153                 case 2 :
6154                   from = Seq_code_ncbieaa;
6155                   break;
6156                 case 3 :
6157                   from = Seq_code_ncbi8aa;
6158                   break;
6159                 case 4 :
6160                   from = Seq_code_ncbistdaa;
6161                   break;
6162                 default:
6163                   break;
6164               }
6165               smtp = SeqMapTableFind (Seq_code_ncbieaa, from);
6166               if (smtp != NULL) {
6167                 aa = SeqMapTableConvert (smtp, trna->aa);
6168               }
6169             }
6170             if (aa > 0 && aa != 255) {
6171               /*
6172               if (aa <= 74) {
6173                 shift = 0;
6174               } else if (aa > 79) {
6175                 shift = 2;
6176               } else {
6177                 shift = 1;
6178               }
6179               */
6180               shift = 0;
6181               if (aa != '*') {
6182                 i = aa - (64 + shift);
6183               } else {
6184                 i = 25;
6185               }
6186               SetValue (rpp->AAitem, (Int2) i + 1);
6187             }
6188             head = NULL;
6189             for (j = 0; j < 6; j++) {
6190               if (trna->codon [j] < 64) {
6191                 /* Note - it is important to set the fourth character in the codon array to NULL
6192                  * because CodonForIndex only fills in the three characters of actual codon,
6193                  * so if you StringCpy the codon array and the NULL character is not found after
6194                  * the three codon characters, you will write in memory you did not intend to.
6195                  */
6196                 codon [3] = 0;
6197                 if (CodonForIndex (trna->codon [j], Seq_code_iupacna, codon)) {
6198                   StringCpy (str, (CharPtr) codon);
6199                   str [3] = '\0';
6200                   vnp = ValNodeNew (head);
6201                   if (head == NULL) {
6202                     head = vnp;
6203                   }
6204                   if (vnp != NULL) {
6205                     vnp->data.ptrvalue = StringSave (str);
6206                   }
6207                 }
6208               }
6209             }
6210             if (head != NULL) {
6211               PointerToDialog (rpp->codons, head);
6212               ValNodeFreeData (head);
6213             }
6214             if (trna->anticodon == NULL)
6215             {
6216               /* attempt to provide default location */
6217               SeqLocPtr tmp_loc = NULL;
6218               tmp_loc = DialogToPointer (rpp->rfp->location);
6219               PointerToDialog (rpp->anticodon, tmp_loc);
6220               SetSequenceAndStrandForIntervalPage (rpp->anticodon);
6221               SeqLocFree (tmp_loc);              
6222             }
6223             else
6224             {
6225               PointerToDialog (rpp->anticodon, trna->anticodon);                
6226             }
6227           }
6228         }
6229         SafeShow (rpp->trnaGrp);
6230         break;
6231       case 4 :
6232         SafeHide (rpp->trnaGrp);
6233         if (rrp->ext.choice == 1 && rrp->ext.value.ptrvalue != NULL) {
6234           SafeSetTitle (rpp->name, (CharPtr) rrp->ext.value.ptrvalue);
6235         } else {
6236           SafeSetTitle (rpp->name, "");
6237         }
6238         SafeHide (rpp->ornaPrompt);
6239         SafeShow (rpp->rrnaPrompt);
6240         SafeShow (rpp->nameGrp);
6241         SafeHide (rpp->ncrnaGrp);
6242         SafeHide (rpp->tmrnaGrp);
6243         break;
6244       case 5:
6245       case 6:
6246       case 7:
6247       case 8:
6248         SafeHide (rpp->trnaGrp);
6249         SafeHide (rpp->nameGrp);
6250         SafeHide (rpp->rrnaPrompt);
6251         SafeHide (rpp->ornaPrompt);
6252         if (rrp->type == 5) {
6253           PointerToDialog (rpp->ncrnaClass, "snRNA");
6254         } else if (rrp->type == 6) {
6255           PointerToDialog (rpp->ncrnaClass, "scRNA");
6256         } else if (rrp->type == 7) {
6257           PointerToDialog (rpp->ncrnaClass, "snoRNA");
6258         }
6259         SafeHide (rpp->tmrnaGrp);
6260         SafeShow (rpp->ncrnaGrp);
6261         product = GetRNARefProductString (rrp, NULL);
6262         SetTitle (rpp->ncrnaProduct, product);
6263         product = MemFree (product);
6264         if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL 
6265             && rrp->type == 8 && !StringHasNoText (rgp->_class)) {
6266           PointerToDialog (rpp->ncrnaClass, rgp->_class);
6267         }
6268         break;
6269       case 9:
6270         SafeHide (rpp->trnaGrp);
6271         SafeHide (rpp->ornaPrompt);
6272         SafeHide (rpp->rrnaPrompt);
6273         SafeHide (rpp->nameGrp);
6274         SafeHide (rpp->ncrnaGrp);
6275         SafeShow (rpp->tmrnaGrp);
6276         product = GetRNARefProductString (rrp, NULL);
6277         SetTitle (rpp->tmrnaProduct, product);
6278         product = MemFree (product);
6279         if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL) {
6280           tag_peptide = GettmRNATagPeptide (rrp, NULL);
6281           if (tag_peptide != NULL) {
6282             PointerToDialog (rpp->tmrnaTagPeptide, tag_peptide);
6283             tag_peptide = MemFree (tag_peptide);
6284           }
6285         }
6286         break;
6287       case 10 :
6288         SafeHide (rpp->trnaGrp);
6289         SafeShow (rpp->nameGrp);
6290         SafeShow (rpp->rrnaPrompt);
6291         SafeHide (rpp->ncrnaGrp);
6292         SafeHide (rpp->tmrnaGrp);
6293         SafeHide (rpp->ornaPrompt);
6294         product = GetRNARefProductString (rrp, NULL);
6295         SetTitle (rpp->name, product);
6296         product = MemFree (product);
6297         break;
6298       default :
6299         SafeHide (rpp->trnaGrp);
6300         product = GetRNARefProductString (rrp, NULL);
6301         SetTitle (rpp->name, product);
6302         product = MemFree (product);
6303         SafeHide (rpp->rrnaPrompt);
6304         SafeHide (rpp->ornaPrompt);
6305         SafeShow (rpp->nameGrp);
6306         SafeHide (rpp->ncrnaGrp);
6307         SafeHide (rpp->tmrnaGrp);
6308         break;
6309     }
6310   } else {
6311     SetEnumPopup (rpp->type, rna_type_alist, (UIEnum) 0);
6312     SafeSetStatus (rpp->pseudo, FALSE);
6313     SafeSetTitle (rpp->name, "");
6314     SafeHide (rpp->nameGrp);
6315     SafeHide (rpp->rrnaPrompt);
6316     SafeHide (rpp->ornaPrompt);
6317     SafeSetValue (rpp->AAitem, 0);
6318     SafeHide (rpp->trnaGrp);
6319     SafeHide (rpp->ncrnaGrp);
6320     SafeHide (rpp->tmrnaGrp);
6321   }
6322 }
6323 
6324 static Pointer RnaPageToRnaRefPtr (DialoG d)
6325 
6326 {
6327   Char        ch;
6328   Uint1       code;
6329   Uint1       codon [4];
6330   Boolean     degenerate;
6331   ValNodePtr  head;
6332   Int2        i;
6333   Int2        j;
6334   Int2        k;
6335   Int2        q;
6336   RnaPagePtr  rpp;
6337   RnaRefPtr   rrp;
6338   Uint1       shift;
6339   Char        str [8];
6340   tRNAPtr     trna;
6341   UIEnum      val;
6342   ValNodePtr  vnp;
6343   RNAGenPtr   rgp;
6344   CharPtr     tmp;
6345 
6346   rrp = NULL;
6347   rpp = (RnaPagePtr) GetObjectExtra (d);
6348   if (rpp != NULL) {
6349     rrp = RnaRefNew ();
6350     if (rrp != NULL) {
6351       if (GetEnumPopup (rpp->type, rna_type_alist, &val)) {
6352         rrp->type = (Uint1) val;
6353       }
6354       rrp->pseudo = GetStatus (rpp->pseudo);
6355       switch (val) {
6356         case 3 :
6357           rrp->ext.choice = 2;
6358           trna = (tRNAPtr) MemNew (sizeof (tRNA));
6359           rrp->ext.value.ptrvalue = (Pointer) trna;
6360           if (trna != NULL) {
6361             i = GetValue (rpp->AAitem) - 1;
6362             if (i > 0) {
6363               trna->aatype = 2;
6364               /*
6365               if (i < 10) {
6366                 shift = 0;
6367               } else if (i > 13) {
6368                 shift = 2;
6369               } else {
6370                 shift = 1;
6371               }
6372               */
6373               shift = 0;
6374               trna->aa = (Uint1) i + 64 + shift;
6375               if (trna->aa == 91) {
6376                 trna->aa = (Uint1) '*';
6377               }
6378             }
6379             for (j = 0; j < 6; j++) {
6380               trna->codon [j] = 255;
6381             }
6382             head = (ValNodePtr) DialogToPointer (rpp->codons);
6383             if (head != NULL) {
6384               for (vnp = head, j = 0; vnp != NULL && j < 6; vnp = vnp->next) {
6385                 str [0] = '\0';
6386                 StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
6387                 if (str [0] != '\0') {
6388                   degenerate = FALSE;
6389                   k = 0;
6390                   q = 0;
6391                   ch = str [k];
6392                   while (ch != '\0' && q < 3) {
6393                     ch = TO_UPPER (ch);
6394                     if (ch == 'U') {
6395                       ch = 'T';
6396                     }
6397                     if (StringChr ("ACGT", ch) == NULL) {
6398                       degenerate = TRUE;
6399                     }
6400                     codon [q] = (Uint1) ch;
6401                     q++;
6402                     k++;
6403                     ch = str [k];
6404                   }
6405                   codon [q] = 0;
6406                   if (q == 3) {
6407                     if (degenerate) {
6408                       ParseDegenerateCodon (trna, codon);
6409                     } else {
6410                       code = IndexForCodon (codon, Seq_code_iupacna);
6411                       if (code != INVALID_RESIDUE) {
6412                         trna->codon [j] = code;
6413                       }
6414                     }
6415                   }
6416                   j++;
6417                 }
6418               }
6419               ValNodeFreeData (head);
6420             }
6421             trna->anticodon = DialogToPointer (rpp->anticodon);
6422           }
6423           break;
6424         case 5:
6425         case 6:
6426         case 7:
6427         case 8: /* ncRNA */
6428           rgp = RNAGenNew ();
6429           rgp->_class = DialogToPointer (rpp->ncrnaClass);
6430           rgp->product = SaveStringFromText (rpp->ncrnaProduct);
6431           rrp->ext.choice = 3;
6432           rrp->ext.value.ptrvalue = rgp;
6433           break;
6434         case 9: /* tmRNA */
6435           rgp = RNAGenNew ();
6436           rrp->ext.choice = 3;
6437           rrp->ext.value.ptrvalue = rgp;
6438           if (!TextHasNoText (rpp->tmrnaProduct)) {
6439             rgp->product = SaveStringFromText (rpp->tmrnaProduct);
6440           }
6441           tmp = DialogToPointer (rpp->tmrnaTagPeptide);
6442           if (!StringHasNoText (tmp)) {
6443             SettmRNATagPeptide (rrp, NULL, tmp, ExistingTextOption_replace_old);
6444           }
6445           tmp = MemFree (tmp);
6446           break;
6447         case 10:
6448           rgp = RNAGenNew ();
6449           rgp->product = SaveStringFromText (rpp->name);
6450           rrp->ext.choice = 3;
6451           rrp->ext.value.ptrvalue = rgp;
6452           break;
6453         case 255:
6454         default :
6455           if (! TextHasNoText (rpp->name)) {
6456             rrp->ext.choice = 1;
6457             rrp->ext.value.ptrvalue = SaveStringFromText (rpp->name);
6458           }
6459           break;
6460       }
6461     }
6462   }
6463   return (Pointer) rrp;
6464 }
6465 
6466 
6467 static GBQualPtr FindOrAddQual (SeqFeatPtr sfp, CharPtr qual_name)
6468 {
6469   GBQualPtr gbq;
6470 
6471   if (sfp == NULL) return NULL;
6472   gbq = sfp->qual;
6473   while (gbq != NULL && StringCmp (gbq->qual, qual_name) != 0) {
6474     gbq = gbq->next;
6475   }
6476   if (gbq == NULL) {
6477     gbq = GBQualNew ();
6478     gbq->qual = StringSave (qual_name);
6479     gbq->next = sfp->qual;
6480     sfp->qual = gbq;
6481   }
6482   return gbq;
6483 }
6484 
6485 
6486 static void RemoveQualByName (SeqFeatPtr sfp, CharPtr qual_name)
6487 {
6488   GBQualPtr gbq, gbq_next, gbq_prev = NULL;
6489 
6490   if (sfp == NULL || StringHasNoText (qual_name))
6491   {
6492     return;
6493   }
6494   gbq = sfp->qual;
6495   while (gbq != NULL)
6496   {
6497     gbq_next = gbq->next;
6498     if (StringCmp (gbq->qual, qual_name) == 0)
6499     {
6500       if (gbq_prev == NULL)
6501       {
6502         sfp->qual = gbq->next;
6503       }
6504       else
6505       {
6506         gbq_prev->next = gbq->next;
6507       }
6508       gbq->next = NULL;
6509       gbq = GBQualFree (gbq);
6510     }
6511     else
6512     {
6513       gbq_prev = gbq;
6514     }
6515     gbq = gbq_next;
6516   }
6517 }
6518 
6519 extern void ConvertProductQualToRnaRefName (SeqFeatPtr sfp)
6520 {
6521   RnaRefPtr rrp;
6522   GBQualPtr gbq, gbq_prev = NULL;
6523 
6524   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || sfp->data.value.ptrvalue == NULL) return;
6525   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
6526 
6527   gbq = sfp->qual;
6528   while (gbq != NULL && StringCmp (gbq->qual, "product") != 0) {
6529     gbq_prev = gbq;
6530     gbq = gbq->next;
6531   }
6532   if (gbq != NULL) {
6533     rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
6534     rrp->ext.choice = 1;
6535     rrp->ext.value.ptrvalue = gbq->val;
6536     gbq->val = NULL;
6537     if (gbq_prev == NULL) {
6538       sfp->qual = gbq->next;
6539     } else {
6540       gbq_prev->next = gbq->next;
6541     }
6542     gbq->next = NULL;
6543     gbq = GBQualFree (gbq);
6544   }
6545 }
6546 
6547 
6548 static void ConvertRnaRefNameToProductQual (SeqFeatPtr sfp)
6549 {
6550   RnaRefPtr rrp;
6551   GBQualPtr gbq;
6552 
6553   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || sfp->data.value.ptrvalue == NULL) return;
6554   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
6555   if (rrp->ext.choice != 1) return;
6556   
6557   gbq = GBQualNew ();
6558   gbq->next = sfp->qual;
6559   sfp->qual = gbq;
6560   gbq->qual = StringSave ("product");
6561   gbq->val = StringSave (rrp->ext.value.ptrvalue);
6562 }
6563 
6564 
6565 static void SetRnaImportExportItems (RnaFormPtr rfp)
6566 
6567 {
6568   IteM        exportItm;
6569   IteM        importItm;
6570   RnaPagePtr  rpp;
6571   UIEnum      val;
6572 
6573   if (rfp != NULL) {
6574     importItm = FindFormMenuItem ((BaseFormPtr) rfp, VIB_MSG_IMPORT);
6575     exportItm = FindFormMenuItem ((BaseFormPtr) rfp, VIB_MSG_EXPORT);
6576     switch (rfp->currentPage) {
6577       case RNA_PAGE :
6578         rpp = (RnaPagePtr) GetObjectExtra (rfp->data);
6579         if (rpp != NULL && GetEnumPopup (rpp->type, rna_type_alist, &val) && val == 2) {
6580           SafeSetTitle (importItm, "Import cDNA FASTA...");
6581           SafeSetTitle (exportItm, "Export...");
6582           SafeEnable (importItm);
6583           SafeDisable (exportItm);
6584         } else {
6585           SafeSetTitle (importItm, "Import...");
6586           SafeSetTitle (exportItm, "Export...");
6587           SafeDisable (importItm);
6588           SafeDisable (exportItm);
6589         }
6590         break;
6591       case COMMON_PAGE :
6592         SafeSetTitle (importItm, "Import...");
6593         SafeSetTitle (exportItm, "Export...");
6594         SafeDisable (importItm);
6595         SafeDisable (exportItm);
6596         break;
6597       case LOCATION_PAGE :
6598         SafeSetTitle (importItm, "Import SeqLoc...");
6599         SafeSetTitle (exportItm, "Export SeqLoc...");
6600         SafeEnable (importItm);
6601         SafeEnable (exportItm);
6602         break;
6603       default :
6604         break;
6605     }
6606   }
6607 }
6608 
6609 static void SetRnaType (RnaPagePtr rpp, Uint2 subtype)
6610 
6611 {
6612   RnaFormPtr  rfp;
6613 
6614   if (rpp != NULL && rpp->rfp != NULL) {
6615     rfp = rpp->rfp;
6616     switch (subtype) {
6617       case 0 :
6618         SafeHide (rpp->nameGrp);
6619         SafeHide (rpp->rrnaPrompt);
6620         SafeHide (rpp->ornaPrompt);
6621         SafeHide (rpp->trnaGrp);
6622         SafeHide (rfp->product);
6623         SafeHide (rfp->usrobjext);
6624         SafeHide (rpp->ncrnaGrp);
6625         SafeHide (rpp->tmrnaGrp);
6626         break;
6627       case FEATDEF_mRNA:
6628         SafeHide (rpp->trnaGrp);
6629         SafeHide (rpp->rrnaPrompt);
6630         SafeHide (rpp->ornaPrompt);
6631         SafeShow (rpp->nameGrp);
6632         SafeShow (rfp->product);
6633         SafeShow (rfp->usrobjext);
6634         SafeHide (rpp->ncrnaGrp);
6635         SafeHide (rpp->tmrnaGrp);
6636         break;
6637      case FEATDEF_preRNA :
6638         SafeHide (rpp->trnaGrp);
6639         SafeHide (rpp->rrnaPrompt);
6640         SafeHide (rpp->ornaPrompt);
6641         SafeShow (rpp->nameGrp);
6642         SafeShow (rfp->product);
6643         SafeShow (rfp->usrobjext);
6644         SafeHide (rpp->ncrnaGrp);
6645         SafeHide (rpp->tmrnaGrp);
6646         break;
6647       case FEATDEF_tRNA :
6648         SafeHide (rpp->nameGrp);
6649         SafeHide (rpp->rrnaPrompt);
6650         SafeHide (rpp->ornaPrompt);
6651         SafeShow (rpp->trnaGrp);
6652         SafeShow (rfp->product);
6653         SafeHide (rfp->usrobjext);
6654         SafeHide (rpp->ncrnaGrp);
6655         SafeHide (rpp->tmrnaGrp);
6656         break;
6657       case FEATDEF_rRNA :
6658         SafeHide (rpp->trnaGrp);
6659         SafeHide (rpp->ornaPrompt);
6660         SafeShow (rpp->rrnaPrompt);
6661         SafeShow (rpp->nameGrp);
6662         SafeShow (rfp->product);
6663         SafeHide (rfp->usrobjext);
6664         SafeHide (rpp->ncrnaGrp);
6665         SafeHide (rpp->tmrnaGrp);
6666         break;
6667       case FEATDEF_snRNA :
6668       case FEATDEF_scRNA :
6669       case FEATDEF_snoRNA :
6670         SafeHide (rpp->trnaGrp);
6671         SafeHide (rpp->rrnaPrompt);
6672         SafeHide (rpp->ornaPrompt);
6673         SafeHide (rpp->nameGrp);
6674         SafeShow (rfp->product);
6675         SafeHide (rfp->usrobjext);
6676         SafeShow (rpp->ncrnaGrp);
6677         SafeHide (rpp->tmrnaGrp);
6678         if (subtype == FEATDEF_snRNA) {
6679           PointerToDialog (rpp->ncrnaClass, "snRNA");
6680           
6681         } else if (subtype == FEATDEF_scRNA) {
6682           PointerToDialog (rpp->ncrnaClass, "scRNA");
6683         } else if (subtype == FEATDEF_snoRNA) {
6684           PointerToDialog (rpp->ncrnaClass, "snoRNA");
6685         } else if (subtype == FEATDEF_snoRNA) {
6686           PointerToDialog (rpp->ncrnaClass, "miscRNA");
6687         }
6688         break;
6689 
6690       case FEATDEF_ncRNA :
6691         SafeHide (rpp->trnaGrp);
6692         SafeHide (rpp->rrnaPrompt);
6693         SafeHide (rpp->ornaPrompt);
6694         SafeHide (rpp->nameGrp);
6695         SafeShow (rfp->product);
6696         SafeHide (rfp->usrobjext);
6697         SafeShow (rpp->ncrnaGrp);
6698         SafeHide (rpp->tmrnaGrp);
6699         break;
6700       case FEATDEF_tmRNA :
6701         SafeHide (rpp->trnaGrp);
6702         SafeHide (rpp->rrnaPrompt);
6703         SafeHide (rpp->ornaPrompt);
6704         SafeHide (rpp->nameGrp);
6705         SafeShow (rfp->product);
6706         SafeHide (rfp->usrobjext);
6707         SafeHide (rpp->ncrnaGrp);
6708         SafeShow (rpp->tmrnaGrp);
6709         break;
6710       case FEATDEF_otherRNA :
6711         SafeHide (rpp->trnaGrp);
6712         SafeHide (rpp->rrnaPrompt);
6713         SafeShow (rpp->ornaPrompt);
6714         SafeShow (rpp->nameGrp);
6715         SafeShow (rfp->product);
6716         SafeHide (rfp->usrobjext);
6717         break;
6718       default :
6719         SafeHide (rpp->trnaGrp);
6720         SafeHide (rpp->rrnaPrompt);
6721         SafeHide (rpp->ornaPrompt);
6722         SafeShow (rpp->nameGrp);
6723         SafeHide (rfp->product);
6724         SafeHide (rfp->usrobjext);
6725         SafeHide (rpp->ncrnaGrp);
6726         SafeHide (rpp->tmrnaGrp);
6727         break;
6728     }
6729     SetRnaImportExportItems (rpp->rfp);
6730     Update ();
6731   }
6732 }
6733 
6734 static void PopulateAAPopup (PopuP AAitem)
6735 
6736 {
6737   Char             ch;
6738   Uint1            first;
6739   Uint1            i;
6740   Char             item [77];
6741   Uint1            last;
6742   SeqCodeTablePtr  sctp;
6743   CharPtr          str;
6744 
6745   sctp = SeqCodeTableFind (Seq_code_ncbieaa);
6746   first = FirstResidueInCode (sctp);
6747   last = LastResidueInCode (sctp);
6748   PopupItem (AAitem, " ");
6749   for (i = 65; i <= last; i++) {
6750     /*
6751     if (i == 74 || i == 79) {
6752       continue;
6753     }
6754     */
6755     ch = GetSymbolForResidue (sctp, i);
6756     str = (CharPtr) GetNameForResidue (sctp, i);
6757     sprintf (item, "%c    %s", ch, str);
6758     PopupItem (AAitem, item);
6759   }
6760   SetValue (AAitem, 1); 
6761 }
6762 
6763 static void ChangetRNASubPage (VoidPtr data, Int2 newval, Int2 oldval)
6764 
6765 {
6766   RnaPagePtr  rpp;
6767 
6768   rpp = (RnaPagePtr) data;
6769   if (rpp != NULL) {
6770     if (oldval >= 0 && oldval <= 2) {
6771       SafeHide (rpp->trnaPages [oldval]);
6772     }
6773     if (newval >= 0 && newval <= 2) {
6774       SafeShow (rpp->trnaPages [newval]);
6775     }
6776     SetRnaImportExportItems (rpp->rfp);
6777     Update ();
6778   }
6779 }
6780 
6781 static CharPtr trnaTabs [] = {
6782   "Amino Acid", "Codons", "Anticodon", NULL
6783 };
6784 
6785 
6786 static Uint1 RnaTypeFromFeatdef (Uint2 featdef)
6787 {
6788   switch (featdef) 
6789   {
6790     case FEATDEF_preRNA:
6791       return 1;
6792       break;
6793     case FEATDEF_mRNA:
6794       return 2;
6795       break;
6796     case FEATDEF_tRNA:
6797       return 3;
6798       break;
6799     case FEATDEF_rRNA:
6800       return 4;
6801       break;
6802     case FEATDEF_snRNA:
6803       return 8;
6804       break;
6805     case FEATDEF_scRNA:
6806       return 8;
6807       break;
6808     case FEATDEF_snoRNA:
6809       return 8;
6810       break;
6811     case FEATDEF_ncRNA:
6812       return 8;
6813       break;
6814     case FEATDEF_tmRNA:
6815       return 9; 
6816       break;
6817     case FEATDEF_misc_RNA:
6818       return 10;
6819       break;
6820     case FEATDEF_otherRNA:
6821     default:
6822       return 255;
6823       break;
6824   }
6825 }
6826 
6827 
6828 static void ChangeRNAType (PopuP p)
6829 
6830 {
6831   RnaFormPtr       rfp;
6832   RnaRefPtr        rrp;
6833   RnaPagePtr       rpp;
6834   UIEnum           val;
6835   CharPtr          product = NULL;
6836 
6837   rfp = (RnaFormPtr) GetObjectExtra (p);
6838   if (rfp == NULL) return;
6839   rpp = (RnaPagePtr) GetObjectExtra (rfp->data);
6840   if (rpp == NULL) return;
6841 
6842   if (GetEnumPopup (rpp->type, rna_type_alist, &val)) {
6843     switch (rpp->prev_rna_type) {
6844       case 5:
6845       case 6:
6846       case 7:
6847       case 8:
6848         if (!TextHasNoText (rpp->ncrnaProduct)) {
6849           product = SaveStringFromText (rpp->ncrnaProduct);
6850         }
6851         break;
6852       case 9:
6853         if (!TextHasNoText (rpp->tmrnaProduct)) {
6854           product = SaveStringFromText (rpp->tmrnaProduct);
6855         }
6856         break;
6857       case 3:
6858         /* don't collect product for tRNA */
6859         break;
6860       default:
6861         if (!TextHasNoText (rpp->name)) {
6862           product = SaveStringFromText (rpp->name);
6863         }
6864         break;
6865     }
6866     switch (val) {
6867       case 3:
6868         /* don't set product for tRNA */
6869         break;
6870       case 5:
6871       case 6:
6872       case 7:
6873       case 8:
6874         SetTitle (rpp->ncrnaProduct, product);
6875         break;
6876       case 9:
6877         SetTitle (rpp->tmrnaProduct, product);
6878         break;
6879       default:
6880         SetTitle (rpp->name, product);
6881         break;
6882     }
6883     product = MemFree (product);
6884     rrp = RnaPageToRnaRefPtr (rpp->dialog);
6885     RnaRefPtrToRnaPage (rpp->dialog, rrp);
6886     rrp = RnaRefFree (rrp);
6887     rpp->prev_rna_type = val;
6888     Update ();
6889   }
6890 }
6891 
6892 
6893 
6894 
6895 static DialoG CreateRnaDialog (GrouP h, CharPtr title,
6896                                Uint2 subtype, SeqEntryPtr sep,
6897                                SeqFeatPtr sfp, RnaFormPtr rfp)
6898 
6899 {
6900   GrouP       f;
6901   GrouP       g;
6902   Boolean     indexerVersion;
6903   GrouP       k;
6904   GrouP       m;
6905   GrouP       p;
6906   GrouP       q;
6907   RnaPagePtr  rpp;
6908   RnaRefPtr   rrp;
6909   GrouP       s;
6910   Boolean     showpseudo;
6911   PrompT      t;
6912   DialoG      tbs;
6913   GrouP       x;
6914   Uint1       rna_type;
6915   Uint2       entityID;
6916 
6917   p = HiddenGroup (h, 1, 0, NULL);
6918   SetGroupSpacing (p, 10, 10);
6919 
6920   rpp = (RnaPagePtr) MemNew (sizeof (RnaPage));
6921   if (rpp != NULL) {
6922 
6923     SetObjectExtra (p, rpp, StdCleanupExtraProc);
6924     rpp->dialog = (DialoG) p;
6925     rpp->todialog = RnaRefPtrToRnaPage;
6926     rpp->fromdialog = RnaPageToRnaRefPtr;
6927     rpp->testdialog = NULL;
6928 
6929     rpp->prev_rna_type = -1;
6930 
6931     if (title != NULL && title [0] != '\0') {
6932       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
6933     } else {
6934       s = HiddenGroup (p, 0, -2, NULL);
6935     }
6936     m = HiddenGroup (s, -1, 0, NULL);
6937     SetGroupSpacing (m, 10, 10);
6938 
6939     rpp->rfp = rfp;
6940 
6941     f = HiddenGroup (m, -2, 0, NULL);
6942     StaticPrompt (f, "Type", 0, popupMenuHeight, programFont, 'l');
6943     rpp->type = PopupList (f, TRUE, ChangeRNAType);
6944     SetObjectExtra (rpp->type, rfp, NULL);
6945     InitEnumPopup (rpp->type, rna_type_alist, NULL);
6946     SetEnumPopup (rpp->type, rna_type_alist, (UIEnum) 0);
6947 
6948     StaticPrompt (m, "Changing RNA type will recreate the window.",
6949                         0, 0, programFont, 'c');
6950 
6951     showpseudo = FALSE;
6952     if (sfp != NULL && sfp->data.choice == SEQFEAT_RNA) {
6953       rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
6954       if (rrp != NULL && rrp->pseudo) {
6955         showpseudo = TRUE;
6956       }
6957     }
6958     indexerVersion = (Boolean) (GetAppProperty ("InternalNcbiSequin") != NULL);
6959     if (indexerVersion) {
6960       showpseudo = TRUE;
6961     }
6962     if (showpseudo) {
6963       rpp->pseudo = CheckBox (m, "PseudoRNA", NULL);
6964     }
6965 
6966     g = HiddenGroup (m, 0, 0, NULL);
6967 
6968     rpp->nameGrp = HiddenGroup (g, -1, 0, NULL);
6969     q = HiddenGroup (rpp->nameGrp, -2, 0, NULL);
6970     StaticPrompt (q, "Name", 0, dialogTextHeight, programFont, 'l');
6971     rpp->name = DialogText (q, "", 20, NULL);
6972     x = HiddenGroup (rpp->nameGrp, 0, 0, NULL);
6973     rpp->rrnaPrompt = StaticPrompt (x, "E.g., 16S ribosomal RNA", 0, 0, programFont, 'c');
6974     rpp->ornaPrompt = StaticPrompt (x, "E.g., internal transcribed spacer 1", 0, 0, programFont, 'c');
6975     AlignObjects (ALIGN_CENTER, (HANDLE) q, (HANDLE) rpp->rrnaPrompt, (HANDLE) rpp->ornaPrompt, NULL);
6976     Hide (rpp->nameGrp);
6977 
6978     rpp->trnaGrp = HiddenGroup (g, -1, 0, NULL);
6979     SetGroupSpacing (rpp->trnaGrp, 10, 10);
6980     tbs = CreateFolderTabs (rpp->trnaGrp, trnaTabs, 0, 0, 0,
6981                             PROGRAM_FOLDER_TAB,
6982                             ChangetRNASubPage, (Pointer) rpp);
6983     k = HiddenGroup (rpp->trnaGrp, 0, 0, NULL);
6984     rpp->trnaPages [0] = HiddenGroup (k, -2, 0, NULL);
6985     StaticPrompt (rpp->trnaPages [0], "Amino Acid", 0, popupMenuHeight, programFont, 'l');
6986     rpp->AAitem = PopupList (rpp->trnaPages [0], TRUE, NULL);
6987     PopulateAAPopup (rpp->AAitem);
6988     rpp->trnaPages [1] = HiddenGroup (k, -1, 0, NULL);
6989     t = StaticPrompt (rpp->trnaPages [1], "Recognized Codons", 0, 0, programFont, 'c');
6990     rpp->codons = CreateVisibleStringDialog (rpp->trnaPages [1], 3, -1, 4);
6991     AlignObjects (ALIGN_CENTER, (HANDLE) t, (HANDLE) rpp->codons, NULL);
6992     Hide (rpp->trnaPages [1]);
6993     rpp->trnaPages [2] = HiddenGroup (k, -1, 0, NULL);
6994     rpp->anticodon = CreateIntervalEditorDialogEx (rpp->trnaPages [2], NULL,
6995                                                    3, 2, sep, TRUE, FALSE,
6996                                                    FALSE, FALSE, FALSE, NULL, NULL);
6997     Hide (rpp->trnaPages [2]);
6998     Hide (rpp->trnaGrp);
6999 
7000     AlignObjects (ALIGN_CENTER, (HANDLE) tbs,
7001                   (HANDLE) rpp->trnaPages [0], (HANDLE) rpp->trnaPages [1],
7002                   (HANDLE) rpp->trnaPages [2], NULL);
7003     AlignObjects (ALIGN_CENTER, (HANDLE) f, (HANDLE) rpp->nameGrp,
7004                   (HANDLE) rpp->trnaGrp,  (HANDLE) rpp->pseudo,NULL);
7005     Hide (rpp->ncrnaGrp);
7006 
7007     rpp->ncrnaGrp = HiddenGroup (g, 2, 0, NULL);
7008     SetGroupSpacing (rpp->ncrnaGrp, 10, 10);
7009     StaticPrompt (rpp->ncrnaGrp, "Class", 0, popupMenuHeight, programFont, 'l');
7010     rpp->ncrnaClass = CreatencRNAClassDialog (rpp->ncrnaGrp, FALSE, NULL, NULL);
7011     StaticPrompt (rpp->ncrnaGrp, "Product", 0, dialogTextHeight, programFont, 'l');
7012     rpp->ncrnaProduct = DialogText (rpp->ncrnaGrp, "", 10, NULL);
7013     Hide (rpp->ncrnaGrp);
7014 
7015     rpp->tmrnaGrp = HiddenGroup (g, 2, 0, NULL);
7016     SetGroupSpacing (rpp->tmrnaGrp, 10, 10);
7017     StaticPrompt (rpp->tmrnaGrp, "Tag Peptide", 0, dialogTextHeight, programFont, 'l');
7018     rpp->tmrnaTagPeptide = CreateRptUnitRangeDialog (rpp->tmrnaGrp, NULL, NULL, NULL, NULL);
7019     StaticPrompt (rpp->tmrnaGrp, "Product", 0, dialogTextHeight, programFont, 'l');
7020     rpp->tmrnaProduct = DialogText (rpp->tmrnaGrp, "", 10, NULL);
7021     Hide (rpp->tmrnaGrp);
7022 
7023     rna_type = RnaTypeFromFeatdef (subtype);
7024 
7025     SetEnumPopup (rpp->type, rna_type_alist, (UIEnum) rna_type);
7026     rpp->prev_rna_type = rna_type;
7027 
7028     if ((sfp != NULL && sfp->product != NULL) || indexerVersion) {
7029       entityID = SeqMgrGetEntityIDForSeqEntry(sep);
7030       rfp->product = CreateRNATranscriptIDDialog (m, entityID, TRUE, NULL, NULL);
7031     }
7032 
7033     SetRnaType (rpp, subtype);
7034   }
7035 
7036   return (DialoG) p;
7037 }
7038 
7039 static void ChangeRnaPage (VoidPtr data, Int2 newval, Int2 oldval)
7040 
7041 {
7042   RnaFormPtr    rfp;
7043 
7044   rfp = (RnaFormPtr) data;
7045   if (rfp != NULL) {
7046     rfp->currentPage = newval;
7047     SafeHide (rfp->pages [oldval]);
7048     SafeShow (rfp->pages [newval]);
7049     switch (newval) {
7050       case RNA_PAGE :
7051         SendMessageToDialog (rfp->data, VIB_MSG_ENTER);
7052         break;
7053       case COMMON_PAGE :
7054         break;
7055       case LOCATION_PAGE :
7056         SendMessageToDialog (rfp->location, VIB_MSG_ENTER);
7057         break;
7058       default :
7059         break;
7060     }
7061     SetRnaImportExportItems (rfp);
7062     Update ();
7063   }
7064 }
7065 
7066 static Boolean ImportRnaForm (ForM f, CharPtr filename)
7067 
7068 {
7069   BioseqPtr    bsp;
7070   SeqLocPtr    currslp;
7071   CharPtr      extension;
7072   FILE         *fp;
7073   BioseqPtr    mbsp;
7074   BioseqPtr    nbsp;
7075   SeqEntryPtr  nsep;
7076   SeqLocPtr    oldslp;
7077   Char         path [PATH_MAX];
7078   RnaFormPtr   rfp;
7079   SeqIdPtr     sip;
7080   SeqEntryPtr  sep;
7081   SeqLocPtr    slp;
7082 
7083   path [0] = '\0';
7084   StringNCpy_0 (path, filename, sizeof (path));
7085   rfp = (RnaFormPtr) GetObjectExtra (f);
7086   if (rfp != NULL) {
7087     switch (rfp->currentPage) {
7088       case RNA_PAGE :
7089         extension = GetAppProperty ("FastaNucExtension");
7090         if (path [0] != '\0' || GetInputFileName (path, sizeof (path), extension, "TEXT")) {
7091           fp = FileOpen (path, "r");
7092           if (fp != NULL) {
7093             sep = FastaToSeqEntry (fp, TRUE);
7094             if (sep != NULL && sep->choice == 1 && sep->data.ptrvalue != NULL) {
7095               mbsp = (BioseqPtr) sep->data.ptrvalue;
7096               nsep = GetBestTopParentForItemID (rfp->input_entityID,
7097                                                 rfp->input_itemID,
7098                                                 rfp->input_itemtype);
7099               if (nsep != NULL) {
7100                 nsep = FindNucSeqEntry (nsep);
7101               }
7102               if (nsep != NULL && nsep->data.ptrvalue != NULL) {
7103                 nbsp = (BioseqPtr) nsep->data.ptrvalue;
7104                 slp = AlignmRNA2genomic (nbsp, mbsp);
7105                 if (slp != NULL) {
7106                   currslp = DialogToPointer (rfp->location);
7107                   if (currslp != NULL) {
7108                     if (Message (MSG_OKC, "Replace existing location?") == ANS_CANCEL) {
7109                       slp = SeqLocFree (slp);
7110                     }
7111                     Select (rfp->form);
7112                     Update ();
7113                   }
7114                   SeqLocFree (currslp);
7115                   if (slp != NULL) {
7116                     sip = SeqLocId (slp);
7117                     if (sip != NULL) {
7118                       bsp = BioseqFind (sip);
7119                       if (bsp != NULL) {
7120                         if (bsp->repr == Seq_repr_seg) {
7121                           oldslp = slp;
7122                           slp = SegLocToParts (bsp, oldslp);
7123                           FreeAllFuzz (slp);
7124                           SeqLocFree (oldslp);
7125                         }
7126                       }
7127                     }
7128                     StripLocusFromSeqLoc (slp);
7129                     PointerToDialog (rfp->location, slp);
7130                     SeqLocFree (slp);
7131                   }
7132                 }
7133               }
7134             }
7135             SeqEntryFree (sep);
7136           }
7137           FileClose (fp);
7138         }
7139         break;
7140       case LOCATION_PAGE :
7141         return ImportDialog (rfp->location, filename);
7142       default :
7143         break;
7144     }
7145   }
7146   return FALSE;
7147 }
7148 
7149 static Boolean ExportRnaForm (ForM f, CharPtr filename)
7150 
7151 {
7152   RnaFormPtr  rfp;
7153 
7154   rfp = (RnaFormPtr) GetObjectExtra (f);
7155   if (rfp != NULL) {
7156     switch (rfp->currentPage) {
7157       case LOCATION_PAGE :
7158         return ExportDialog (rfp->location, filename);
7159       default :
7160         break;
7161     }
7162   }
7163   return FALSE;
7164 }
7165 
7166 static CharPtr  rnaFormTabs [] = {
7167   NULL, "Properties", "Location", NULL
7168 };
7169 
7170 static void RnaFormMessage (ForM f, Int2 mssg)
7171 
7172 {
7173   RnaFormPtr  rfp;
7174 
7175   rfp = (RnaFormPtr) GetObjectExtra (f);
7176   if (rfp != NULL) {
7177     switch (mssg) {
7178       case VIB_MSG_INIT :
7179         StdInitFeatFormProc (f);
7180         break;
7181       case VIB_MSG_IMPORT :
7182         ImportRnaForm (f, NULL);
7183         break;
7184       case VIB_MSG_EXPORT :
7185         ExportRnaForm (f, NULL);
7186         break;
7187       case VIB_MSG_CLOSE :
7188         Remove (f);
7189         break;
7190       case VIB_MSG_CUT :
7191         StdCutTextProc (NULL);
7192         break;
7193       case VIB_MSG_COPY :
7194         StdCopyTextProc (NULL);
7195         break;
7196       case VIB_MSG_PASTE :
7197         StdPasteTextProc (NULL);
7198         break;
7199       case VIB_MSG_DELETE :
7200         if (rfp->currentPage == LOCATION_PAGE) {
7201           PointerToDialog (rfp->location, NULL);
7202         } else {
7203           StdDeleteTextProc (NULL);
7204         }
7205         break;
7206       default :
7207         if (rfp->appmessage != NULL) {
7208           rfp->appmessage (f, mssg);
7209         }
7210         break;
7211     }
7212   }
7213 }
7214 
7215 static void RnaFormActivate (WindoW w)
7216 
7217 {
7218   RnaFormPtr  rfp;
7219 
7220   rfp = (RnaFormPtr) GetObjectExtra (w);
7221   if (rfp != NULL) {
7222     if (rfp->activate != NULL) {
7223       rfp->activate (w);
7224     }
7225     SetRnaImportExportItems (rfp);
7226   }
7227 }
7228 
7229 static void RnaRefPtrToForm (ForM f, Pointer data)
7230 
7231 {
7232   SeqEntryPtr   oldsep;
7233   RnaFormPtr    rfp;
7234   SeqEntryPtr   sep;
7235   SeqFeatPtr    sfp;
7236   Int4          val;
7237 
7238   rfp = (RnaFormPtr) GetObjectExtra (f);
7239   if (rfp != NULL) {
7240     sep = GetTopSeqEntryForEntityID (rfp->input_entityID);
7241     oldsep = SeqEntrySetScope (sep);
7242     sfp = (SeqFeatPtr) data;
7243     if (sfp != NULL) {
7244       PointerToDialog (rfp->location, sfp->location);
7245       switch (sfp->data.choice) {
7246         case SEQFEAT_BOND :
7247         case SEQFEAT_SITE :
7248         case SEQFEAT_PSEC_STR :
7249           val = (Int4) sfp->data.value.intvalue;
7250           PointerToDialog (rfp->data, (Pointer) &(val));
7251           break;
7252         case SEQFEAT_COMMENT:
7253           break;
7254         default :
7255           PointerToDialog (rfp->data, sfp->data.value.ptrvalue);
7256           break;
7257       }
7258       SeqFeatPtrToCommon ((FeatureFormPtr) rfp, sfp);
7259       PointerToDialog (rfp->product, sfp->product);
7260     }
7261     SeqEntrySetScope (oldsep);
7262   }
7263 }
7264 
7265 
7266 static void RnaFormClearButtonProc (ButtoN b)
7267 {
7268   RnaFormPtr         rfp;
7269 
7270   rfp = (RnaFormPtr) GetObjectExtra (b);
7271   if (rfp != NULL)
7272   {
7273     PointerToDialog (rfp->data, NULL);
7274     SendMessageToDialog (rfp->data, VIB_MSG_INIT);
7275     SendMessageToDialog (rfp->location, NUM_VIB_MSG + 1);
7276 
7277     SeqFeatPtrToCommon ((FeatureFormPtr) rfp, NULL);
7278     
7279   }
7280 }
7281 
7282 extern ForM CreateRnaForm (Int2 left, Int2 top, CharPtr title,
7283                            SeqFeatPtr sfp, SeqEntryPtr sep,
7284                            Uint2 subtype, FormActnFunc actproc)
7285 
7286 {
7287   ButtoN             b;
7288   GrouP              c;
7289   GrouP              g;
7290   GrouP              h;
7291   GrouP              k;
7292   RnaFormPtr         rfp;
7293   GrouP              s;
7294   StdEditorProcsPtr  sepp;
7295   WindoW             w;
7296   Boolean            indexerVersion;
7297 
7298   w = NULL;
7299   rfp = (RnaFormPtr) MemNew (sizeof (RnaForm));
7300   if (rfp != NULL) {
7301     w = FixedWindow (left, top, -10, -10, title, StdCloseWindowProc);
7302     SetObjectExtra (w, rfp, StdFeatFormCleanupProc);
7303     rfp->form = (ForM) w;
7304     rfp->actproc = actproc;
7305     rfp->toform = RnaRefPtrToForm;
7306     rfp->fromform = NULL;
7307     rfp->formmessage = RnaFormMessage;
7308     rfp->testform = NULL;
7309     rfp->importform = ImportRnaForm;
7310     rfp->exportform = ExportRnaForm;
7311     
7312     if (sfp == NULL)
7313     {
7314       rfp->empty_feat = TRUE;
7315     }
7316     else
7317     {
7318       rfp->empty_feat = FALSE;
7319     }
7320 
7321 #ifndef WIN_MAC
7322     CreateStdEditorFormMenus (w);
7323 #endif
7324 
7325     rfp->activate = NULL;
7326     sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
7327     if (sepp != NULL) {
7328       rfp->activate = sepp->activateForm;
7329       rfp->appmessage = sepp->handleMessages;
7330     }
7331     SetActivate (w, RnaFormActivate);
7332 
7333     g = HiddenGroup (w, -1, 0, NULL);
7334     SetGroupSpacing (g, 3, 10);
7335 
7336     rfp->sep = sep;
7337     rnaFormTabs [0] = NULL;
7338     if (title != NULL && *title != '\0') {
7339       rnaFormTabs [0] = title;
7340     } else {
7341       rnaFormTabs [0] = "RNA";
7342     }
7343     rfp->foldertabs = CreateFolderTabs (g, rnaFormTabs, RNA_PAGE,
7344                                         0, 0, SYSTEM_FOLDER_TAB,
7345                                         ChangeRnaPage, (Pointer) rfp);
7346     rfp->currentPage = RNA_PAGE;
7347 
7348     h = HiddenGroup (g, 0, 0, NULL);
7349 
7350     s = HiddenGroup (h, -1, 0, NULL);
7351     SetGroupSpacing (s, 3, 10);
7352     rfp->data = CreateRnaDialog (s, NULL, subtype, sep, sfp, rfp);
7353     rfp->pages [RNA_PAGE] = s;
7354     Hide (rfp->pages [RNA_PAGE]);
7355     rnaFormTabs [0] = NULL;
7356 
7357     s = HiddenGroup (h, -1, 0, NULL);
7358     CreateCommonFeatureGroup (s, (FeatureFormPtr) rfp, sfp, TRUE, TRUE);
7359     rfp->pages [COMMON_PAGE] = s;
7360     Hide (rfp->pages [COMMON_PAGE]);
7361 
7362     s = HiddenGroup (h, -1, 0, NULL);
7363     rfp->location = CreateIntervalEditorDialogEx (s, NULL, 4, 2, sep, TRUE, FALSE,
7364                                                   TRUE, TRUE, FALSE,
7365                                                   (FeatureFormPtr) rfp,
7366                                                   StdFeatIntEdPartialCallback);
7367     rfp->pages [LOCATION_PAGE] = s;
7368     Hide (rfp->pages [LOCATION_PAGE]);
7369 
7370     AlignObjects (ALIGN_CENTER, (HANDLE) rfp->pages [RNA_PAGE],
7371                   (HANDLE) rfp->pages [COMMON_PAGE], (HANDLE) rfp->pages [LOCATION_PAGE],
7372                   NULL);
7373     AlignObjects (ALIGN_CENTER, (HANDLE) rfp->foldertabs, (HANDLE) h, NULL);
7374 
7375     indexerVersion = (Boolean) (GetAppProperty ("InternalNcbiSequin") != NULL);
7376     if (rfp->empty_feat && indexerVersion)
7377     {
7378       k = HiddenGroup (w, 2, 0, NULL);
7379       SetGroupSpacing (k, 10, 10);
7380       b = PushButton (k, "Clear", RnaFormClearButtonProc);
7381       SetObjectExtra (b, rfp, NULL);
7382       rfp->leave_dlg_up = CheckBox (k, "Leave Dialog Up", NULL);
7383     }
7384     else
7385     {
7386       k = NULL;
7387       rfp->leave_dlg_up = NULL;
7388     }
7389 
7390     c = HiddenGroup (w, 2, 0, NULL);
7391     b = PushButton (c, "Accept", StdFeatFormAcceptButtonProc);
7392     SetObjectExtra (b, rfp, NULL);
7393     PushButton (c, "Cancel", StdCancelButtonProc);
7394     
7395     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) k, NULL);
7396     RealizeWindow (w);
7397 
7398     SendMessageToDialog (rfp->data, VIB_MSG_INIT);
7399     SendMessageToDialog (rfp->location, VIB_MSG_INIT);
7400     SendMessageToDialog (rfp->product, VIB_MSG_INIT);
7401     SendMessageToDialog (rfp->usrobjext, VIB_MSG_INIT);
7402     Show (rfp->pages [rfp->currentPage]);
7403     SendMessageToDialog (rfp->data, VIB_MSG_ENTER);
7404     Update ();
7405   }
7406   return (ForM) w;
7407 }
7408 
7409 extern Int2 LIBCALLBACK RnaGenFunc (Pointer data)
7410 
7411 {
7412   FeatDefPtr        curr;
7413   HelpMessageFunc   helpfunc;
7414   Uint1             key;
7415   CharPtr           label = NULL;
7416   ObjMgrPtr         omp;
7417   OMProcControlPtr  ompcp;
7418   ObjMgrTypePtr     omtp;
7419   OMUserDataPtr     omudp;
7420   ObjMgrProcPtr     proc;
7421   RnaFormPtr        rfp;
7422   RnaPagePtr        rpp;
7423   RnaRefPtr         rrp;
7424   SeqEntryPtr       sep;
7425   SeqFeatPtr        sfp;
7426   Uint2             subtype;
7427   Char              title [64];
7428   WindoW            w;
7429 
7430   ompcp = (OMProcControlPtr) data;
7431   sfp = NULL;
7432   sep = NULL;
7433   subtype = FEATDEF_otherRNA;
7434   if (ompcp == NULL || ompcp->proc == NULL) return OM_MSG_RET_ERROR;
7435   proc = ompcp->proc;
7436   switch (ompcp->input_itemtype) {
7437     case OBJ_SEQFEAT :
7438       sfp = (SeqFeatPtr) ompcp->input_data;
7439       if (sfp != NULL && sfp->data.choice != SEQFEAT_RNA) {
7440         return OM_MSG_RET_ERROR;
7441       }
7442       break;
7443     case OBJ_BIOSEQ :
7444       break;
7445     case OBJ_BIOSEQSET :
7446       break;
7447     case 0 :
7448       break;
7449     default :
7450       return OM_MSG_RET_ERROR;
7451   }
7452   omudp = ItemAlreadyHasEditor (ompcp->input_entityID, ompcp->input_itemID,
7453                                 ompcp->input_itemtype, ompcp->proc->procid);
7454   if (omudp != NULL) {
7455     rfp = (RnaFormPtr) omudp->userdata.ptrvalue;
7456     if (rfp != NULL) {
7457       Select (rfp->form);
7458     }
7459     return OM_MSG_RET_DONE;
7460   }
7461   StringCpy (title, "Unknown RNA");
7462   if (sfp != NULL && sfp->data.value.ptrvalue != NULL) {
7463     rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
7464     StringNCpy_0 (title,
7465                 GetEnumName (rrp->type, rna_type_alist),
7466                 sizeof (title));
7467     if (StringHasNoText (title)) {
7468       StringCpy (title, "Unknown RNA");
7469     } else if (proc->subinputtype > 0) {
7470       subtype = proc->subinputtype;
7471     }
7472   } else if (proc->subinputtype > 0) {
7473     subtype = proc->subinputtype;
7474     curr = FeatDefFindNext (NULL, &key, &label, FEATDEF_ANY, TRUE);
7475     while (curr != NULL) {
7476       if (key != FEATDEF_BAD && curr->seqfeat_key == SEQFEAT_RNA) {
7477         if (subtype == curr->featdef_key) {
7478           StringNCpy_0 (title, curr->typelabel, sizeof (title));
7479           break;
7480         }
7481       }
7482       curr = FeatDefFindNext (curr, &key, &label, FEATDEF_ANY, TRUE);
7483     }
7484   }
7485   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
7486   ModernizeRNAFields (sfp);
7487   w = (WindoW) CreateRnaForm (-50, -33, title, sfp, sep,
7488                               subtype, StdFeatFormActnProc);
7489   rfp = (RnaFormPtr) GetObjectExtra (w);
7490   if (rfp != NULL) {
7491     rfp->input_entityID = ompcp->input_entityID;
7492     rfp->input_itemID = ompcp->input_itemID;
7493     rfp->input_itemtype = ompcp->input_itemtype;
7494     rfp->this_itemtype = OBJ_SEQFEAT;
7495     rfp->this_subtype = subtype;
7496     rfp->procid = ompcp->proc->procid;
7497     rfp->proctype = ompcp->proc->proctype;
7498     rfp->userkey = OMGetNextUserKey ();
7499     omudp = ObjMgrAddUserData (ompcp->input_entityID, ompcp->proc->procid,
7500                                OMPROC_EDIT, rfp->userkey);
7501     if (omudp != NULL) {
7502       omudp->userdata.ptrvalue = (Pointer) rfp;
7503       omudp->messagefunc = StdVibrantEditorMsgFunc;
7504     }
7505     if (sfp != NULL) {
7506       omp = ObjMgrGet ();
7507       if (omp != NULL) {
7508         omtp = ObjMgrTypeFind (omp, OBJ_SEQFEAT, NULL, NULL);
7509         if (omtp != NULL && omtp->subtypefunc != NULL) {
7510           rfp->this_subtype = (*(omtp->subtypefunc)) (sfp);
7511         }
7512       }
7513     }
7514     SendMessageToForm (rfp->form, VIB_MSG_INIT);
7515     if (sfp != NULL) {
7516       PointerToForm (rfp->form, (Pointer) sfp);
7517       SetClosestParentIfDuplicating ((BaseFormPtr) rfp);
7518     } else {
7519       rpp = (RnaPagePtr) GetObjectExtra (rfp->data);
7520       if (rpp != NULL) {
7521         SetNewFeatureDefaultInterval ((FeatureFormPtr) rfp);
7522         SetEnumPopup (rpp->type, rna_type_alist, RnaTypeFromFeatdef (subtype));
7523         if (subtype == FEATDEF_tRNA)
7524         {
7525           /* attempt to provide default location for anticodons */
7526           SeqLocPtr tmp_loc = NULL;
7527           
7528           tmp_loc = DialogToPointer (rpp->rfp->location);
7529           PointerToDialog (rpp->anticodon, tmp_loc);
7530           SetSequenceAndStrandForIntervalPage (rpp->anticodon);
7531           SeqLocFree (tmp_loc);              
7532         }
7533       }
7534     }
7535   }
7536   Show (w);
7537   Select (w);
7538   helpfunc = (HelpMessageFunc) GetAppProperty ("HelpMessageProc");
7539   if (helpfunc != NULL) {
7540     helpfunc ("Features", title);
7541   }
7542   return OM_MSG_RET_DONE;
7543 }
7544 
7545 
7546 typedef struct ncrnaclassdlg {
7547   DIALOG_MESSAGE_BLOCK
7548   PopuP                ncrnaclass;
7549   TexT                 otherclass;
7550   Nlm_ChangeNotifyProc change_notify;
7551   Pointer              change_userdata;
7552   Boolean              is_constraint;
7553 
7554 } NcrnaClassDlgData, PNTR NcrnaClassDlgPtr;
7555 
7556 static void ChangeNcrnaClass (PopuP p)
7557 {
7558   NcrnaClassDlgPtr dlg;
7559 
7560   dlg = (NcrnaClassDlgPtr) GetObjectExtra (p);
7561   if (dlg == NULL) return;
7562 
7563   if (GetValue (dlg->ncrnaclass) == NcrnaOTHER) {
7564     Show (dlg->otherclass);
7565   } else {
7566     Hide (dlg->otherclass);
7567   }
7568 
7569   if (dlg->change_notify != NULL) {
7570     (dlg->change_notify) (dlg->change_userdata);
7571   }
7572 }
7573 
7574 
7575 static void ChangeNcrnaOtherClass (TexT t)
7576 {
7577   NcrnaClassDlgPtr dlg;
7578 
7579   dlg = (NcrnaClassDlgPtr) GetObjectExtra (t);
7580   if (dlg == NULL) return;
7581   if (dlg->change_notify != NULL) {
7582     (dlg->change_notify) (dlg->change_userdata);
7583   }
7584 }
7585 
7586 
7587 static void PointerToNcrnaClassDialog (DialoG d, Pointer data)
7588 {
7589   NcrnaClassDlgPtr dlg;
7590   CharPtr PNTR     cpp;
7591   Int4             pos = NcrnaOTHER;
7592 
7593   dlg = (NcrnaClassDlgPtr) GetObjectExtra (d);
7594   if (dlg == NULL) return;
7595 
7596   if (data == NULL) {
7597     if (dlg->is_constraint) {
7598       pos = NcrnaOTHER + 1;
7599     }
7600   } else {
7601     if (data != NULL) {
7602       for (cpp = ncrnaClassList, pos = 1;
7603           *cpp != NULL && pos < NcrnaOTHER;
7604           cpp++, pos++) {
7605         if (StringCmp (*cpp, (CharPtr) data) == 0) {
7606           break;
7607         }
7608       }
7609     }
7610   }
7611   
7612   SetValue (dlg->ncrnaclass, pos);
7613   if (pos == NcrnaOTHER) {
7614     if (StringCmp ((CharPtr) data, "other") == 0) {
7615       SetTitle (dlg->otherclass, "");
7616     } else {
7617       SetTitle (dlg->otherclass, (CharPtr) data);
7618     }
7619     Show (dlg->otherclass);
7620   } else {
7621     Hide (dlg->otherclass);
7622   }
7623 }
7624 
7625 
7626 static Pointer NcrnaClassDialogToPointer (DialoG d)
7627 {
7628   NcrnaClassDlgPtr dlg;
7629   Int4             pos;
7630   CharPtr          rval = NULL;
7631 
7632   dlg = (NcrnaClassDlgPtr) GetObjectExtra (d);
7633   if (dlg == NULL) return NULL;
7634   pos = GetValue (dlg->ncrnaclass);
7635   if (pos > 0 && pos < NcrnaOTHER) {
7636     rval = StringSave (ncrnaClassList[pos - 1]);
7637   } else if (pos == NcrnaOTHER) {
7638     if (TextHasNoText (dlg->otherclass)) {
7639       rval = StringSave ("other");
7640     } else {
7641       rval = SaveStringFromText (dlg->otherclass);
7642     }
7643   }  
7644   return rval;
7645 }
7646 
7647 
7648 static ValNodePtr TestNcrnaClassDialog (DialoG d)
7649 {
7650   ValNodePtr err_list = NULL;
7651 
7652   NcrnaClassDlgPtr dlg;
7653   Int4             pos;
7654 
7655   dlg = (NcrnaClassDlgPtr) GetObjectExtra (d);
7656   if (dlg == NULL) return NULL;
7657   pos = GetValue (dlg->ncrnaclass);
7658 
7659   if (pos < 1 && !dlg->is_constraint) {
7660     ValNodeAddPointer (&err_list, 0, "No ncRNA class");
7661   } else if (!dlg->is_constraint && pos > NcrnaOTHER) {
7662     ValNodeAddPointer (&err_list, 0, "No ncRNA class");
7663   }
7664   return err_list;
7665 }
7666 
7667 
7668 extern DialoG CreatencRNAClassDialog (GrouP h, Boolean is_constraint, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
7669 {
7670   NcrnaClassDlgPtr dlg;
7671   GrouP            p;
7672   CharPtr PNTR cpp;
7673 
7674   p = HiddenGroup (h, 2, 0, NULL);  
7675   dlg = (NcrnaClassDlgPtr) MemNew (sizeof (NcrnaClassDlgData));
7676   SetObjectExtra (p, dlg, StdCleanupExtraProc);
7677   
7678   dlg->dialog = (DialoG) p;
7679   dlg->todialog = PointerToNcrnaClassDialog;
7680   dlg->fromdialog = NcrnaClassDialogToPointer;
7681   dlg->testdialog = TestNcrnaClassDialog;
7682   dlg->change_notify = change_notify;
7683   dlg->change_userdata = change_userdata;
7684   dlg->is_constraint = is_constraint;
7685   
7686   dlg->ncrnaclass = PopupList (p, TRUE, ChangeNcrnaClass);
7687   SetObjectExtra (dlg->ncrnaclass, dlg, NULL);
7688   for (cpp = ncrnaClassList; *cpp != NULL; cpp++) {
7689     PopupItem (dlg->ncrnaclass, *cpp);
7690   }
7691   if (is_constraint) {
7692     PopupItem (dlg->ncrnaclass, "Any");
7693     SetValue (dlg->ncrnaclass, NcrnaOTHER + 1);
7694   } else {
7695     SetValue (dlg->ncrnaclass, NcrnaOTHER);
7696   }
7697   dlg->otherclass = DialogText (p, "", 10, ChangeNcrnaOtherClass);
7698   SetObjectExtra (dlg->otherclass, dlg, NULL);
7699 
7700   return (DialoG) p;
7701 }
7702 
7703 
7704 extern RnaTypePtr RnaTypeFree (RnaTypePtr rtp)
7705 {
7706   if (rtp != NULL)
7707   {
7708     rtp->ncrna_class = MemFree (rtp->ncrna_class);
7709     rtp = MemFree (rtp);
7710   }
7711   return rtp;
7712 }
7713 
7714 
7715 extern Boolean MatchesRnaType (SeqFeatPtr sfp, RnaTypePtr rtp)
7716 {
7717   RnaRefPtr rrp;
7718   RNAGenPtr rgp;
7719   Uint1     featdef;
7720   Boolean   matches = TRUE;
7721 
7722   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return FALSE;
7723   if (rtp == NULL || rtp->rna_featdef == FEATDEF_ANY) return TRUE;
7724 
7725   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
7726   if (rrp == NULL) return FALSE;
7727 
7728   featdef = RnaFeatDefFromRnaRef (rrp);
7729   if (featdef != rtp->rna_featdef) return FALSE;
7730 
7731   if (featdef == FEATDEF_ncRNA)
7732   {
7733     if (rtp->ncrna_class == NULL) {
7734       matches = TRUE;
7735     } else {
7736       if (rrp->ext.choice == 3) {
7737         rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
7738         if (StringCmp (rgp->_class, rtp->ncrna_class) == 0) {
7739           matches = TRUE;
7740         }
7741       }
7742     }
7743   }
7744   return matches; 
7745 }
7746 
7747 
7748 extern void ApplyRnaTypeToSeqFeat (SeqFeatPtr sfp, RnaTypePtr rtp)
7749 {
7750   RnaRefPtr rrp;
7751   RNAGenPtr rgp;
7752 
7753   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA)
7754   {
7755     return;
7756   }
7757 
7758   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
7759   if (rrp == NULL)
7760   {
7761     rrp = RnaRefNew();
7762     sfp->data.value.ptrvalue = rrp;
7763   }
7764 
7765   if (rtp == NULL || rtp->rna_featdef == FEATDEF_ANY)
7766   {
7767     return;
7768   }
7769 
7770   switch (rtp->rna_featdef)
7771   {
7772     case FEATDEF_preRNA:
7773       rrp->type = 1;
7774       break;
7775     case FEATDEF_mRNA:
7776       rrp->type = 2;
7777       break;
7778     case FEATDEF_tRNA:
7779       rrp->type = 3;
7780       break;
7781     case FEATDEF_rRNA:
7782       rrp->type = 4;
7783       break;
7784     case FEATDEF_scRNA:
7785     case FEATDEF_snRNA:
7786     case FEATDEF_snoRNA:
7787     case FEATDEF_ncRNA:
7788     case FEATDEF_misc_RNA:
7789       rrp->type = 8;
7790       if (rrp->ext.choice == 1) {
7791         rgp = RNAGenNew ();
7792         rgp->product = rrp->ext.value.ptrvalue;
7793         rrp->ext.value.ptrvalue = rgp;
7794         rrp->ext.choice = 3;
7795       }
7796 
7797       if (rrp->ext.choice != 3) {
7798         rrp->ext.choice = 3;        
7799         rrp->ext.value.ptrvalue = RNAGenNew ();
7800       }
7801 
7802       rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
7803       if (rgp == NULL) {
7804         rgp = RNAGenNew ();
7805         rrp->ext.value.ptrvalue = rgp;
7806       }
7807       if (rtp->rna_featdef == FEATDEF_scRNA) {
7808         rgp->_class = StringSave ("scRNA");
7809       } else if (rtp->rna_featdef == FEATDEF_snRNA) {
7810         rgp->_class = StringSave ("snRNA");
7811       } else if (rtp->rna_featdef == FEATDEF_snoRNA) {
7812         rgp->_class = StringSave ("snoRNA");
7813       } else if (rtp->rna_featdef == FEATDEF_ncRNA) {
7814         rgp->_class = StringSave (rtp->ncrna_class);
7815       } else if (rtp->rna_featdef == FEATDEF_misc_RNA) {
7816         if (IsStringInNcRNAClassList (rgp->product)) {
7817           rgp->_class = rgp->product;
7818           rgp->product = NULL;
7819         } else {
7820           rrp->type = 10;
7821         }
7822       } 
7823       break;
7824     case FEATDEF_tmRNA:
7825       rrp->type = 9;
7826       if (rrp->ext.choice == 1) {
7827         rgp = RNAGenNew ();
7828         rgp->product = rrp->ext.value.ptrvalue;
7829         rrp->ext.value.ptrvalue = rgp;
7830         rrp->ext.choice = 3;
7831       }
7832 
7833       if (rrp->ext.choice != 3) {
7834         rrp->ext.choice = 3;        
7835         rrp->ext.value.ptrvalue = RNAGenNew ();
7836       }
7837 
7838       rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
7839       if (rgp == NULL) {
7840         rgp = RNAGenNew ();
7841         rrp->ext.value.ptrvalue = rgp;
7842       }
7843       break;
7844     case FEATDEF_otherRNA:
7845       rrp->type = 255;
7846       if (rrp->ext.choice == 3) {
7847         rrp->ext.value.ptrvalue = RNAGenFree (rrp->ext.value.ptrvalue);
7848         rrp->ext.choice = 0;
7849       }
7850       if (rrp->ext.choice == 1 || rrp->ext.choice == 0) {
7851         rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
7852         rrp->ext.value.ptrvalue = StringSave ("misc_RNA");
7853         rrp->ext.choice = 1;
7854       }
7855       break;
7856   }
7857 
7858 }
7859 
7860 
7861 extern void AddToComment (SeqFeatPtr sfp, CharPtr comment)
7862 {
7863   CharPtr tmp;
7864 
7865   if (sfp == NULL || StringHasNoText (comment)) return;
7866 
7867   if (StringHasNoText (sfp->comment))
7868   {
7869     sfp->comment = MemFree (sfp->comment);
7870     sfp->comment = StringSave (comment);
7871   }
7872   else
7873   {
7874     tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (sfp->comment) + StringLen (comment) + 3));
7875     sprintf (tmp, "%s; %s", sfp->comment, comment);
7876     sfp->comment = MemFree (sfp->comment);
7877     sfp->comment = tmp;
7878   }
7879 }
7880 
7881 
7882 extern void ApplyProductToRNA (SeqFeatPtr sfp, CharPtr product)
7883 {
7884   RnaRefPtr rrp;
7885   Uint1     aa;
7886   Int4      j;
7887   Boolean   justTrnaText = FALSE;
7888   Char      codon [16];
7889   tRNAPtr   trp;
7890 
7891   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA
7892       || sfp->data.value.ptrvalue == NULL)
7893   {
7894     return;
7895   }
7896 
7897   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
7898   if (rrp->type == 3)
7899   {
7900     RemoveRNAProductString (sfp, NULL);
7901 
7902     aa = ParseTRnaString (product, &justTrnaText, (Uint1Ptr) codon, TRUE);
7903     if (aa != 0) 
7904     {
7905       trp = (tRNAPtr) MemNew (sizeof (tRNA));
7906       if (trp != NULL) 
7907       {
7908         trp->aatype = 2;
7909         for (j = 0; j < 6; j++)
7910         {
7911           trp->codon [j] = 255;
7912         }
7913         if (justTrnaText)
7914         {
7915           for (j = 0; j < 6; j++)
7916           {
7917             trp->codon [j] = codon [j];
7918           }
7919         }
7920         trp->aa = aa;
7921         rrp->ext.choice = 2;
7922         rrp->ext.value.ptrvalue = (Pointer) trp;
7923       }
7924     }
7925     if (aa == 0 || !justTrnaText)
7926     {
7927       AddToComment (sfp, product);
7928     }
7929   }
7930   else
7931   {
7932     SetRNAProductString (sfp, NULL, product, ExistingTextOption_replace_old);
7933   }
7934 }
7935 
7936 
7937 
7938 typedef struct rnatypedlg {
7939   DIALOG_MESSAGE_BLOCK
7940   PopuP                rna_type;
7941   DialoG               ncrna_class;
7942   Nlm_ChangeNotifyProc change_notify;
7943   Pointer              change_userdata;
7944   Boolean              is_constraint;
7945 
7946 } RnaTypeDlgData, PNTR RnaTypeDlgPtr;
7947 
7948 
7949 static void ChangeRnaTypeDlg (PopuP p)
7950 {
7951   RnaTypeDlgPtr dlg;
7952   UIEnum        val;
7953 
7954   dlg = (RnaTypeDlgPtr) GetObjectExtra (p);
7955   if (dlg != NULL)
7956   {
7957     if (GetEnumPopup (dlg->rna_type, rna_type_alist, &val) && val == 8)
7958     {
7959       Enable (dlg->ncrna_class);
7960     }
7961     else
7962     {
7963       Disable (dlg->ncrna_class);
7964     }
7965     if (dlg->change_notify != NULL)
7966     {
7967       (dlg->change_notify) (dlg->change_userdata);
7968     }
7969   }
7970 }
7971 
7972 
7973 static void PointerToRnaTypeDialog (DialoG d, Pointer data)
7974 {
7975   RnaTypeDlgPtr dlg;
7976   RnaTypePtr    rtp = NULL;
7977 
7978   dlg = (RnaTypeDlgPtr) GetObjectExtra (d);
7979   if (dlg == NULL) return;
7980 
7981   rtp = (RnaTypePtr) data;
7982   if (rtp == NULL || rtp->rna_featdef == FEATDEF_ANY) 
7983   {
7984     SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 0);
7985     PointerToDialog (dlg->ncrna_class, NULL);
7986   }
7987   else
7988   {
7989     SetEnumPopup (dlg->rna_type, rna_type_alist, RnaTypeFromFeatdef (rtp->rna_featdef));
7990   }
7991   ChangeRnaTypeDlg (dlg->rna_type);
7992 }
7993 
7994 
7995 static Pointer RnaTypeDialogToPointer (DialoG d)
7996 {
7997   RnaTypeDlgPtr dlg;
7998   RnaTypePtr    rtp = NULL;
7999   UIEnum        val;
8000 
8001   dlg = (RnaTypeDlgPtr) GetObjectExtra (d);
8002   if (dlg == NULL) return NULL;
8003 
8004   if (GetEnumPopup (dlg->rna_type, rna_type_alist, &val))
8005   {
8006     rtp = (RnaTypePtr) MemNew (sizeof (RnaTypeData));
8007     rtp->rna_featdef = FEATDEF_ANY;
8008     rtp->ncrna_class = NULL;
8009     switch (val)
8010     {
8011       case 0:
8012         rtp->rna_featdef = FEATDEF_ANY;
8013         break;
8014       case 1:
8015         rtp->rna_featdef = FEATDEF_preRNA;
8016         break;
8017       case 2:
8018         rtp->rna_featdef = FEATDEF_mRNA;
8019         break;
8020       case 3:
8021         rtp->rna_featdef = FEATDEF_tRNA;
8022         break;
8023       case 4:
8024         rtp->rna_featdef = FEATDEF_rRNA;
8025         break;
8026       case 8:
8027         rtp->rna_featdef = FEATDEF_ncRNA;
8028         rtp->ncrna_class = DialogToPointer (dlg->ncrna_class);
8029         break;
8030       case 9:
8031         rtp->rna_featdef = FEATDEF_tmRNA;
8032         break;
8033       case 10:
8034         rtp->rna_featdef = FEATDEF_misc_RNA;
8035         break;
8036       case 255:
8037         rtp->rna_featdef = FEATDEF_otherRNA;
8038         break;
8039     }
8040   }
8041   return rtp;
8042 }
8043  
8044 
8045 static ValNodePtr TestRnaTypeDialog (DialoG d)
8046 {
8047   RnaTypeDlgPtr dlg;
8048   ValNodePtr    err_list = NULL;
8049   UIEnum        val;
8050 
8051   dlg = (RnaTypeDlgPtr) GetObjectExtra (d);
8052   if (dlg == NULL) return NULL;
8053   if (GetEnumPopup (dlg->rna_type, rna_type_alist, &val)) {
8054     if (val == 8) {
8055       err_list = TestDialog (dlg->ncrna_class);
8056     }
8057   } else {
8058     ValNodeAddPointer (&err_list, 0, "RNA type");
8059   }
8060   return err_list;
8061 }  
8062 
8063 extern DialoG RnaTypeDialog (GrouP h, Boolean is_constraint, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
8064 {
8065   RnaTypeDlgPtr dlg;
8066   GrouP         p;
8067   CharPtr       title;
8068 
8069   if (is_constraint) {
8070     title = "RNA Type of Feature to be Edited";
8071   } else {
8072     title = "RNA Type";
8073   }
8074   
8075   p = NormalGroup (h, -1, 0, title, programFont, NULL);  
8076   dlg = (RnaTypeDlgPtr) MemNew (sizeof (RnaTypeDlgData));
8077   SetObjectExtra (p, dlg, StdCleanupExtraProc);
8078   
8079   dlg->dialog = (DialoG) p;
8080   dlg->todialog = PointerToRnaTypeDialog;
8081   dlg->fromdialog = RnaTypeDialogToPointer;
8082   dlg->testdialog = TestRnaTypeDialog;
8083   dlg->change_notify = change_notify;
8084   dlg->change_userdata = change_userdata;
8085   dlg->is_constraint = is_constraint;
8086 
8087   dlg->rna_type = PopupList (p, TRUE, ChangeRnaTypeDlg);
8088   SetObjectExtra (dlg->rna_type, dlg, NULL);
8089   InitEnumPopup (dlg->rna_type, rna_type_alist, NULL);
8090   SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 0);
8091   
8092   dlg->ncrna_class = CreatencRNAClassDialog (p, is_constraint, change_notify, change_userdata);
8093 
8094   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->rna_type, (HANDLE) dlg->ncrna_class, NULL);
8095 
8096   return (DialoG) p;
8097 }
8098 
8099 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.