1 /*   dlgutil1.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:  dlgutil1.c
27 *
28 * Author:  Jonathan Kans
29 *
30 * Version Creation Date:   1/22/95
31 *
32 * $Revision: 6.197 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date     Name        Description of modification
39 * -------  ----------  -----------------------------------------------------
40 *
41 *
42 * ==========================================================================
43 */
44 
45 #include <dlogutil.h>
46 #include <document.h>
47 #include <gather.h>
48 #include <subutil.h>
49 #include <objfdef.h>
50 #include <gbfeat.h>
51 #include <gbftdef.h>
52 #include <edutil.h>
53 #include <explore.h>
54 #include <sqnutils.h>
55 #include <alignmgr2.h>
56 #include <toasn3.h>
57 #include <vibforms.h>
58 #include <cdrgn.h>
59 #include <findrepl.h>
60 #include <pubdesc.h>
61 
62 #define NLM_GENERATED_CODE_PROTO
63 #include <objmacro.h>
64 #include <macroapi.h>
65 #include <macrodlg.h>
66 
67 /* for formatting */
68 #include <asn2gnbp.h>
69 
70 #define NUMBER_OF_SUFFIXES    13
71 
72 static CharPtr name_suffix_labels [] = {
73   " ", "Jr.", "Sr.", "II", "III", "IV", "V", "VI", "2nd", "3rd", "4th", "5th", "6th", NULL
74 };
75 
ENUM_ALIST(name_suffix_alist)76 static ENUM_ALIST(name_suffix_alist)
77   {" ",    0},
78   {"Jr.",  1},
79   {"Sr.",  2},
80   {"II",   3},
81   {"III",  4},
82   {"IV",   5},
83   {"V",    6},
84   {"VI",   7},
85   {"2nd",  8},
86   {"3rd",  9},
87   {"4th", 10},
88   {"5th", 11},
89   {"6th", 12},
90 END_ENUM_ALIST
91 
92 Uint2 author_types [] = {
93   TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_POPUP
94 };
95 
96 Uint2 std_author_widths [] = {
97   8, 4, 9, 0
98 };
99 
100 static EnumFieldAssocPtr author_popups [] = {
101   NULL, NULL, NULL, name_suffix_alist
102 };
103 
104 Uint2 str_author_widths [] = {
105   24
106 };
107 
108 typedef struct authordialog {
109   DIALOG_MESSAGE_BLOCK
110   DialoG             stdAuthor;
111   DialoG             strAuthor;
112   GrouP              stdGrp;
113   GrouP              strGrp;
114   Uint1              type;
115   Nlm_ChangeNotifyProc change_notify;
116   Pointer              change_data;
117 } AuthorDialog, PNTR AuthorDialogPtr;
118 
119 StdPrintOptionsPtr  spop = NULL;
120 
SetupPrintOptions(void)121 extern Boolean SetupPrintOptions (void)
122 
123 {
124   if (spop == NULL) {
125     spop = StdPrintOptionsNew (NULL);
126     if (spop != NULL) {
127       spop->newline = "\r";
128       spop->indent = "";
129     } else {
130       Message (MSG_FATAL, "StdPrintOptionsNew failed");
131     }
132   }
133   return (Boolean) (spop != NULL);
134 }
135 
FreePrintOptions(void)136 extern void FreePrintOptions (void)
137 
138 {
139   spop = StdPrintOptionsFree (spop);
140 }
141 
ENUM_ALIST(months_alist)142 ENUM_ALIST(months_alist)
143   {" ",     0},
144   {"Jan",   1},
145   {"Feb",   2},
146   {"Mar",   3},
147   {"Apr",   4},
148   {"May",   5},
149   {"Jun",   6},
150   {"Jul",   7},
151   {"Aug",   8},
152   {"Sep",   9},
153   {"Oct",  10},
154   {"Nov",  11},
155   {"Dec",  12},
156 END_ENUM_ALIST
157 
158 static void CopyOneDescriptorToSeqEntry (SeqDescrPtr sdp, SeqEntryPtr sep)
159 {
160   BioseqPtr bsp;
161   BioseqSetPtr bssp;
162 
163   if (sdp == NULL || sep == NULL) {
164     return;
165   }
166 
167   /* NOTE - we are using SeqDescAsnRead and SeqDescAsnWrite
168    * instead of SeqDescrAsnWrite and SeqDescrAsnWrite
169    * so that only THIS descriptor is propagated, rather than than chain
170    */
171   if (sep->choice == 1) {
172     bsp = (BioseqPtr) sep->data.ptrvalue;
173     ValNodeLink (&(bsp->descr),
174                   AsnIoMemCopy ((Pointer) sdp,
175                                 (AsnReadFunc) SeqDescAsnRead,
176                                 (AsnWriteFunc) SeqDescAsnWrite));
177   } else if (sep->choice == 2) {
178     bssp = (BioseqSetPtr) sep->data.ptrvalue;
179     ValNodeLink (&(bssp->descr),
180                   AsnIoMemCopy ((Pointer) sdp,
181                                 (AsnReadFunc) SeqDescAsnRead,
182                                 (AsnWriteFunc) SeqDescAsnWrite));
183   }
184 }
185 
186 
DescriptorPropagate(Pointer data)187 extern Int2 LIBCALLBACK DescriptorPropagate (Pointer data)
188 
189 {
190   BioseqSetPtr      bssp = NULL;
191   OMProcControlPtr  ompcp;
192   SeqDescrPtr sdp;
193   ObjValNodePtr ovp;
194   SeqEntryPtr   sep;
195 
196   ompcp = (OMProcControlPtr) data;
197   if (ompcp == NULL || ompcp->input_entityID == 0) {
198     Message (MSG_ERROR, "Please select a BioseqSet");
199     return OM_MSG_RET_ERROR;
200   }
201   switch (ompcp->input_itemtype) {
202     case OBJ_BIOSEQSET :
203       bssp = (BioseqSetPtr) ompcp->input_data;
204       break;
205     case OBJ_SEQDESC:
206       /* special case - propagate just this descriptor */
207       sdp = (SeqDescrPtr) ompcp->input_data;
208       if (sdp != NULL && sdp->extended > 0) {
209         ovp = (ObjValNodePtr) sdp;
210         if (ovp->idx.parenttype == OBJ_BIOSEQSET && ovp->idx.parentptr != NULL) {
211           bssp = ovp->idx.parentptr;
212           for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
213             CopyOneDescriptorToSeqEntry (sdp, sep);
214           }
215           ovp->idx.deleteme = TRUE;
216           DeleteMarkedObjects (ompcp->input_entityID, 0, NULL);
217           ObjMgrSetDirtyFlag (ompcp->input_entityID, TRUE);
218           ObjMgrSendMsg (OM_MSG_UPDATE, ompcp->input_entityID, 0, 0);
219           return OM_MSG_RET_DONE;
220         }
221       }
222       return OM_MSG_RET_ERROR;
223       break;
224     case 0 :
225       Message (MSG_ERROR, "Please select a BioseqSet");
226       return OM_MSG_RET_ERROR;
227     default :
228       Message (MSG_ERROR, "Please select a BioseqSet");
229       return OM_MSG_RET_ERROR;
230   }
231 
232   SetDescriptorPropagate (bssp);
233 
234   ObjMgrSetDirtyFlag (ompcp->input_entityID, TRUE);
235   ObjMgrSendMsg (OM_MSG_UPDATE, ompcp->input_entityID, 0, 0);
236   return OM_MSG_RET_DONE;
237 }
238 
OneDescriptorPropagate(Pointer data)239 static Int2 OneDescriptorPropagate (Pointer data)
240 
241 {
242   BioseqSetPtr      bssp = NULL;
243   OMProcControlPtr  ompcp;
244   ObjValNodePtr     ovp;
245   SeqDescrPtr       sdp;
246   SeqEntryPtr       sep;
247 
248   ompcp = (OMProcControlPtr) data;
249   if (ompcp == NULL || ompcp->input_entityID == 0) {
250     Message (MSG_ERROR, "Please select a BioseqSet");
251     return OM_MSG_RET_ERROR;
252   }
253   /* propagate just this descriptor */
254   sdp = (SeqDescrPtr) ompcp->output_data;
255   if (sdp != NULL && sdp->extended > 0 && ompcp->input_itemtype == OBJ_BIOSEQSET) {
256     ovp = (ObjValNodePtr) sdp;
257     bssp = (BioseqSetPtr) ompcp->input_data;
258     if (bssp != NULL) {
259       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
260         CopyOneDescriptorToSeqEntry (sdp, sep);
261       }
262       ovp->idx.deleteme = TRUE;
263       DeleteMarkedObjects (ompcp->input_entityID, 0, NULL);
264       ObjMgrSetDirtyFlag (ompcp->input_entityID, TRUE);
265       ObjMgrSendMsg (OM_MSG_UPDATE, ompcp->input_entityID, 0, 0);
266       return OM_MSG_RET_DONE;
267     }
268   }
269   return OM_MSG_RET_ERROR;
270 }
271 
DescFormReplaceWithoutUpdateProcEx(ForM f,Boolean feature_or_molinfo_change)272 extern Boolean DescFormReplaceWithoutUpdateProcEx (ForM f, Boolean feature_or_molinfo_change)
273 
274 {
275   MsgAnswer          ans;
276   DescriptorFormPtr  dfp;
277   Int4Ptr            intptr;
278   OMProcControl      ompc;
279   Boolean            rsult;
280   ValNodePtr         sdp;
281   SeqEntryPtr        sep;
282   BioseqSetPtr       bssp;
283 
284   rsult = FALSE;
285   dfp = (DescriptorFormPtr) GetObjectExtra (f);
286   if (dfp != NULL) {
287     sep = GetTopSeqEntryForEntityID (dfp->input_entityID);
288     MemSet ((Pointer) &ompc, 0, sizeof (OMProcControl));
289     ompc.input_entityID = dfp->input_entityID;
290     ompc.input_itemID = dfp->input_itemID;
291     ompc.input_itemtype = dfp->input_itemtype;
292     ompc.output_itemtype = dfp->input_itemtype;
293     sdp = SeqDescrNew (NULL);
294     if (sdp != NULL) {
295       sdp->choice = (Uint1)dfp->this_subtype;
296       switch (sdp->choice) {
297         case Seq_descr_mol_type :
298         case Seq_descr_method :
299           intptr = (Int4Ptr) DialogToPointer (dfp->data);
300           if (intptr != NULL) {
301             sdp->data.intvalue = *intptr;
302           }
303           break;
304         default :
305           sdp->data.ptrvalue = DialogToPointer (dfp->data);
306           break;
307       }
308       FixSpecialCharactersForObject (OBJ_SEQDESC, sdp, "You may not include special characters in the text.\nIf you do not choose replacement characters, these special characters will be replaced with '#'.", TRUE, NULL);
309       if (!feature_or_molinfo_change) {
310         CleanupStringsForOneDescriptor (sdp, sep);
311       }
312 
313       ompc.output_data = (Pointer) sdp;
314       if (ompc.input_entityID == 0) {
315         if (! ObjMgrRegister (OBJ_SEQDESC, (Pointer) sdp)) {
316           Message (MSG_ERROR, "ObjMgrRegister failed");
317         }
318       } else if (ompc.input_itemtype != OBJ_SEQDESC) {
319         ompc.output_itemtype = OBJ_SEQDESC;
320         if (! AttachDataForProc (&ompc, FALSE)) {
321           Message (MSG_ERROR, "AttachDataForProc failed");
322         }
323         rsult = TRUE;
324       } else {
325         if (! ReplaceDataForProc (&ompc, FALSE)) {
326           Message (MSG_ERROR, "ReplaceDataForProc failed");
327         }
328         rsult = TRUE;
329       }
330     }
331 
332     /* If the descriptor was added to a GenBank set then*/
333     /* optionally propagate it to the set's Bioseqs.    */
334 
335     if (ompc.input_itemtype == OBJ_BIOSEQSET) {
336       sep = (SeqEntryPtr) ompc.input_choice;
337       bssp = (BioseqSetPtr) sep->data.ptrvalue;
338       if (bssp->_class == BioseqseqSet_class_genbank) {
339         ans = Message (MSG_YN, "Do you wish to propagate the descriptor to "
340                        "the set's Bioseqs?");
341         if (ANS_YES == ans) {
342           OneDescriptorPropagate (&ompc);
343         }
344       }
345     }
346 
347     if (!feature_or_molinfo_change) {
348       CleanUpProteinTitles (sep);
349     }
350   }
351   return rsult;
352 }
353 
354 
DescFormReplaceWithoutUpdateProc(ForM f)355 extern Boolean DescFormReplaceWithoutUpdateProc (ForM f)
356 {
357   return DescFormReplaceWithoutUpdateProcEx (f, TRUE);
358 }
359 
360 
StdDescFormActnProcEx(ForM f,Boolean feature_or_molinfo_change)361 static void StdDescFormActnProcEx (ForM f, Boolean feature_or_molinfo_change)
362 {
363   DescriptorFormPtr  dfp;
364 
365   if (DescFormReplaceWithoutUpdateProcEx (f, feature_or_molinfo_change)) {
366     dfp = (DescriptorFormPtr) GetObjectExtra (f);
367     if (dfp != NULL) {
368       GetRidOfEmptyFeatsDescStrings (dfp->input_entityID, NULL);
369       if (feature_or_molinfo_change && GetAppProperty ("InternalNcbiSequin") != NULL) {
370         ExtendGeneFeatIfOnMRNA (dfp->input_entityID, NULL);
371       }
372 
373       ObjMgrSetDirtyFlag (dfp->input_entityID, TRUE);
374       if (feature_or_molinfo_change) {
375         ObjMgrSendMsg (OM_MSG_UPDATE, dfp->input_entityID,
376                        dfp->input_itemID, dfp->input_itemtype);
377       } else {
378         ObjMgrSendMsgNoFeatureChange(OM_MSG_UPDATE, dfp->input_entityID,
379                        dfp->input_itemID, dfp->input_itemtype);
380       }
381     }
382   }
383 
384 }
385 
386 
StdDescFormActnProc(ForM f)387 extern void StdDescFormActnProc (ForM f)
388 
389 {
390   StdDescFormActnProcEx (f, TRUE);
391 }
392 
393 
StdDescFormActnProcNoFeatureChangeNoMolInfoChange(ForM f)394 extern void StdDescFormActnProcNoFeatureChangeNoMolInfoChange (ForM f)
395 
396 {
397   StdDescFormActnProcEx (f, FALSE);
398 }
399 
400 
StdDescFormCleanupProc(GraphiC g,VoidPtr data)401 extern void StdDescFormCleanupProc (GraphiC g, VoidPtr data)
402 
403 {
404   DescriptorFormPtr  dfp;
405   Uint2              userkey;
406 
407   dfp = (DescriptorFormPtr) data;
408   if (dfp != NULL) {
409     if (dfp->input_entityID > 0 && dfp->userkey > 0) {
410       userkey = dfp->userkey;
411       dfp->userkey = 0;
412       ObjMgrFreeUserData (dfp->input_entityID, dfp->procid, dfp->proctype, userkey);
413     }
414   }
415   StdCleanupExtraProc (g, data);
416 }
417 
ItemAlreadyHasEditor(Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint2 procid)418 extern OMUserDataPtr ItemAlreadyHasEditor (Uint2 entityID, Uint4 itemID, Uint2 itemtype, Uint2 procid)
419 
420 {
421   BaseFormPtr    bfp;
422   Uint4          j;
423   Uint4          num;
424   ObjMgrPtr      omp;
425   ObjMgrDataPtr  PNTR omdpp;
426   OMUserDataPtr  omudp;
427   ObjMgrDataPtr  tmp;
428 
429   if (entityID == 0 || itemID == 0 || itemtype == 0 || procid == 0) return NULL;
430   omp = ObjMgrGet ();
431   if (omp == NULL) return NULL;
432   num = omp->currobj;
433   for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
434     tmp = *omdpp;
435     if (tmp->parentptr == NULL && tmp->EntityID == entityID) {
436 
437       for (omudp = tmp->userdata; omudp != NULL; omudp = omudp->next) {
438         if (omudp->proctype == OMPROC_EDIT && omudp->procid == procid) {
439           bfp = (BaseFormPtr) omudp->userdata.ptrvalue;
440           if (bfp != NULL) {
441             if (bfp->input_itemID == itemID && bfp->input_itemtype == itemtype) {
442               return omudp;
443             }
444           }
445         }
446       }
447     }
448   }
449   return NULL;
450 }
451 
452 
GetProcIdForItemEditor(Uint2 entityID,Uint2 itemID,Uint1 itemtype,Uint2 subinputtype)453 extern Uint2 GetProcIdForItemEditor (Uint2 entityID, Uint2 itemID, Uint1 itemtype, Uint2 subinputtype)
454 {
455   ObjMgrPtr     omp;
456     ObjMgrProcPtr ompp=NULL;
457   Uint2         best_procid = 0;
458 
459   omp = ObjMgrGet ();
460 
461     while ((ompp = ObjMgrProcFindNext(omp, OMPROC_EDIT, itemtype, itemtype, ompp)) != NULL)
462     {
463         if (ompp->subinputtype == subinputtype)
464         {
465       return ompp->procid;
466         }
467         else if (! ompp->subinputtype)  /* general proc found */
468     {
469             best_procid = ompp->procid;
470     }
471     }
472   return best_procid;
473 }
474 
475 
476 /* Note - if a viewer displays features from a far sequence mapped to
477  * the current sequence, it will register an interest in the entityID
478  * for the far sequence.
479  * To find the "main" viewer for just the original sequence, we want
480  * to find a view for which only one entityID is registered.
481  */
EntityAlreadyHasViewer(Uint2 entityID)482 extern OMUserDataPtr EntityAlreadyHasViewer (Uint2 entityID)
483 
484 {
485   BaseFormPtr    bfp;
486   Uint4          j;
487   Uint4          num;
488   ObjMgrPtr      omp;
489   ObjMgrDataPtr  PNTR omdpp;
490   OMUserDataPtr  omudp;
491   ObjMgrDataPtr  tmp;
492   ValNodePtr     found_views = NULL, vnp_view;
493   ValNodePtr     view_forms = NULL, vnp_form;
494   Boolean        not_this_one;
495 
496   if (entityID == 0) return NULL;
497   omp = ObjMgrGet ();
498   if (omp == NULL) return NULL;
499   num = omp->currobj;
500   for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
501     tmp = *omdpp;
502     if (tmp->parentptr == NULL && tmp->EntityID == entityID) {
503 
504       for (omudp = tmp->userdata; omudp != NULL; omudp = omudp->next) {
505         if (omudp->proctype == OMPROC_VIEW) {
506           bfp = (BaseFormPtr) omudp->userdata.ptrvalue;
507           if (bfp != NULL) {
508             ValNodeAddPointer (&found_views, 0, omudp);
509             ValNodeAddPointer (&view_forms, 0, bfp);
510           }
511         }
512       }
513     }
514   }
515 
516   /* now look to see if the form is also a view for another entityID */
517   for (vnp_view = found_views, vnp_form = view_forms;
518        vnp_view != NULL && vnp_form != NULL;
519        vnp_view = vnp_view->next, vnp_form = vnp_form->next) {
520     not_this_one = FALSE;
521     for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL && !not_this_one; j++, omdpp++) {
522       tmp = *omdpp;
523       if (tmp->parentptr == NULL && tmp->EntityID != entityID) {
524 
525         for (omudp = tmp->userdata; omudp != NULL && !not_this_one; omudp = omudp->next) {
526           if (omudp->proctype == OMPROC_VIEW) {
527             bfp = (BaseFormPtr) omudp->userdata.ptrvalue;
528             if (bfp != NULL && bfp == (BaseFormPtr) vnp_form->data.ptrvalue) {
529               not_this_one = TRUE;
530             }
531           }
532         }
533       }
534     }
535     if (!not_this_one) {
536       omudp = vnp_view->data.ptrvalue;
537       found_views = ValNodeFree (found_views);
538       view_forms = ValNodeFree (view_forms);
539       return omudp;
540     }
541   }
542   found_views = ValNodeFree (found_views);
543   view_forms = ValNodeFree (view_forms);
544 
545   return NULL;
546 }
547 
548 
MakeViewerIndependent(Uint2 entityID,OMUserDataPtr omudp)549 extern Boolean MakeViewerIndependent (Uint2 entityID, OMUserDataPtr omudp)
550 {
551   Uint4          j;
552   Uint4          num;
553   ObjMgrPtr      omp;
554   ObjMgrDataPtr  PNTR omdpp;
555   OMUserDataPtr  omudp_tmp;
556   ObjMgrDataPtr  tmp;
557 
558   if (entityID == 0 || omudp == NULL) return FALSE;
559   omp = ObjMgrGet ();
560   if (omp == NULL) return FALSE;
561   num = omp->currobj;
562   for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
563     tmp = *omdpp;
564     if (tmp->parentptr == NULL && tmp->EntityID == entityID) {
565       omudp_tmp = tmp->userdata;
566       while (omudp_tmp != NULL && omudp_tmp != omudp) {
567         omudp_tmp = omudp_tmp->next;
568       }
569       if (omudp_tmp != NULL) {
570         tmp->tempload = TL_NOT_TEMP;
571         return TRUE;
572       }
573     }
574   }
575   return FALSE;
576 }
577 
578 
579 typedef struct genegatherlist {
580   FeatureFormPtr  ffp;
581   ObjMgrPtr       omp;
582   SeqLocPtr       slp;
583   GeneRefPtr      genexref;
584   Boolean         xrefmatch;
585   Int2            idx;
586   Int2            val;
587   Int4            min;
588   Uint2           geneEntityID;
589   Uint4           geneItemID;
590   Uint2           geneItemtype;
591   Boolean         geneFound;
592   SeqLocPtr       old_feature_location;
593   ValNodePtr      lastgene;
594 } GeneGatherList, PNTR GeneGatherPtr;
595 
GeneFindFunc(GatherContextPtr gcp)596 static Boolean GeneFindFunc (GatherContextPtr gcp)
597 
598 {
599   GeneGatherPtr  ggp;
600   ObjMgrTypePtr  omtp;
601   SeqFeatPtr     sfp;
602   Char           thislabel [41];
603 
604   if (gcp == NULL) return TRUE;
605 
606   ggp = (GeneGatherPtr) gcp->userdata;
607   if (ggp == NULL ) return TRUE;
608 
609   thislabel [0] = '\0';
610 
611   if (gcp->thistype == OBJ_SEQFEAT) {
612     sfp = (SeqFeatPtr) gcp->thisitem;
613     if (sfp != NULL && sfp->data.choice == SEQFEAT_GENE) {
614       omtp = ObjMgrTypeFind (ggp->omp, gcp->thistype, NULL, NULL);
615       if (omtp == NULL) {
616         return TRUE;
617       }
618       if (omtp->labelfunc != NULL) {
619         (*(omtp->labelfunc)) (gcp->thisitem, thislabel, 40, OM_LABEL_CONTENT);
620       }
621       if (thislabel [0] != '\0') {
622         ggp->idx++;
623         if (ggp->idx == ggp->val) {
624           ggp->geneEntityID = gcp->entityID;
625           ggp->geneItemID = gcp->itemID;
626           ggp->geneItemtype = gcp->thistype;
627           ggp->geneFound = TRUE;
628           return FALSE;
629         }
630       }
631     }
632   }
633   return TRUE;
634 }
635 
636 extern void Nlm_LaunchGeneFeatEd (ButtoN b);
Nlm_LaunchGeneFeatEd(ButtoN b)637 extern void Nlm_LaunchGeneFeatEd (ButtoN b)
638 
639 {
640   FeatureFormPtr  ffp;
641   GeneGatherList  ggl;
642   GatherScope     gs;
643   Int2            handled;
644   Int2            val;
645 
646   ffp = (FeatureFormPtr) GetObjectExtra (b);
647   if (ffp != NULL && ffp->gene != NULL && GetValue (ffp->useGeneXref) == 1) {
648     val = GetValue (ffp->gene);
649     if (val > 2) {
650       ggl.ffp = ffp;
651       ggl.omp = ObjMgrGet ();
652       ggl.idx = 2;
653       ggl.val = val;
654       ggl.min = INT4_MAX;
655       ggl.geneFound = FALSE;
656       ggl.geneEntityID = 0;
657       ggl.geneItemID = 0;
658       ggl.geneItemtype = 0;
659       MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
660       gs.seglevels = 1;
661       gs.get_feats_location = TRUE;
662       MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
663       gs.ignore[OBJ_BIOSEQ] = FALSE;
664       gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
665       gs.ignore[OBJ_SEQFEAT] = FALSE;
666       gs.ignore[OBJ_SEQANNOT] = FALSE;
667       gs.scope = GetBestTopParentForItemID (ffp->input_entityID,
668                                             ffp->input_itemID,
669                                             ffp->input_itemtype);
670       GatherEntity (ffp->input_entityID, (Pointer) &ggl, GeneFindFunc, &gs);
671       if (ggl.geneFound) {
672         WatchCursor ();
673         Update ();
674         handled = GatherProcLaunch (OMPROC_EDIT, FALSE, ggl.geneEntityID, ggl.geneItemID,
675                                     ggl.geneItemtype, 0, 0, ggl.geneItemtype, 0);
676         ArrowCursor ();
677         Update ();
678         if (handled != OM_MSG_RET_DONE || handled == OM_MSG_RET_NOPROC) {
679           Message (MSG_ERROR, "Unable to launch editor on gene feature.");
680         }
681       }
682     }
683   }
684 }
685 
UpdateGeneLocation(SeqFeatPtr gene,SeqLocPtr old_feat_loc,SeqLocPtr new_feat_loc,Uint2 entityID)686 extern void UpdateGeneLocation
687 (SeqFeatPtr gene,
688  SeqLocPtr  old_feat_loc,
689  SeqLocPtr  new_feat_loc,
690  Uint2      entityID)
691 {
692   Uint1          strandfeat, strandgene, strandold;
693   BioseqPtr      bsp;
694   SeqLocPtr      tmpslp, slp;
695   Boolean        hasNulls;
696   Boolean        noLeft;
697   Boolean        noRight;
698   Boolean        noLeftFeat;
699   Boolean        noLeftGene;
700   Boolean        noRightFeat;
701   Boolean        noRightGene;
702 
703   if (gene == NULL || new_feat_loc == NULL)
704   {
705     return;
706   }
707 
708   strandfeat = SeqLocStrand (new_feat_loc);
709   strandgene = SeqLocStrand (gene->location);
710   if (old_feat_loc == NULL)
711   {
712     strandold = strandfeat;
713   }
714   else
715   {
716     strandold = SeqLocStrand (old_feat_loc);
717   }
718 
719   /* only correct gene location if gene is on same strand as old feature
720    * location and contained in new feature location (on either strand).
721    */
722   if (SeqLocAinB (new_feat_loc, gene->location) <= 0
723       && ((strandold == Seq_strand_minus && strandgene == Seq_strand_minus)
724           || (strandold != Seq_strand_minus && strandgene != Seq_strand_minus)))
725   {
726     bsp = GetBioseqGivenSeqLoc (gene->location, entityID);
727     if (bsp != NULL) {
728       hasNulls = LocationHasNullsBetween (gene->location);
729       if ((strandfeat == Seq_strand_minus && strandgene != Seq_strand_minus)
730           || (strandfeat != Seq_strand_minus && strandgene == Seq_strand_minus))
731       {
732         tmpslp = SeqLocCopy (gene->location);
733         SeqLocRevCmp (tmpslp);
734         slp = SeqLocMerge (bsp, tmpslp, new_feat_loc, TRUE, FALSE, hasNulls);
735         tmpslp = SeqLocFree (tmpslp);
736       }
737       else
738       {
739         slp = SeqLocMergeExEx (bsp, gene->location, new_feat_loc, TRUE, FALSE, TRUE, hasNulls, TRUE, TRUE, FALSE);
740       }
741 
742       if (slp != NULL) {
743         CheckSeqLocForPartial (gene->location, &noLeftGene, &noRightGene);
744         gene->location = SeqLocFree (gene->location);
745         gene->location = slp;
746         CheckSeqLocForPartial (new_feat_loc, &noLeftFeat, &noRightFeat);
747         if (bsp->repr == Seq_repr_seg) {
748           slp = SegLocToPartsEx (bsp, gene->location, TRUE);
749           gene->location = SeqLocFree (gene->location);
750           gene->location = slp;
751           hasNulls = LocationHasNullsBetween (gene->location);
752           gene->partial = (gene->partial || hasNulls);
753         }
754         FreeAllFuzz (gene->location);
755         noLeft = (noLeftFeat || noLeftGene);
756         noRight = (noRightFeat || noRightGene);
757         SetSeqLocPartial (gene->location, noLeft, noRight);
758         gene->partial = (gene->partial || noLeft || noRight);
759       }
760     }
761   }
762 }
763 
DlgStrandsMatch(Uint1 featstrand,Uint1 locstrand)764 static Boolean DlgStrandsMatch (Uint1 featstrand, Uint1 locstrand)
765 
766 {
767   if (featstrand == locstrand) return TRUE;
768   if (locstrand == Seq_strand_unknown && featstrand != Seq_strand_minus) return TRUE;
769   if (featstrand == Seq_strand_unknown && locstrand != Seq_strand_minus) return TRUE;
770   if (featstrand == Seq_strand_both && locstrand != Seq_strand_minus) return TRUE;
771   if (locstrand == Seq_strand_both) return TRUE;
772   return FALSE;
773 }
774 
GeneUpdateFunc(GatherContextPtr gcp)775 static Boolean GeneUpdateFunc (GatherContextPtr gcp)
776 
777 {
778   GeneGatherPtr  ggp;
779   ObjMgrTypePtr  omtp;
780   SeqFeatPtr     sfp;
781   Uint1          strand1, strand2;
782   Char           thislabel [41];
783 
784   if (gcp == NULL) return TRUE;
785 
786   ggp = (GeneGatherPtr) gcp->userdata;
787   if (ggp == NULL ) return TRUE;
788 
789   thislabel [0] = '\0';
790 
791   if (gcp->thistype == OBJ_SEQFEAT) {
792     sfp = (SeqFeatPtr) gcp->thisitem;
793     if (sfp != NULL && sfp->data.choice == SEQFEAT_GENE) {
794       omtp = ObjMgrTypeFind (ggp->omp, gcp->thistype, NULL, NULL);
795       if (omtp == NULL) {
796         return TRUE;
797       }
798       if (omtp->labelfunc != NULL) {
799         (*(omtp->labelfunc)) (gcp->thisitem, thislabel, 40, OM_LABEL_CONTENT);
800       }
801       if (thislabel [0] != '\0') {
802         ggp->idx++;
803         if (ggp->idx == ggp->val) {
804           strand1 = SeqLocStrand (sfp->location);
805           strand2 = SeqLocStrand (ggp->slp);
806           if (DlgStrandsMatch (strand1, strand2)) {
807             UpdateGeneLocation (sfp, ggp->old_feature_location, ggp->slp, gcp->entityID);
808             return FALSE;
809           }
810         }
811       }
812     }
813   }
814   return TRUE;
815 }
816 
GeneGatherFunc(GatherContextPtr gcp)817 static Boolean GeneGatherFunc (GatherContextPtr gcp)
818 
819 {
820   FeatureFormPtr  ffp;
821   GeneGatherPtr   ggp;
822   GeneRefPtr      grp;
823   ObjMgrTypePtr   omtp;
824   SeqFeatPtr      sfp;
825   Char            thislabel [41];
826   ValNodePtr      vnp;
827 
828   if (gcp == NULL) return TRUE;
829 
830   ggp = (GeneGatherPtr) gcp->userdata;
831   if (ggp == NULL || ggp->ffp == NULL) return TRUE;
832 
833   thislabel [0] = '\0';
834 
835   if (gcp->thistype == OBJ_SEQFEAT) {
836     sfp = (SeqFeatPtr) gcp->thisitem;
837     if (sfp != NULL && sfp->data.choice == SEQFEAT_GENE) {
838       omtp = ObjMgrTypeFind (ggp->omp, gcp->thistype, NULL, NULL);
839       if (omtp == NULL) {
840         return TRUE;
841       }
842       if (omtp->labelfunc != NULL) {
843         (*(omtp->labelfunc)) (gcp->thisitem, thislabel, 40, OM_LABEL_CONTENT);
844       }
845       if (thislabel [0] != '\0') {
846         ffp = (FeatureFormPtr) ggp->ffp;
847         grp = (GeneRefPtr) sfp->data.value.ptrvalue;
848         if (grp != NULL
849             && (grp->locus != NULL || grp->locus_tag != NULL || grp->desc != NULL))
850         {
851           vnp = ValNodeNew (ggp->lastgene);
852           if (ffp->geneNames == NULL) {
853             ffp->geneNames = vnp;
854           }
855           ggp->lastgene = vnp;
856           if (vnp != NULL) {
857             vnp->data.ptrvalue = StringSave (thislabel);
858             if (grp->locus != NULL) {
859               vnp->choice = 1;
860             } else if (grp->desc != NULL) {
861               vnp->choice = 2;
862             } else if (grp->locus_tag != NULL) {
863               vnp->choice = 3;
864             }
865           }
866         }
867       }
868     }
869   }
870 
871   return TRUE;
872 }
873 
PopulateGenePopup(FeatureFormPtr ffp)874 extern void PopulateGenePopup (FeatureFormPtr ffp)
875 
876 {
877   Int2            count;
878   GeneGatherList  ggl;
879   GatherScope     gs;
880   CharPtr         str;
881   Boolean         usePopupForGene;
882   ValNodePtr      vnp;
883 
884   if (ffp != NULL && ffp->genePopup != NULL && ffp->geneList != NULL) {
885     ggl.ffp = ffp;
886     ggl.omp = ObjMgrGet ();
887     ggl.slp = NULL;
888     ggl.genexref = NULL;
889     ggl.xrefmatch = FALSE;
890     ggl.idx = 0;
891     ggl.val = 0;
892     ggl.min = 0;
893     ggl.lastgene = NULL;
894     MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
895     gs.seglevels = 1;
896     gs.get_feats_location = TRUE;
897     MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
898     gs.ignore[OBJ_BIOSEQ] = FALSE;
899     gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
900     gs.ignore[OBJ_SEQFEAT] = FALSE;
901     gs.ignore[OBJ_SEQANNOT] = FALSE;
902     gs.scope = GetBestTopParentForItemID (ffp->input_entityID,
903                                           ffp->input_itemID,
904                                           ffp->input_itemtype);
905     GatherEntity (ffp->input_entityID, (Pointer) &ggl, GeneGatherFunc, &gs);
906     count = 0;
907     for (vnp = ffp->geneNames; vnp != NULL; vnp = vnp->next) {
908       count++;
909     }
910     if (count < 32) {
911       usePopupForGene = TRUE;
912       ffp->gene = ffp->genePopup;
913     } else {
914       usePopupForGene = FALSE;
915       ffp->gene = ffp->geneList;
916     }
917     for (vnp = ffp->geneNames; vnp != NULL; vnp = vnp->next) {
918       str = (CharPtr) vnp->data.ptrvalue;
919       if (StringHasNoText (str)) {
920         str = "??";
921       }
922       if (usePopupForGene) {
923         PopupItem (ffp->gene, str);
924       } else {
925         ListItem (ffp->gene, str);
926       }
927     }
928     Show (ffp->gene);
929   }
930 }
931 
GeneMatchFunc(GatherContextPtr gcp)932 static Boolean GeneMatchFunc (GatherContextPtr gcp)
933 
934 {
935   Int4            diff;
936   FeatureFormPtr  ffp;
937   GeneRefPtr      genexref;
938   GeneGatherPtr   ggp;
939   GeneRefPtr      grp;
940   ObjMgrTypePtr   omtp;
941   SeqFeatPtr      sfp;
942   Uint1           strand1, strand2;
943   Char            thislabel [41];
944 
945   if (gcp == NULL) return TRUE;
946 
947   ggp = (GeneGatherPtr) gcp->userdata;
948   if (ggp == NULL || ggp->ffp == NULL) return TRUE;
949 
950   thislabel [0] = '\0';
951 
952   if (gcp->thistype == OBJ_SEQFEAT) {
953     sfp = (SeqFeatPtr) gcp->thisitem;
954     if (sfp != NULL && sfp->data.choice == SEQFEAT_GENE && sfp->data.value.ptrvalue != NULL) {
955       omtp = ObjMgrTypeFind (ggp->omp, gcp->thistype, NULL, NULL);
956       if (omtp == NULL) {
957         return TRUE;
958       }
959       if (omtp->labelfunc != NULL) {
960         (*(omtp->labelfunc)) (gcp->thisitem, thislabel, 40, OM_LABEL_CONTENT);
961       }
962       if (thislabel [0] != '\0') {
963         ffp = (FeatureFormPtr) ggp->ffp;
964         ggp->idx++;
965         genexref = ggp->genexref;
966         if (genexref != NULL) {
967           grp = (GeneRefPtr) sfp->data.value.ptrvalue;
968           if (! StringHasNoText (genexref->locus)) {
969             if (StringICmp (genexref->locus, grp->locus) == 0) {
970               ggp->val = ggp->idx;
971               ggp->xrefmatch = TRUE;
972               if (ffp != NULL) {
973                 SetValue (ffp->useGeneXref, 2);
974               }
975             }
976           } else if (! StringHasNoText (genexref->locus_tag)) {
977             if (StringICmp (genexref->locus_tag, grp->locus_tag) == 0) {
978               ggp->val = ggp->idx;
979               ggp->xrefmatch = TRUE;
980               if (ffp != NULL) {
981                 SetValue (ffp->useGeneXref, 2);
982               }
983             }
984           } else if (! StringHasNoText (genexref->desc)) {
985             if (StringICmp (genexref->desc, grp->desc) == 0) {
986               ggp->val = ggp->idx;
987               ggp->xrefmatch = TRUE;
988               if (ffp != NULL) {
989                 SetValue (ffp->useGeneXref, 2);
990               }
991             }
992           }
993         }
994         diff = SeqLocAinB (ggp->slp, sfp->location);
995         if (diff >= 0) {
996           if (diff < ggp->min) {
997             strand1 = SeqLocStrand (ggp->slp);
998             strand2 = SeqLocStrand (sfp->location);
999             if (DlgStrandsMatch (strand1, strand2)) {
1000               ggp->min = diff;
1001               if (! ggp->xrefmatch) {
1002                 ggp->val = ggp->idx;
1003               }
1004             }
1005           }
1006         }
1007       }
1008     }
1009   }
1010 
1011   return TRUE;
1012 }
1013 
SaveGoTermsInSfp(UserObjectPtr uop,Pointer userdata)1014 static void SaveGoTermsInSfp (UserObjectPtr uop, Pointer userdata)
1015 
1016 {
1017   FeatureFormPtr  ffp;
1018   ObjectIdPtr     oip;
1019 
1020   if (uop == NULL || userdata == NULL) return;
1021   oip = uop->type;
1022   if (oip == NULL) return;
1023   if (StringCmp (oip->str, "GeneOntology") == 0) {
1024     ffp = (FeatureFormPtr) userdata;
1025     ffp->goTermUserObj = AsnIoMemCopy (uop, (AsnReadFunc) UserObjectAsnRead,
1026                                        (AsnWriteFunc) UserObjectAsnWrite);
1027   }
1028 }
1029 
FeatIDtoText(TexT t,ChoicePtr cp)1030 static void FeatIDtoText (TexT t, ChoicePtr cp)
1031 
1032 {
1033   Char         buf [32];
1034   ObjectIdPtr  oip;
1035 
1036   if (t == NULL) return;
1037   if (cp == NULL) {
1038     SetTitle (t, "");
1039     return;
1040   }
1041 
1042   if (cp->choice == 3) {
1043     oip = (ObjectIdPtr) cp->value.ptrvalue;
1044     if (oip != NULL) {
1045       if (StringDoesHaveText (oip->str)) {
1046         SetTitle (t, oip->str);
1047         return;
1048       } else {
1049         sprintf (buf, "%ld", (long) oip->id);
1050         SetTitle (t, buf);
1051         return;
1052       }
1053     }
1054   }
1055 
1056   SetTitle (t, "");
1057 }
1058 
TextToFeatID(TexT t,ChoicePtr cp)1059 NLM_EXTERN void TextToFeatID (TexT t, ChoicePtr cp)
1060 
1061 {
1062   Boolean      all_digits = TRUE;
1063   Char         buf [128];
1064   Char         ch;
1065   ObjectIdPtr  oip;
1066   CharPtr      str;
1067   long int     val;
1068 
1069   if (t == NULL || cp == NULL) return;
1070 
1071   GetTitle (t, buf, sizeof (buf) - 1);
1072   if (StringHasNoText (buf)) {
1073     SeqFeatIdFree (cp);
1074     cp->choice = 0;
1075     return;
1076   }
1077 
1078   oip = ObjectIdNew ();
1079   if (oip == NULL) return;
1080 
1081   str = buf;
1082   ch = *str;
1083   while (ch != '\0') {
1084     if (! IS_DIGIT (ch)) {
1085       all_digits = FALSE;
1086     }
1087     str++;
1088     ch = *str;
1089   }
1090 
1091   if (all_digits && sscanf (buf, "%ld", &val) == 1) {
1092     oip->id = (Int4) val;
1093   } else {
1094     oip->str = StringSave (buf);
1095   }
1096   SeqFeatIdFree (cp);
1097   cp->choice = 3;
1098   cp->value.ptrvalue = (Pointer) oip;
1099 }
1100 
FeatXreftoText(TexT t,SeqFeatPtr sfp)1101 static void FeatXreftoText (TexT t, SeqFeatPtr sfp)
1102 
1103 {
1104   Char            buf [32];
1105   ObjectIdPtr     oip;
1106   SeqFeatXrefPtr  xref;
1107 
1108   if (t == NULL) return;
1109   if (sfp == NULL) {
1110     SetTitle (t, "");
1111     return;
1112   }
1113 
1114   for (xref = sfp->xref; xref != NULL; xref = xref->next) {
1115     if (xref->id.choice != 3) continue;
1116     oip = (ObjectIdPtr) xref->id.value.ptrvalue;
1117     if (oip != NULL) {
1118       if (StringDoesHaveText (oip->str)) {
1119         SetTitle (t, oip->str);
1120         return;
1121       } else {
1122         sprintf (buf, "%ld", (long) oip->id);
1123         SetTitle (t, buf);
1124         return;
1125       }
1126     }
1127   }
1128 
1129   SetTitle (t, "");
1130 }
1131 
TextToFeatXref(TexT t,SeqFeatPtr sfp)1132 NLM_EXTERN void TextToFeatXref (TexT t, SeqFeatPtr sfp)
1133 
1134 {
1135   Boolean         all_digits = TRUE;
1136   Char            buf [128];
1137   Char            ch;
1138   ObjectIdPtr     oip;
1139   CharPtr         str;
1140   long int        val;
1141   SeqFeatXrefPtr  xref;
1142 
1143   if (t == NULL || sfp == NULL) return;
1144 
1145   GetTitle (t, buf, sizeof (buf) - 1);
1146   if (StringHasNoText (buf)) {
1147     ClearFeatIDXrefs (sfp);
1148     return;
1149   }
1150 
1151   ClearFeatIDXrefs (sfp);
1152 
1153   oip = ObjectIdNew ();
1154   if (oip == NULL) return;
1155 
1156   str = buf;
1157   ch = *str;
1158   while (ch != '\0') {
1159     if (! IS_DIGIT (ch)) {
1160       all_digits = FALSE;
1161     }
1162     str++;
1163     ch = *str;
1164   }
1165 
1166   if (all_digits && sscanf (buf, "%ld", &val) == 1) {
1167     oip->id = (Int4) val;
1168   } else {
1169     oip->str = StringSave (buf);
1170   }
1171 
1172   xref = SeqFeatXrefNew ();
1173   if (xref != NULL) {
1174     xref->id.choice = 3;
1175     xref->id.value.ptrvalue = (Pointer) oip;
1176     xref->next = sfp->xref;
1177     sfp->xref = xref;
1178   }
1179 }
1180 
SafeSetEnumPopupByName(PopuP lst,EnumFieldAssocPtr al,CharPtr name)1181 static void SafeSetEnumPopupByName (PopuP lst, EnumFieldAssocPtr al, CharPtr name)
1182 
1183 {
1184   if (StringDoesHaveText (name)) {
1185     SetEnumPopupByName (lst, al, name);
1186   } else {
1187     SetEnumPopupByName (lst, al, " ");
1188   }
1189 }
1190 
ENUM_ALIST(new_pseudogene_alist)1191 ENUM_ALIST(new_pseudogene_alist)
1192   { " ",              0 },
1193   { "Processed",      1 },
1194   { "Unprocessed",    2 },
1195   { "Unitary",        3 },
1196   { "Allelic",        4 },
1197   { "Unknown",        5 },
1198 END_ENUM_ALIST
1199 
1200 ENUM_ALIST(legacy_pseudogene_alist)
1201   { " ",              0 },
1202   { "Processed",      1 },
1203   { "Unprocessed",    2 },
1204   { "Unitary",        3 },
1205   { "Allelic",        4 },
1206   { "Unknown",        5 },
1207   { "Unqualified",  255 },
1208 END_ENUM_ALIST
1209 
1210 extern void InitPseudogenePopup (FeatureFormPtr ffp, PopuP p, Boolean ispseudo, CharPtr pseudogene, Boolean indexerVersion)
1211 
1212 {
1213   if (ffp == NULL) return;
1214   ffp->pseudoalist = new_pseudogene_alist;
1215   if (indexerVersion) {
1216     ffp->pseudoalist = legacy_pseudogene_alist;
1217   } else if (ispseudo && pseudogene == NULL) {
1218     ffp->pseudoalist = legacy_pseudogene_alist;
1219   } else if (ispseudo) {
1220     if ((StringICmp (pseudogene, "processed") != 0) &&
1221         (StringICmp (pseudogene, "unprocessed") != 0) &&
1222         (StringICmp (pseudogene, "unitary") != 0) &&
1223         (StringICmp (pseudogene, "allelic") != 0) &&
1224         (StringICmp (pseudogene, "unknown") != 0)) {
1225       ffp->pseudoalist = legacy_pseudogene_alist;
1226     }
1227   }
1228   InitEnumPopup (p, ffp->pseudoalist, NULL);
1229 }
1230 
GbqualsToPseudogenePopup(SeqFeatPtr sfp,FeatureFormPtr ffp,PopuP p)1231 static void GbqualsToPseudogenePopup (SeqFeatPtr sfp, FeatureFormPtr ffp, PopuP p)
1232 
1233 {
1234   GBQualPtr  gbq;
1235   CharPtr    str = NULL;
1236 
1237   if (sfp == NULL) {
1238     SetValue (p, 0);
1239     return;
1240   }
1241 
1242   if (ffp == NULL) return;
1243 
1244   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
1245     if (StringICmp (gbq->qual, "pseudogene") != 0) continue;
1246     str = gbq->val;
1247   }
1248 
1249   if (StringHasNoText (str) && sfp->pseudo) {
1250     str = "Unqualified";
1251   }
1252 
1253   SafeSetEnumPopupByName (p, ffp->pseudoalist, str);
1254 }
1255 
PseudogenePopupToGbquals(SeqFeatPtr sfp,FeatureFormPtr ffp,PopuP p)1256 static void PseudogenePopupToGbquals (SeqFeatPtr sfp, FeatureFormPtr ffp, PopuP p)
1257 
1258 {
1259   Char       ch;
1260   GBQualPtr  gbq, gbqlast = NULL;
1261   CharPtr    str;
1262 
1263   if (sfp == NULL) return;
1264   if (ffp == NULL) return;
1265 
1266   str = GetEnumPopupByName (p, ffp->pseudoalist);
1267   if (StringHasNoText (str)) return;
1268 
1269   if (StringICmp (str, "Unqualified") == 0) {
1270     sfp->pseudo = TRUE;
1271     MemFree (str);
1272     return;
1273   }
1274 
1275   ch = str [0];
1276   str [0] = TO_LOWER (ch);
1277 
1278   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
1279     gbqlast = gbq;
1280   }
1281 
1282   gbq = GBQualNew ();
1283   if (gbq == NULL) return;
1284   gbq->qual = StringSave ("pseudogene");
1285   gbq->val = str;
1286   if (gbqlast == NULL) {
1287     sfp->qual = gbq;
1288   } else {
1289     gbqlast->next = gbq;
1290   }
1291 }
1292 
GbqualsToVisStringDialog(SeqFeatPtr sfp,DialoG d,CharPtr qual)1293 static void GbqualsToVisStringDialog (SeqFeatPtr sfp, DialoG d, CharPtr qual)
1294 
1295 {
1296   GBQualPtr   gbq;
1297   ValNodePtr  head = NULL;
1298 
1299   if (sfp == NULL || StringHasNoText (qual)) {
1300     PointerToDialog (d, NULL);
1301     return;
1302   }
1303   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
1304     if (StringICmp (gbq->qual, qual) != 0) continue;
1305     ValNodeCopyStr (&head, 0, gbq->val);
1306   }
1307   PointerToDialog (d, head);
1308   ValNodeFreeData (head);
1309 }
1310 
1311 extern void VisStringDialogToGbquals (SeqFeatPtr sfp, DialoG d, CharPtr qual);
VisStringDialogToGbquals(SeqFeatPtr sfp,DialoG d,CharPtr qual)1312 extern void VisStringDialogToGbquals (SeqFeatPtr sfp, DialoG d, CharPtr qual)
1313 
1314 {
1315   GBQualPtr   gbq, gbqlast = NULL;
1316   ValNodePtr  head = NULL, vnp;
1317   CharPtr     str;
1318 
1319   if (sfp == NULL || StringHasNoText (qual)) return;
1320   head = DialogToPointer (d);
1321   for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
1322     gbqlast = gbq;
1323   }
1324   for (vnp = head; vnp != NULL; vnp = vnp->next) {
1325     str = (CharPtr) vnp->data.ptrvalue;
1326     if (StringHasNoText (str)) continue;
1327     gbq = GBQualNew ();
1328     if (gbq == NULL) continue;
1329     gbq->qual = StringSave (qual);
1330     gbq->val = StringSave (str);
1331     if (gbqlast == NULL) {
1332       sfp->qual = gbq;
1333     } else {
1334       gbqlast->next = gbq;
1335     }
1336     gbqlast = gbq;
1337   }
1338   ValNodeFreeData (head);
1339 }
1340 
1341 extern void SeqFeatPtrToFieldPage (DialoG d, SeqFeatPtr sfp);
1342 
SeqFeatPtrToCommon(FeatureFormPtr ffp,SeqFeatPtr sfp)1343 extern void SeqFeatPtrToCommon (FeatureFormPtr ffp, SeqFeatPtr sfp)
1344 
1345 {
1346   GeneGatherList  ggl;
1347   GeneRefPtr      grp;
1348   GatherScope     gs;
1349   ProtRefPtr      prp;
1350   CharPtr         str;
1351   ValNodePtr      vnp;
1352   SeqFeatXrefPtr  xref;
1353   /*
1354   Char            ch;
1355   CharPtr         ptr;
1356   */
1357 
1358   if (ffp != NULL) {
1359     if (sfp != NULL) {
1360       str = StringSave (sfp->comment);
1361       /*
1362       ptr = str;
1363       if (ptr != NULL) {
1364         ch = *ptr;
1365         while (ch != '\0') {
1366           if (ch == '~') {
1367 #ifdef WIN_MAC
1368             *ptr = '\015';
1369 #else
1370             *ptr = '\n';
1371 #endif
1372           }
1373           ptr++;
1374           ch = *ptr;
1375         }
1376       }
1377       */
1378       SetTitle (ffp->comment, str);
1379       SetTitle (ffp->title, sfp->title);
1380       SetValue (ffp->evidence, sfp->exp_ev + 1);
1381       if (GetAppProperty ("InternalNcbiSequin") == NULL) {
1382         if (sfp->exp_ev == 0) {
1383           SafeDisable (ffp->evidence);
1384         }
1385       }
1386       SetStatus (ffp->partial, sfp->partial);
1387       SetStatus (ffp->exception, sfp->excpt);
1388       SetStatus (ffp->pseudo, sfp->pseudo);
1389       SetTitle (ffp->exceptText, sfp->except_text);
1390       SetValue (ffp->useGeneXref, 1);
1391       SetTitle (ffp->geneSymbol, "");
1392       SetTitle (ffp->geneAllele, "");
1393       SetTitle (ffp->geneDesc, "");
1394       SetTitle (ffp->locusTag, "");
1395       SetTitle (ffp->geneSynonym, "");
1396       ggl.ffp = ffp;
1397       ggl.omp = ObjMgrGet ();
1398       ggl.slp = sfp->location;
1399       ggl.genexref = NULL;
1400       grp = NULL;
1401       xref = sfp->xref;
1402       while (xref != NULL && xref->data.choice != SEQFEAT_PROT) {
1403         xref = xref->next;
1404       }
1405       if (xref != NULL) {
1406         prp = (ProtRefPtr) xref->data.value.ptrvalue;
1407         if (prp != NULL && ffp->protXrefName != NULL) {
1408           vnp = prp->name;
1409           if (vnp != NULL) {
1410             SetTitle (ffp->protXrefName, (CharPtr) vnp->data.ptrvalue);
1411           }
1412         }
1413         if (prp != NULL && StringDoesHaveText (prp->desc)) {
1414           SetTitle (ffp->protXrefDesc, prp->desc);
1415         }
1416       }
1417       xref = sfp->xref;
1418       while (xref != NULL && xref->data.choice != SEQFEAT_GENE) {
1419         xref = xref->next;
1420       }
1421       if (xref != NULL) {
1422         grp = (GeneRefPtr) xref->data.value.ptrvalue;
1423         ggl.genexref = grp;
1424       }
1425       ggl.xrefmatch = FALSE;
1426       ggl.idx = 2;
1427       ggl.val = 1;
1428       ggl.min = INT4_MAX;
1429       MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
1430       gs.seglevels = 1;
1431       gs.get_feats_location = TRUE;
1432       MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
1433       gs.ignore[OBJ_BIOSEQ] = FALSE;
1434       gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
1435       gs.ignore[OBJ_SEQFEAT] = FALSE;
1436       gs.ignore[OBJ_SEQANNOT] = FALSE;
1437       gs.scope = GetBestTopParentForItemID (ffp->input_entityID,
1438                                             ffp->input_itemID,
1439                                             ffp->input_itemtype);
1440       GatherEntity (ffp->input_entityID, (Pointer) &ggl, GeneMatchFunc, &gs);
1441       if (grp != NULL && StringHasNoText (grp->locus) && StringHasNoText (grp->allele) &&
1442             StringHasNoText (grp->desc) && StringHasNoText (grp->maploc) &&
1443             grp->db == NULL && grp->syn == NULL && grp->locus_tag == NULL) {
1444         SetValue (ffp->gene, 1);
1445         SetValue (ffp->useGeneXref, 3);
1446         SetTitle (ffp->geneSymbol, grp->locus);
1447         SetTitle (ffp->geneAllele, grp->allele);
1448         SetTitle (ffp->geneDesc, grp->desc);
1449         SetTitle (ffp->locusTag, grp->locus_tag);
1450         if (grp->syn == NULL) {
1451           SetTitle (ffp->geneSynonym, "");
1452         } else {
1453           SetTitle (ffp->geneSynonym, grp->syn->data.ptrvalue);
1454         }
1455         SafeHide (ffp->editGeneBtn);
1456         SafeHide (ffp->newGeneGrp);
1457       } else if (ggl.val == 1 && grp != NULL && (! ggl.xrefmatch)) {
1458         SetValue (ffp->gene, 2);
1459         SetValue (ffp->useGeneXref, 2);
1460         SetTitle (ffp->geneSymbol, grp->locus);
1461         SetTitle (ffp->geneAllele, grp->allele);
1462         SetTitle (ffp->geneDesc, grp->desc);
1463         SetTitle (ffp->locusTag, grp->locus_tag);
1464         if (grp->syn == NULL) {
1465           SetTitle (ffp->geneSynonym, "");
1466         } else {
1467           SetTitle (ffp->geneSynonym, grp->syn->data.ptrvalue);
1468         }
1469         SafeHide (ffp->editGeneBtn);
1470         SafeShow (ffp->newGeneGrp);
1471       } else if (grp != NULL && (! ggl.xrefmatch)) {
1472         SetValue (ffp->gene, 2);
1473         SetValue (ffp->useGeneXref, 2);
1474         SetTitle (ffp->geneSymbol, grp->locus);
1475         SetTitle (ffp->geneAllele, grp->allele);
1476         SetTitle (ffp->geneDesc, grp->desc);
1477         SetTitle (ffp->locusTag, grp->locus_tag);
1478         if (grp->syn == NULL) {
1479           SetTitle (ffp->geneSynonym, "");
1480         } else {
1481           SetTitle (ffp->geneSynonym, grp->syn->data.ptrvalue);
1482         }
1483         SafeHide (ffp->editGeneBtn);
1484         SafeShow (ffp->newGeneGrp);
1485       } else if (ggl.val > 2) {
1486         SetValue (ffp->gene, ggl.val);
1487         SafeShow (ffp->editGeneBtn);
1488         if (ffp->gene == ffp->geneList) {
1489           SetOffset (ffp->gene, 0, (Int2) (ggl.val - 1));
1490         }
1491         if (grp != NULL && (! ggl.xrefmatch)) {
1492           SetValue (ffp->useGeneXref, 2);
1493         }
1494       } else {
1495         SetValue (ffp->gene, ggl.val);
1496       }
1497       PointerToDialog (ffp->featcits, sfp->cit);
1498       PointerToDialog (ffp->dbxrefs, sfp->dbxref);
1499       PointerToDialog (ffp->gbquals, sfp->qual);
1500       SeqFeatPtrToFieldPage (ffp->gbquals, sfp);
1501       GbqualsToPseudogenePopup (sfp, ffp, ffp->pseudogene);
1502       GBQualsToExperimentDialog (sfp, ffp->experiment);
1503       GBQualsToInferenceDialog (ffp->inference, sfp);
1504       PointerToDialog (ffp->usrobjext, sfp->ext);
1505       VisitUserObjectsInUop (sfp->ext, (Pointer) ffp, SaveGoTermsInSfp);
1506       FeatIDtoText (ffp->featid, &(sfp->id));
1507       FeatXreftoText (ffp->fidxref, sfp);
1508     } else {
1509       SetTitle (ffp->comment, "");
1510       SetValue (ffp->evidence, 1);
1511       if (GetAppProperty ("InternalNcbiSequin") == NULL) {
1512         SafeDisable (ffp->evidence);
1513       }
1514       SetStatus (ffp->partial, FALSE);
1515       SetStatus (ffp->exception, FALSE);
1516       SetStatus (ffp->pseudo, FALSE);
1517       SetTitle (ffp->exceptText, "");
1518       SetValue (ffp->gene, 1);
1519       SafeHide (ffp->newGeneGrp);
1520       SafeHide (ffp->editGeneBtn);
1521       SetValue (ffp->useGeneXref, 1);
1522       SetTitle (ffp->geneSymbol, "");
1523       SetTitle (ffp->geneAllele, "");
1524       SetTitle (ffp->geneDesc, "");
1525       SetTitle (ffp->locusTag, "");
1526       SetTitle (ffp->geneSynonym, "");
1527       PointerToDialog (ffp->featcits, NULL);
1528       PointerToDialog (ffp->dbxrefs, NULL);
1529       PointerToDialog (ffp->gbquals, NULL);
1530       PointerToDialog (ffp->experiment, NULL);
1531       GBQualsToInferenceDialog (ffp->inference, NULL);
1532       PointerToDialog (ffp->usrobjext, NULL);
1533       ffp->goTermUserObj = NULL;
1534       FeatIDtoText (ffp->featid, NULL);
1535       FeatXreftoText (ffp->fidxref, NULL);
1536     }
1537   }
1538 }
1539 
CleanupEvidenceGBQuals(GBQualPtr PNTR prevgbq)1540 extern void CleanupEvidenceGBQuals (GBQualPtr PNTR prevgbq)
1541 
1542 {
1543   GBQualPtr  gbq;
1544   GBQualPtr  next;
1545   Boolean    unlink;
1546 
1547   if (prevgbq == NULL) return;
1548   gbq = *prevgbq;
1549   while (gbq != NULL) {
1550     next = gbq->next;
1551     unlink = FALSE;
1552     if (StringICmp (gbq->qual, "experiment") == 0 ||
1553         StringICmp (gbq->qual, "inference") == 0 ||
1554         StringICmp (gbq->qual, "pseudogene") == 0) {
1555       unlink = TRUE;
1556     }
1557     if (unlink) {
1558       *prevgbq = gbq->next;
1559       gbq->next = NULL;
1560       GBQualFree (gbq);
1561     } else {
1562       prevgbq = (GBQualPtr PNTR) &(gbq->next);
1563     }
1564     gbq = next;
1565   }
1566 }
1567 
CombineGOTermUserObjects(UserObjectPtr origuop,UserObjectPtr newuop)1568 static UserObjectPtr CombineGOTermUserObjects (UserObjectPtr origuop, UserObjectPtr newuop)
1569 
1570 {
1571   ObjectIdPtr  oip;
1572 
1573   if (newuop == NULL) return origuop;
1574   if (origuop == NULL) return newuop;
1575 
1576   oip = origuop->type;
1577   if (oip != NULL && StringCmp (oip->str, "GeneOntology") == 0) return origuop;
1578 
1579   return CombineUserObjects (origuop, newuop);
1580 }
1581 
1582 typedef struct replacesdata {
1583   FeatureFormPtr  ffp;
1584   SeqFeatPtr      sfp;
1585 } ReplaceData, PNTR ReplaceDataPtr;
1586 
ReplaceFeatureExtras(GatherContextPtr gcp)1587 static Boolean ReplaceFeatureExtras (GatherContextPtr gcp)
1588 
1589 {
1590   SeqFeatXrefPtr  curr;
1591   FeatureFormPtr  ffp;
1592   SeqFeatXrefPtr  PNTR last;
1593   SeqFeatXrefPtr  next;
1594   SeqFeatPtr      old;
1595   ReplaceDataPtr  rdp;
1596   SeqFeatPtr      sfp;
1597 
1598   rdp = (ReplaceDataPtr) gcp->userdata;
1599   if (rdp != NULL && rdp->sfp != NULL && rdp->ffp != NULL) {
1600     sfp = rdp->sfp;
1601     ffp = rdp->ffp;
1602     old = gcp->thisitem;
1603     if (old != NULL) {
1604       if (ffp->gbquals != NULL) {
1605         sfp->qual = DialogToPointer (ffp->gbquals);
1606       } else if (sfp->qual == NULL) {
1607         sfp->qual = old->qual;
1608         old->qual = NULL;
1609       }
1610       CleanupEvidenceGBQuals (&(sfp->qual));
1611       PseudogenePopupToGbquals (sfp, ffp, ffp->pseudogene);
1612       VisStringDialogToGbquals (sfp, ffp->experiment, "experiment");
1613       InferenceDialogToGBQuals (ffp->inference, sfp, TRUE);
1614       if (ffp->usrobjext != NULL) {
1615         sfp->ext = DialogToPointer (ffp->usrobjext);
1616       } else if (sfp->ext == NULL) {
1617         sfp->ext = old->ext;
1618         old->ext = NULL;
1619       }
1620       if (ffp->goTermUserObj != NULL) {
1621         sfp->ext = CombineGOTermUserObjects (sfp->ext, ffp->goTermUserObj);
1622       }
1623       if (ffp->featid != NULL) {
1624         TextToFeatID (ffp->featid, &(sfp->id));
1625       }
1626       /*
1627       if (sfp->cit == NULL) {
1628         sfp->cit = old->cit;
1629         old->cit = NULL;
1630       }
1631       */
1632       if (old->xref != NULL) {
1633         last = (SeqFeatXrefPtr PNTR) &(old->xref);
1634         curr = old->xref;
1635         while (curr != NULL) {
1636           next = curr->next;
1637           if (curr->data.choice == SEQFEAT_GENE) {
1638             *last = next;
1639             curr->next = NULL;
1640             SeqFeatXrefFree (curr);
1641           } else {
1642             last = &(curr->next);
1643           }
1644           curr = next;
1645         }
1646       }
1647       if (sfp->xref == NULL) {
1648         sfp->xref = old->xref;
1649       } else {
1650         curr = sfp->xref;
1651         while (curr->next != NULL) {
1652           curr = curr->next;
1653         }
1654         if (curr != NULL) {
1655           curr->next = old->xref;
1656         }
1657       }
1658       old->xref = NULL;
1659     }
1660   }
1661   return TRUE;
1662 }
1663 
GetOldFeatureLocation(GatherContextPtr gcp)1664 static Boolean GetOldFeatureLocation (GatherContextPtr gcp)
1665 {
1666   SeqLocPtr PNTR  old_loc;
1667   SeqFeatPtr      old_feat;
1668 
1669   if (gcp == NULL || gcp->userdata == NULL)
1670   {
1671     return FALSE;
1672   }
1673   old_loc = (SeqLocPtr PNTR) gcp->userdata;
1674   if (*old_loc != NULL)
1675   {
1676     return TRUE;
1677   }
1678   old_feat = gcp->thisitem;
1679   if (old_feat != NULL)
1680   {
1681     *old_loc = (SeqLocPtr) AsnIoMemCopy (old_feat->location,
1682                                          (AsnReadFunc) SeqLocAsnRead,
1683                                          (AsnWriteFunc) SeqLocAsnWrite);
1684   }
1685   return TRUE;
1686 }
1687 
HasExceptionGBQual(SeqFeatPtr sfp)1688 static Boolean HasExceptionGBQual (SeqFeatPtr sfp)
1689 
1690 {
1691   GBQualPtr  qual;
1692   Boolean    rsult;
1693 
1694   rsult = FALSE;
1695   if (sfp != NULL) {
1696     qual = sfp->qual;
1697     while (qual != NULL) {
1698       if (StringICmp (qual->qual, "exception") == 0) {
1699         if (! StringHasNoText (qual->val)) {
1700           rsult = TRUE;
1701         }
1702       }
1703       qual = qual->next;
1704     }
1705   }
1706   return rsult;
1707 }
1708 
AddProtRefXref(SeqFeatPtr sfp,TexT protXrefName,TexT protXrefDesc)1709 static void AddProtRefXref (SeqFeatPtr sfp, TexT protXrefName, TexT protXrefDesc)
1710 
1711 {
1712   Char            desc [256];
1713   Char            name [256];
1714   ProtRefPtr      prp;
1715   SeqFeatXrefPtr  xref;
1716 
1717   if (sfp == NULL) return;
1718   if (protXrefName == NULL && protXrefDesc == NULL) return;
1719   GetTitle (protXrefName, name, sizeof (name) - 1);
1720   GetTitle (protXrefDesc, desc, sizeof (desc) - 1);
1721   if (StringHasNoText (name) && StringHasNoText (desc)) return;
1722   for (xref = sfp->xref; xref != NULL; xref = xref->next) {
1723     if (xref->data.choice == SEQFEAT_PROT) break;
1724   }
1725   if (xref == NULL) {
1726     xref = SeqFeatXrefNew ();
1727     if (xref != NULL) {
1728       prp = ProtRefNew ();
1729       xref->data.choice = SEQFEAT_PROT;
1730       xref->data.value.ptrvalue = (Pointer) prp;
1731       xref->next = sfp->xref;
1732       sfp->xref = xref;
1733     }
1734   }
1735   if (xref != NULL && xref->data.choice == SEQFEAT_PROT) {
1736     prp = (ProtRefPtr) xref->data.value.ptrvalue;
1737     xref->data.value.ptrvalue = ProtRefFree (prp);
1738     prp = CreateNewProtRef (name, desc, NULL, NULL);
1739     xref->data.value.ptrvalue = (Pointer) prp;
1740   }
1741 }
1742 
1743 
1744 static CharPtr infDetails [] = {
1745   "unknown error",
1746   "empty inference string",
1747   "bad inference prefix",
1748   "bad inference body",
1749   "single inference field",
1750   "spaces in inference",
1751   "same species misused",
1752   "bad inference accession",
1753   "accession is missing version",
1754   "accession.version not public",
1755   NULL
1756 };
1757 
TestInference(FeatureFormPtr ffp,CharPtr badInfQual,size_t len,CharPtr badInfMssg)1758 extern Boolean TestInference (FeatureFormPtr ffp, CharPtr badInfQual, size_t len, CharPtr badInfMssg)
1759 
1760 {
1761   GBQualPtr   gbq;
1762   Int2        inferenceCode;
1763   Boolean     rsult = TRUE;
1764   CharPtr     str;
1765   SeqFeatPtr  tmp;
1766 
1767   if (ffp == NULL) return FALSE;
1768   tmp = SeqFeatNew ();
1769   if (tmp == NULL) return FALSE;
1770   if (badInfQual != NULL) {
1771     *badInfQual = '\0';
1772   }
1773   if (badInfMssg != NULL) {
1774     *badInfMssg = '\0';
1775   }
1776   InferenceDialogToGBQuals (ffp->inference, tmp, FALSE);
1777   for (gbq = tmp->qual; gbq != NULL; gbq = gbq->next) {
1778     str = gbq->val;
1779     if (StringICmp (gbq->qual, "inference") != 0) continue;
1780     inferenceCode = ValidateInferenceQualifier (str, FALSE);
1781     if (inferenceCode != VALID_INFERENCE) {
1782         if (inferenceCode < VALID_INFERENCE || inferenceCode > ACC_VERSION_NOT_PUBLIC) {
1783           inferenceCode = VALID_INFERENCE;
1784         }
1785         if (badInfQual != NULL) {
1786         StringNCpy_0 (badInfQual, str, len);
1787         }
1788         if (badInfMssg != NULL) {
1789         StringCpy (badInfMssg, infDetails [(int) inferenceCode]);
1790         }
1791       rsult = FALSE;
1792       break;
1793     }
1794   }
1795   SeqFeatFree (tmp);
1796   return rsult;
1797 }
1798 
1799 static CharPtr infWarning1 =
1800 "Bad inference qualifier!  You must conform to international nucleotide sequence database\nconventions for inference qualifiers!";
1801 
1802 static CharPtr infWarning2 =
1803 "Still has bad inference!  You must conform to international nucleotide sequence database\nconventions for inference qualifiers!";
1804 
1805 static CharPtr infAccept =
1806 "Do you want to accept changes with bad inference data?  The bad qualifier will be converted to a note!";
1807 
1808 const char * kTransSplicing = "trans-splicing";
1809 
FeatFormReplaceWithoutUpdateProc(ForM f)1810 extern Boolean FeatFormReplaceWithoutUpdateProc (ForM f)
1811 
1812 {
1813   Char            allele [128];
1814   MsgAnswer       ans;
1815   Int2            attempts = 3;
1816   Char            badInfMssg [32];
1817   Char            badInfQual [256];
1818   BioseqPtr       bsp;
1819   Char            desc [128];
1820   Int2            expev;
1821   SeqMgrFeatContext  fcontext;
1822   FeatureFormPtr  ffp;
1823   SeqFeatPtr      gene;
1824   GeneGatherList  ggl;
1825   GeneRefPtr      grp;
1826   GeneRefPtr      grpfeat;
1827   GatherScope     gs;
1828   SeqLocPtr       gslp;
1829   Boolean         hasNulls;
1830   Int2            i;
1831   Int4Ptr         intptr;
1832   Uint4           itemID;
1833   Char            locustag [128];
1834   Boolean         noLeft;
1835   Boolean         noRight;
1836   SeqEntryPtr     oldscope;
1837   OMProcControl   ompc;
1838   ReplaceData     rd;
1839   Boolean         rsult;
1840   SeqAnnotPtr     sap;
1841   SeqEntryPtr     sep;
1842   SeqFeatPtr      sfp = NULL;
1843   SeqFeatPtr      new_gene = NULL;
1844   SeqLocPtr       slp;
1845   CharPtr         str;
1846   Char            symbol [128];
1847   Int2            usexref;
1848   Int2            val;
1849   ValNodePtr      vnp, err_list;
1850   SeqFeatXrefPtr  xref;
1851   SeqLocPtr       old_location = NULL; /* we need the old location of the feature
1852                                         * if we're going to do a gene update
1853                                         */
1854   Boolean         fix_interval_order;
1855   Boolean         trans_spliced = FALSE;
1856 
1857   rsult = FALSE;
1858   if ((ffp = (FeatureFormPtr) GetObjectExtra (f)) == NULL) {
1859     return FALSE;
1860   }
1861   MemSet ((Pointer) &ompc, 0, sizeof (OMProcControl));
1862   ompc.input_entityID = ffp->input_entityID;
1863   ompc.input_itemID = ffp->input_itemID;
1864   ompc.input_itemtype = ffp->input_itemtype;
1865   ompc.output_itemtype = ffp->input_itemtype;
1866   sfp = SeqFeatNew ();
1867   if (sfp == NULL) {
1868     return FALSE;
1869   }
1870 
1871   sep = GetTopSeqEntryForEntityID (ffp->input_entityID);
1872   oldscope = SeqEntrySetScope (sep);
1873   sfp->data.choice = FindFeatFromFeatDefType (ffp->this_subtype);
1874   switch (sfp->data.choice) {
1875     case SEQFEAT_BOND :
1876     case SEQFEAT_SITE :
1877     case SEQFEAT_PSEC_STR :
1878       intptr = (Int4Ptr) DialogToPointer (ffp->data);
1879       if (intptr != NULL) {
1880         sfp->data.value.intvalue = *intptr;
1881       }
1882       break;
1883     case SEQFEAT_COMMENT:
1884       sfp->data.value.ptrvalue = NULL;
1885       break;
1886     default :
1887       sfp->data.value.ptrvalue = DialogToPointer (ffp->data);
1888       break;
1889   }
1890   sfp->comment = SaveStringFromText (ffp->comment);
1891   NewlinesToTildes (sfp->comment);
1892   expev = GetValue (ffp->evidence);
1893   if (expev > 0 && expev <= 3) {
1894     sfp->exp_ev = expev - 1;
1895   } else {
1896     sfp->exp_ev = 0;
1897   }
1898   sfp->partial = GetStatus (ffp->partial);
1899   sfp->excpt = GetStatus (ffp->exception);
1900   sfp->pseudo = GetStatus (ffp->pseudo);
1901   sfp->except_text = SaveStringFromText (ffp->exceptText);
1902   sfp->title = NULL;
1903   sfp->product = DialogToPointer (ffp->product);
1904   sfp->location = DialogToPointer (ffp->location);
1905   if (sfp->location == NULL) {
1906     SeqEntrySetScope (oldscope);
1907     ErrPostEx (SEV_ERROR, 0, 0, "Feature must have a location!");
1908     err_list = TestDialog (ffp->location);
1909     DisplayErrorMessages ("Location Errors", err_list);
1910     err_list = ValNodeFree (err_list);
1911     return FALSE;
1912   }
1913   if ((! ffp->acceptBadInf) && (! TestInference (ffp, badInfQual, sizeof (badInfQual), badInfMssg))) {
1914     (ffp->badInfAttempts)++;
1915     if (GetAppProperty ("InternalNcbiSequin") != NULL) {
1916       attempts = 2;
1917     }
1918     if (ffp->badInfAttempts < attempts) {
1919       if (ffp->badInfAttempts == 2) {
1920         Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning2, badInfMssg, badInfQual);
1921       } else {
1922         Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning1, badInfMssg, badInfQual);
1923       }
1924       return FALSE;
1925     } else {
1926       if (Message (MSG_YN, "%s", infAccept) == ANS_NO) return FALSE;
1927       ffp->acceptBadInf = TRUE;
1928     }
1929   }
1930 
1931   if (StringISearch (sfp->except_text, kTransSplicing) != NULL)
1932   {
1933     trans_spliced = TRUE;
1934   }
1935 
1936   bsp = GetBioseqGivenSeqLoc (sfp->location, ffp->input_entityID);
1937   if (bsp != NULL) {
1938     if (SeqLocBadSortOrder (bsp, sfp->location)) {
1939       fix_interval_order = FALSE;
1940       if (!trans_spliced)
1941       {
1942         ans = Message (MSG_YN, "Your feature intervals are out of order, but this coding region has a trans-splicing exception. Continue without correcting interval order?");
1943         if (ans == ANS_NO)
1944         {
1945           fix_interval_order = TRUE;
1946         }
1947       }
1948       else
1949       {
1950         ans = Message (MSG_YN,
1951         "Feature location intervals are out of order.  Do you want them repaired?");
1952         if (ans == ANS_YES)
1953         {
1954           fix_interval_order = TRUE;
1955         }
1956       }
1957       if (fix_interval_order) {
1958         hasNulls = LocationHasNullsBetween (sfp->location);
1959         gslp = SeqLocMerge (bsp, sfp->location, NULL, FALSE, FALSE, hasNulls);
1960         if (gslp != NULL) {
1961           CheckSeqLocForPartial (sfp->location, &noLeft, &noRight);
1962           sfp->location = SeqLocFree (sfp->location);
1963           sfp->location = gslp;
1964           if (bsp->repr == Seq_repr_seg) {
1965             gslp = SegLocToParts (bsp, sfp->location);
1966             sfp->location = SeqLocFree (sfp->location);
1967             sfp->location = gslp;
1968           }
1969           FreeAllFuzz (sfp->location);
1970           SetSeqLocPartial (sfp->location, noLeft, noRight);
1971         }
1972       }
1973     }
1974   }
1975   if (/* CheckSeqLocForPartial (sfp->location, NULL, NULL) */ SeqLocPartialCheck (sfp->location) != SLP_COMPLETE) {
1976     sfp->partial = TRUE;
1977   }
1978   sfp->cit = DialogToPointer (ffp->featcits);
1979   sfp->dbxref = DialogToPointer (ffp->dbxrefs);
1980   slp = AsnIoMemCopy (sfp->location, (AsnReadFunc) SeqLocAsnRead,
1981                       (AsnWriteFunc) SeqLocAsnWrite);
1982   usexref = GetValue (ffp->useGeneXref);
1983   if (ffp->gene != NULL) {
1984     val = GetValue (ffp->gene);
1985 /*
1986     if (StringISearch (sfp->except_text, "trans-splicing") != NULL) {
1987       val = 1;
1988       usexref = 0;
1989     }
1990 */
1991     if (usexref == 3 || (val > 1 && usexref == 2)) {
1992       grp = NULL;
1993       if (usexref == 3) {
1994         grp = GeneRefNew ();
1995       } else if (val == 2) {
1996         GetTitle (ffp->geneSymbol, symbol, sizeof (symbol));
1997         GetTitle (ffp->geneAllele, allele, sizeof (allele));
1998         GetTitle (ffp->geneDesc, desc, sizeof (desc));
1999         GetTitle (ffp->locusTag, locustag, sizeof (locustag));
2000         grp = CreateNewGeneRef (symbol, allele, desc, FALSE);
2001         if (! StringHasNoText (locustag)) {
2002           if (grp == NULL) {
2003             grp = GeneRefNew ();
2004           }
2005           grp->locus_tag = StringSave (locustag);
2006         }
2007         if (!TextHasNoText (ffp->geneSynonym)) {
2008           if (grp == NULL) {
2009             grp = GeneRefNew ();
2010           }
2011           ValNodeAddPointer (&(grp->syn), 0, SaveStringFromText (ffp->geneSynonym));
2012         }
2013       } else {
2014         vnp = ffp->geneNames;
2015         i = val - 3;
2016         while (i > 0 && vnp != NULL) {
2017           vnp = vnp->next;
2018           i--;
2019         }
2020         if (vnp != NULL) {
2021           if (vnp->choice == 1) {
2022             str = (CharPtr) vnp->data.ptrvalue;
2023             if (StringDoesHaveText (str)) {
2024               grp = CreateNewGeneRef (str, NULL, NULL, FALSE);
2025               gene = SeqMgrGetFeatureByLabel (bsp, str, SEQFEAT_GENE, 0, &fcontext);
2026               if (gene != NULL && gene->data.choice == SEQFEAT_GENE) {
2027                 grpfeat = (GeneRefPtr) gene->data.value.ptrvalue;
2028                 if (grpfeat != NULL) {
2029                   grp->locus_tag = StringSaveNoNull (grpfeat->locus_tag);
2030                 }
2031               }
2032             }
2033           } else if (vnp->choice == 2) {
2034              grp = GeneRefNew ();
2035             if (grp != NULL) {
2036               grp->desc = StringSave ((CharPtr) vnp->data.ptrvalue);
2037             }
2038          } else if (vnp->choice == 3) {
2039             grp = GeneRefNew ();
2040             if (grp != NULL) {
2041               grp->locus_tag = StringSave ((CharPtr) vnp->data.ptrvalue);
2042             }
2043           }
2044         }
2045       }
2046       if (grp != NULL) {
2047         xref = SeqFeatXrefNew ();
2048         sfp->xref = xref;
2049         if (xref != NULL) {
2050           xref->data.choice = SEQFEAT_GENE;
2051           xref->data.value.ptrvalue = (Pointer) grp;
2052         }
2053       }
2054     }
2055   } else if (usexref == 3) {
2056     /* protein feature can now suppress gene on GenBank view */
2057     grp = GeneRefNew ();
2058     if (grp != NULL) {
2059       xref = SeqFeatXrefNew ();
2060       sfp->xref = xref;
2061       if (xref != NULL) {
2062         xref->data.choice = SEQFEAT_GENE;
2063         xref->data.value.ptrvalue = (Pointer) grp;
2064       }
2065     }
2066   }
2067 
2068   ompc.output_data = (Pointer) sfp;
2069   if (ompc.input_entityID == 0) {
2070     sfp->qual = DialogToPointer (ffp->gbquals);
2071     PseudogenePopupToGbquals (sfp, ffp, ffp->pseudogene);
2072     VisStringDialogToGbquals (sfp, ffp->experiment, "experiment");
2073     InferenceDialogToGBQuals (ffp->inference, sfp, TRUE);
2074 
2075     sfp->ext = DialogToPointer (ffp->usrobjext);
2076     if (ffp->goTermUserObj != NULL) {
2077       sfp->ext = CombineGOTermUserObjects (sfp->ext, ffp->goTermUserObj);
2078     }
2079     if (ffp->featid != NULL) {
2080       TextToFeatID (ffp->featid, &(sfp->id));
2081     }
2082     if (HasExceptionGBQual (sfp)) {
2083       sfp->excpt = TRUE;
2084     }
2085     if (ffp->fidxref != NULL) {
2086       TextToFeatXref (ffp->fidxref, sfp);
2087     }
2088     AddProtRefXref (sfp, ffp->protXrefName, ffp->protXrefDesc);
2089     FixSpecialCharactersForObject (OBJ_SEQFEAT, sfp, "You may not include special characters in the text.\nIf you do not choose replacement characters, these special characters will be replaced with '#'.", TRUE, NULL);
2090     if (! ObjMgrRegister (OBJ_SEQFEAT, (Pointer) sfp)) {
2091       Message (MSG_ERROR, "ObjMgrRegister failed");
2092     }
2093     SeqLocFree (slp);
2094     SeqEntrySetScope (oldscope);
2095     return TRUE;
2096   } else if (ompc.input_itemtype != OBJ_SEQFEAT) {
2097     sfp->qual = DialogToPointer (ffp->gbquals);
2098     PseudogenePopupToGbquals (sfp, ffp, ffp->pseudogene);
2099     VisStringDialogToGbquals (sfp, ffp->experiment, "experiment");
2100     InferenceDialogToGBQuals (ffp->inference, sfp, TRUE);
2101 
2102     sfp->ext = DialogToPointer (ffp->usrobjext);
2103     if (ffp->goTermUserObj != NULL) {
2104       sfp->ext = CombineGOTermUserObjects (sfp->ext, ffp->goTermUserObj);
2105     }
2106     if (ffp->featid != NULL) {
2107       TextToFeatID (ffp->featid, &(sfp->id));
2108     }
2109     if (HasExceptionGBQual (sfp)) {
2110       sfp->excpt = TRUE;
2111     }
2112     if (ffp->fidxref != NULL) {
2113       TextToFeatXref (ffp->fidxref, sfp);
2114     }
2115     AddProtRefXref (sfp, ffp->protXrefName, ffp->protXrefDesc);
2116     FixSpecialCharactersForObject (OBJ_SEQFEAT, sfp, "You may not include special characters in the text.\nIf you do not choose replacement characters, these special characters will be replaced with '#'.", TRUE, NULL);
2117 
2118     /* adjust mRNA location and product name here */
2119     if (sfp != NULL && sfp->data.choice == SEQFEAT_CDREGION) {
2120       UpdatemRNAAfterEditing (ffp->data, sfp->location, sfp->location);
2121     }
2122 
2123     ompc.output_itemtype = OBJ_SEQFEAT;
2124     if (ompc.input_itemtype == OBJ_BIOSEQ) {
2125       bsp = GetBioseqGivenIDs (ompc.input_entityID, ompc.input_itemID, ompc.input_itemtype);
2126       if (bsp != NULL) {
2127         sap = bsp->annot;
2128         while (sap != NULL && (sap->name != NULL || sap->desc != NULL || sap->type != 1)) {
2129           sap = sap->next;
2130         }
2131         if (sap == NULL) {
2132           sap = SeqAnnotNew ();
2133           if (sap != NULL) {
2134             sap->type = 1;
2135             sap->next = bsp->annot;
2136             bsp->annot = sap;
2137           }
2138         }
2139         if (sap != NULL) {
2140           itemID = GetItemIDGivenPointer (ompc.input_entityID, OBJ_SEQANNOT, (Pointer) sap);
2141           if (itemID > 0) {
2142             ompc.input_itemID = itemID;
2143             ompc.input_itemtype = OBJ_SEQANNOT;
2144           }
2145         }
2146       }
2147     }
2148     if (! AttachDataForProc (&ompc, FALSE)) {
2149       Message (MSG_ERROR, "AttachDataForProc failed");
2150     }
2151     rsult = TRUE;
2152   } else {
2153     GatherItem (ompc.input_entityID, ompc.input_itemID, ompc.input_itemtype,
2154                 (Pointer) &old_location, GetOldFeatureLocation);
2155 
2156     /* adjust mRNA location and product name here, using old location */
2157     if (sfp != NULL && sfp->data.choice == SEQFEAT_CDREGION) {
2158       UpdatemRNAAfterEditing (ffp->data, old_location == NULL ? sfp->location : old_location, sfp->location);
2159     }
2160 
2161     rd.ffp = ffp;
2162     rd.sfp = sfp;
2163     GatherItem (ompc.input_entityID, ompc.input_itemID, ompc.input_itemtype,
2164                 (Pointer) &rd, ReplaceFeatureExtras);
2165     if (HasExceptionGBQual (sfp)) {
2166       sfp->excpt = TRUE;
2167     }
2168     if (ffp->fidxref != NULL) {
2169       TextToFeatXref (ffp->fidxref, sfp);
2170     }
2171     AddProtRefXref (sfp, ffp->protXrefName, ffp->protXrefDesc);
2172 
2173     FixSpecialCharactersForObject (OBJ_SEQFEAT, sfp, "You may not include special characters in the text.\nIf you do not choose replacement characters, these special characters will be replaced with '#'.", TRUE, NULL);
2174     if (! ReplaceDataForProc (&ompc, FALSE)) {
2175       Message (MSG_ERROR, "ReplaceDataForProc failed");
2176     }
2177     rsult = TRUE;
2178   }
2179   if (ffp->gene != NULL && usexref == 1) {
2180     val = GetValue (ffp->gene);
2181     if (val == 2) {
2182       sep = GetBestTopParentForItemID (ffp->input_entityID,
2183                                        ffp->input_itemID,
2184                                        ffp->input_itemtype);
2185       /*
2186       sep = GetTopSeqEntryForEntityID (ffp->input_entityID);
2187       */
2188       if (sep != NULL) {
2189         sep = FindNucSeqEntry (sep);
2190       }
2191       if (sep != NULL && sep->data.ptrvalue != NULL) {
2192         GetTitle (ffp->geneSymbol, symbol, sizeof (symbol));
2193         GetTitle (ffp->geneAllele, allele, sizeof (allele));
2194         GetTitle (ffp->geneDesc, desc, sizeof (desc));
2195         GetTitle (ffp->locusTag, locustag, sizeof (locustag));
2196         grp = CreateNewGeneRef (symbol, allele, desc, FALSE);
2197         if (! StringHasNoText (locustag)) {
2198           if (grp == NULL) {
2199             grp = GeneRefNew ();
2200           }
2201           grp->locus_tag = StringSave (locustag);
2202         }
2203         if (!TextHasNoText (ffp->geneSynonym)) {
2204           if (grp == NULL) {
2205             grp = GeneRefNew ();
2206           }
2207           ValNodeAddPointer (&(grp->syn), 0, SaveStringFromText (ffp->geneSynonym));
2208         }
2209         if (grp != NULL) {
2210           new_gene = CreateNewFeature (sep, NULL, SEQFEAT_GENE, NULL);
2211           if (new_gene != NULL) {
2212             new_gene->data.value.ptrvalue = (Pointer) grp;
2213             FixSpecialCharactersForObject (OBJ_SEQFEAT, new_gene, "You may not include special characters in the text.\nIf you do not choose replacement characters, these special characters will be replaced with '#'.", TRUE, NULL);
2214             new_gene->location = SeqLocFree (new_gene->location);
2215             new_gene->location = DialogToPointer (ffp->location);
2216             gslp = MakeGeneLocForFeatureLoc (new_gene->location, ffp->input_entityID, trans_spliced);
2217             new_gene->location = SeqLocFree (new_gene->location);
2218             new_gene->location = gslp;
2219             hasNulls = LocationHasNullsBetween (new_gene->location);
2220             CheckSeqLocForPartial (new_gene->location, &noLeft, &noRight);
2221             new_gene->partial = (hasNulls || noLeft || noRight);
2222 
2223             /* copy trans-splicing exception if present */
2224             if (trans_spliced) {
2225                 new_gene->excpt = TRUE;
2226                 new_gene->except_text = StringSave(kTransSplicing);
2227             }
2228 
2229           }
2230         }
2231       }
2232     } else if (val > 2 && !trans_spliced) {
2233       /* do not update gene location if trans-spliced */
2234       ggl.ffp = ffp;
2235       ggl.omp = ObjMgrGet ();
2236       ggl.slp = slp;
2237       ggl.genexref = NULL;
2238       ggl.xrefmatch = FALSE;
2239       ggl.idx = 2;
2240       ggl.val = val;
2241       ggl.min = INT4_MAX;
2242       ggl.old_feature_location = old_location;
2243       MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
2244       gs.seglevels = 1;
2245       gs.get_feats_location = TRUE;
2246         MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
2247         gs.ignore[OBJ_BIOSEQ] = FALSE;
2248         gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
2249         gs.ignore[OBJ_SEQFEAT] = FALSE;
2250         gs.ignore[OBJ_SEQANNOT] = FALSE;
2251       gs.scope = GetBestTopParentForItemID (ffp->input_entityID,
2252                                             ffp->input_itemID,
2253                                             ffp->input_itemtype);
2254       GatherEntity (ffp->input_entityID, (Pointer) &ggl, GeneUpdateFunc, &gs);
2255     }
2256   }
2257   SeqLocFree (slp);
2258   SeqEntrySetScope (oldscope);
2259 
2260   old_location = SeqLocFree (old_location);
2261   return rsult;
2262 }
2263 
StdFeatFormActnProc(ForM f)2264 extern void StdFeatFormActnProc (ForM f)
2265 
2266 {
2267   FeatureFormPtr  ffp;
2268 
2269   if (FeatFormReplaceWithoutUpdateProc (f)) {
2270     ffp = (FeatureFormPtr) GetObjectExtra (f);
2271     if (ffp != NULL) {
2272       GetRidOfEmptyFeatsDescStrings (ffp->input_entityID, NULL);
2273       if (GetAppProperty ("InternalNcbiSequin") != NULL) {
2274         ExtendGeneFeatIfOnMRNA (ffp->input_entityID, NULL);
2275       }
2276       ObjMgrSetDirtyFlag (ffp->input_entityID, TRUE);
2277       ObjMgrSendMsg (OM_MSG_UPDATE, ffp->input_entityID,
2278                      ffp->input_itemID, ffp->input_itemtype);
2279     }
2280   }
2281 }
2282 
StdSeqFeatPtrToFeatFormProc(ForM f,Pointer data)2283 extern void StdSeqFeatPtrToFeatFormProc (ForM f, Pointer data)
2284 
2285 {
2286   FeatureFormPtr  ffp;
2287   SeqEntryPtr     oldsep;
2288   SeqEntryPtr     sep;
2289   SeqFeatPtr      sfp;
2290   Int4            val;
2291 
2292   ffp = (FeatureFormPtr) GetObjectExtra (f);
2293   if (ffp != NULL) {
2294     sep = GetTopSeqEntryForEntityID (ffp->input_entityID);
2295     oldsep = SeqEntrySetScope (sep);
2296     sfp = (SeqFeatPtr) data;
2297     if (sfp != NULL) {
2298       switch (sfp->data.choice) {
2299         case SEQFEAT_BOND :
2300         case SEQFEAT_SITE :
2301         case SEQFEAT_PSEC_STR :
2302           val = (Int4) sfp->data.value.intvalue;
2303           PointerToDialog (ffp->data, (Pointer) &(val));
2304           break;
2305         case SEQFEAT_COMMENT:
2306           break;
2307         default :
2308           PointerToDialog (ffp->data, sfp->data.value.ptrvalue);
2309           break;
2310       }
2311       SeqFeatPtrToCommon (ffp, sfp);
2312       PointerToDialog (ffp->location, sfp->location);
2313     }
2314     SeqEntrySetScope (oldsep);
2315   }
2316 }
2317 
StdInitFeatFormProc(ForM f)2318 extern void StdInitFeatFormProc (ForM f)
2319 
2320 {
2321   FeatureFormPtr  ffp;
2322 
2323   ffp = (FeatureFormPtr) GetObjectExtra (f);
2324   if (ffp != NULL) {
2325     PopulateGenePopup (ffp);
2326   }
2327 }
2328 
StdFeatFormAcceptButtonProc(ButtoN b)2329 extern void StdFeatFormAcceptButtonProc (ButtoN b)
2330 
2331 {
2332   Int2            attempts = 3;
2333   Char            badInfMssg [32];
2334   Char            badInfQual [256];
2335   FeatureFormPtr  ffp;
2336   SeqLocPtr       slp;
2337   WindoW          w;
2338   ValNodePtr      err_list;
2339   SeqEntryPtr     oldscope, sep;
2340 
2341   if (b != NULL) {
2342     w = ParentWindow (b);
2343     ffp = (FeatureFormPtr) GetObjectExtra (b);
2344     if (ffp != NULL && ffp->form != NULL && ffp->actproc != NULL) {
2345       sep = GetTopSeqEntryForEntityID (ffp->input_entityID);
2346       oldscope = SeqEntrySetScope (sep);
2347       slp = DialogToPointer (ffp->location);
2348       if (slp == NULL) {
2349         ErrPostEx (SEV_ERROR, 0, 0, "Feature must have a location!");
2350         err_list = TestDialog (ffp->location);
2351         DisplayErrorMessages ("Location Errors", err_list);
2352         err_list = ValNodeFree (err_list);
2353         SeqEntrySetScope (oldscope);
2354         return;
2355       }
2356       SeqLocFree (slp);
2357       if ((! ffp->acceptBadInf) && (! TestInference (ffp, badInfQual, sizeof (badInfQual), badInfMssg))) {
2358         (ffp->badInfAttempts)++;
2359         if (GetAppProperty ("InternalNcbiSequin") != NULL) {
2360           attempts = 2;
2361         }
2362         if (ffp->badInfAttempts < attempts) {
2363           if (ffp->badInfAttempts == 2) {
2364             Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning2, badInfMssg, badInfQual);
2365           } else {
2366             Message (MSG_OK, "%s - Please fix the %s error in\n%s", infWarning1, badInfMssg, badInfQual);
2367           }
2368           return;
2369         } else {
2370           if (Message (MSG_YN, "%s", infAccept) == ANS_NO) return;
2371           ffp->acceptBadInf = TRUE;
2372         }
2373       }
2374       Hide (w);
2375       (ffp->actproc) (ffp->form);
2376       SeqEntrySetScope (oldscope);
2377     }
2378     Update ();
2379     if (ffp != NULL && (ffp->leave_dlg_up == NULL || ! GetStatus (ffp->leave_dlg_up)))
2380     {
2381       Remove (w);
2382     }
2383     else if (ffp != NULL)
2384     {
2385       /* set strand and sequence ID, but clear other location information */
2386       SendMessageToDialog (ffp->location, NUM_VIB_MSG + 1);
2387       SendMessageToDialog (ffp->location, NUM_VIB_MSG + 2);
2388       Show (w);
2389     }
2390   }
2391 }
2392 
StdFeatFormCleanupProc(GraphiC g,VoidPtr data)2393 extern void StdFeatFormCleanupProc (GraphiC g, VoidPtr data)
2394 
2395 {
2396   FeatureFormPtr  ffp;
2397   Uint2           userkey;
2398 
2399   ffp = (FeatureFormPtr) data;
2400   if (ffp != NULL) {
2401     ValNodeFreeData (ffp->geneNames);
2402     if (ffp->input_entityID > 0 && ffp->userkey > 0) {
2403       userkey = ffp->userkey;
2404       ffp->userkey = 0;
2405       ObjMgrFreeUserData (ffp->input_entityID, ffp->procid, ffp->proctype, userkey);
2406     }
2407   }
2408   StdCleanupFormProc (g, data);
2409 }
2410 
AddStringToValNodeChain(ValNodePtr head,CharPtr str,Uint1 choice)2411 extern ValNodePtr AddStringToValNodeChain (ValNodePtr head, CharPtr str, Uint1 choice)
2412 
2413 {
2414   ValNodePtr  vnp;
2415 
2416   vnp = ValNodeNew (head);
2417   if (head == NULL) {
2418     head = vnp;
2419   }
2420   if (vnp != NULL) {
2421     vnp->choice = choice;
2422     vnp->data.ptrvalue = StringSave (str);
2423   }
2424   return head;
2425 }
2426 
StripPeriods(CharPtr str)2427 static void StripPeriods (CharPtr str)
2428 
2429 {
2430   Char     ch;
2431   CharPtr  dst;
2432 
2433   if (str != NULL) {
2434     dst = str;
2435     ch = *str;
2436     while (ch != '\0') {
2437       if (ch != '.') {
2438         *dst = ch;
2439         dst++;
2440       }
2441       str++;
2442       ch = *str;
2443     }
2444     *dst = '\0';
2445   }
2446 }
2447 
TrimLeadingSpaces(CharPtr str)2448 static void TrimLeadingSpaces (CharPtr str)
2449 
2450 {
2451   Char     ch;
2452   CharPtr  dst;
2453 
2454   if (str != NULL && str [0] != '\0') {
2455     dst = str;
2456     ch = *str;
2457     while (ch != '\0' && ch <= ' ') {
2458       str++;
2459       ch = *str;
2460     }
2461     while (ch != '\0') {
2462       *dst = ch;
2463       dst++;
2464       str++;
2465       ch = *str;
2466     }
2467     *dst = '\0';
2468   }
2469 }
2470 
2471 extern CharPtr NameStdPtrToAuthorSpreadsheetString (NameStdPtr nsp);
NameStdPtrToAuthorSpreadsheetString(NameStdPtr nsp)2472 extern CharPtr NameStdPtrToAuthorSpreadsheetString (NameStdPtr nsp)
2473 
2474 {
2475   Char   first [256];
2476   Char   frstinits [64];
2477   Char   initials [64];
2478   Int2   j;
2479   Char   last [256];
2480   Char   middle [128];
2481   Char   str [512];
2482   Char   suffix [64];
2483   Char   suffixPosition[64];
2484   Int2   i;
2485 
2486   if (nsp == NULL) return NULL;
2487   str [0] = '\0';
2488   StringNCpy_0 (first, nsp->names [1], sizeof (first));
2489   TrimSpacesAroundString (first);
2490   StringNCpy_0 (initials, nsp->names [4], sizeof (initials));
2491   StripPeriods (initials);
2492   TrimLeadingSpaces (initials);
2493   StringNCpy_0 (last, nsp->names [0], sizeof (last));
2494   TrimLeadingSpaces (last);
2495   StringNCpy_0 (middle, nsp->names [2], sizeof (middle));
2496   TrimLeadingSpaces (middle);
2497   if (StringCmp (initials, "al") == 0 &&
2498       StringCmp (last, "et") == 0 &&
2499       first [0] == '\0') {
2500     initials [0] = '\0';
2501     StringCpy (last, "et al.");
2502   }
2503   if (first [0] == '\0') {
2504     StringNCpy_0 (first, initials, sizeof (first));
2505     if (IS_ALPHA (first [0])) {
2506       if (first [1] == '-') {
2507         first [3] = '\0';
2508       } else {
2509         first [1] = '\0';
2510       }
2511     } else {
2512       first [0] = '\0';
2513     }
2514   }
2515   FirstNameToInitials (first, frstinits, sizeof (frstinits) - 1);
2516   StripPeriods (first);
2517   TrimLeadingSpaces (first);
2518   if (first [0] != '\0') {
2519     StringCat (str, first);
2520   } else {
2521   }
2522   StringCat (str, "\t");
2523   j = 0;
2524   while (initials [j] != '\0' && TO_UPPER (initials [j]) == TO_UPPER (frstinits [j])) {
2525     j++;
2526   }
2527   if (initials [j] != '\0') {
2528     StringCat (str, initials + j);
2529   } else {
2530   }
2531   StringCat (str, "\t");
2532   StringCat (str, last);
2533   StringNCpy_0 (suffix, nsp->names [5], sizeof (suffix));
2534   for (i = 0; i <= NUMBER_OF_SUFFIXES; i++)
2535     if (StringICmp (suffix, name_suffix_labels [i]) == 0) {
2536       sprintf (suffixPosition, "%d", i);
2537       break;
2538     }
2539   if (i == NUMBER_OF_SUFFIXES)
2540     sprintf (suffixPosition, "%d", 0);
2541   StringCat (str, "\t");
2542   if (suffix [0] != '\0') {
2543     StringCat (str, suffixPosition);
2544   } else {
2545   }
2546   StringCat (str, "\t");
2547   StringCat (str, middle);
2548   StringCat (str, "\n");
2549   return StringSave (str);
2550 }
2551 
StdAuthListPtrToAuthorDialog(DialoG d,Pointer data)2552 static void StdAuthListPtrToAuthorDialog (DialoG d, Pointer data)
2553 
2554 {
2555   AuthListPtr  alp;
2556   AuthorPtr    ap;
2557   ValNodePtr   head;
2558   Int2         j;
2559   ValNodePtr   names;
2560   NameStdPtr   nsp;
2561   PersonIdPtr  pid;
2562   TagListPtr   tlp;
2563   ValNodePtr   vnp;
2564 
2565   tlp = (TagListPtr) GetObjectExtra (d);
2566   alp = (AuthListPtr) data;
2567   if (tlp != NULL) {
2568     head = NULL;
2569     if (alp != NULL) {
2570       if (alp->choice == 1) {
2571         names = alp->names;
2572         while (names != NULL) {
2573           ap = names->data.ptrvalue;
2574           if (ap != NULL) {
2575             pid = ap->name;
2576             if (pid != NULL) {
2577               if (pid->choice == 2) {
2578                 nsp = pid->data;
2579                 if (nsp != NULL) {
2580                   vnp = ValNodeNew (head);
2581                   if (head == NULL) {
2582                     head = vnp;
2583                   }
2584                   if (vnp != NULL) {
2585                     vnp->data.ptrvalue = NameStdPtrToAuthorSpreadsheetString (nsp);
2586                   }
2587                 }
2588               }
2589             }
2590           }
2591           names = names->next;
2592         }
2593       } else {
2594         Message (MSG_ERROR, "Unable to handle author type %d", (int) alp->choice);
2595       }
2596     }
2597     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
2598     tlp->vnp = head;
2599     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
2600     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
2601     }
2602     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
2603     CorrectBarMax (tlp->bar, tlp->max);
2604     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
2605   }
2606 }
2607 
2608 extern NameStdPtr AuthorSpreadsheetStringToNameStdPtr (CharPtr txt);
AuthorSpreadsheetStringToNameStdPtr(CharPtr txt)2609 extern NameStdPtr AuthorSpreadsheetStringToNameStdPtr (CharPtr txt)
2610 
2611 {
2612   Char        ch;
2613   CharPtr     first;
2614   Char        initials [64];
2615   Int2        j;
2616   Int2        k;
2617   Char        last;
2618   NameStdPtr  nsp;
2619   Char        periods [128];
2620   CharPtr     str;
2621   Char        str1 [64];
2622   CharPtr     suffix;
2623   Char        suffixVal [80];
2624 
2625   if (txt == NULL) return NULL;
2626   nsp = NameStdNew ();
2627   if (nsp == NULL) return NULL;
2628   nsp->names [0] = ExtractTagListColumn (txt, 2);
2629   TrimLeadingSpaces (nsp->names [0]);
2630   first = ExtractTagListColumn (txt, 0);
2631   StripPeriods (first);
2632   nsp->names [1] = StringSave (first);
2633   TrimLeadingSpaces (nsp->names [1]);
2634   FirstNameToInitials (first, str1, sizeof (str1) - 1);
2635   str = ExtractTagListColumn (txt, 1);
2636   StringNCat (str1, str, sizeof (str1) - 1);
2637   MemFree (str);
2638   j = 0;
2639   k = 0;
2640   ch = str1 [j];
2641   while (ch != '\0') {
2642     if (ch != ' ') {
2643       initials [k] = ch;
2644       k++;
2645     }
2646     j++;
2647     ch = str1 [j];
2648   }
2649   initials [k] = '\0';
2650   periods [0] = '\0';
2651           j = 0;
2652           ch = initials [j];
2653           while (ch != '\0') {
2654             if (ch == ',') {
2655               initials [j] = '.';
2656             }
2657             j++;
2658             ch = initials [j];
2659           }
2660           str = StringStr (initials, ".ST.");
2661           if (str != NULL) {
2662             *(str + 2) = 't';
2663           }
2664   j = 0;
2665   k = 0;
2666   ch = initials [j];
2667   while (ch != '\0') {
2668     if (ch == '-') {
2669       periods [k] = ch;
2670       k++;
2671       j++;
2672       ch = initials [j];
2673     } else if (ch == '.') {
2674       j++;
2675       ch = initials [j];
2676             } else if (ch == ' ') {
2677               j++;
2678               ch = initials [j];
2679     } else {
2680       periods [k] = ch;
2681               last = ch;
2682       k++;
2683       j++;
2684       ch = initials [j];
2685               if (ch == '\0') {
2686                 if (! (IS_LOWER (last))) {
2687                   periods [k] = '.';
2688                   k++;
2689                 }
2690               /* } else if (ch == '.' && initials [j + 1] == '\0') { */
2691               } else if (! (IS_LOWER (ch))) {
2692                 periods [k] = '.';
2693                 k++;
2694               }
2695     }
2696   }
2697   periods [k] = '\0';
2698   nsp->names [4] = StringSave (periods);
2699   TrimLeadingSpaces (nsp->names [4]);
2700   str = ExtractTagListColumn (txt, 3);
2701   StringNCpy_0 (str1, str, sizeof (str1));
2702   MemFree (str);
2703   j = 0;
2704   k = 0;
2705   ch = str1 [j];
2706   while (ch != '\0') {
2707     if (ch != ' ') {
2708       suffixVal [k] = ch;
2709       k++;
2710     }
2711     j++;
2712     ch = str1 [j];
2713   }
2714   suffixVal [k] = '\0';
2715   if (suffixVal [0] != '\0') {
2716     suffix = GetEnumName (atoi(suffixVal), name_suffix_alist);
2717     nsp->names [5] = StringSave (suffix);
2718     TrimLeadingSpaces (nsp->names [5]);
2719     if (StringHasNoText (nsp->names [5])) {
2720       nsp->names [5] = MemFree (nsp->names [5]);
2721     }
2722   }
2723   if (StringCmp (nsp->names [0], "et al") == 0) {
2724     nsp->names [0] = MemFree (nsp->names [0]);
2725     nsp->names [0] = StringSave ("et al.");
2726   }
2727   nsp->names [2] = ExtractTagListColumn (txt, 4);
2728   TrimLeadingSpaces (nsp->names [2]);
2729   if (StringHasNoText (nsp->names [2])) {
2730     nsp->names [2] = MemFree (nsp->names [2]);
2731   }
2732   return nsp;
2733 }
2734 
AuthorDialogToStdAuthListPtr(DialoG d)2735 static Pointer AuthorDialogToStdAuthListPtr (DialoG d)
2736 
2737 {
2738   AuthListPtr  alp;
2739   AuthorPtr    ap;
2740   Char         ch;
2741   Int2         j;
2742   Int2         len;
2743   ValNodePtr   names;
2744   NameStdPtr   nsp;
2745   Boolean      okay;
2746   PersonIdPtr  pid;
2747   CharPtr      str;
2748   TagListPtr   tlp;
2749   ValNodePtr   vnp;
2750 
2751   alp = NULL;
2752   tlp = (TagListPtr) GetObjectExtra (d);
2753   if (tlp != NULL && tlp->vnp != NULL) {
2754     alp = AuthListNew ();
2755     if (alp != NULL) {
2756       alp->choice = 1;
2757       names = NULL;
2758       for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
2759         str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 2);
2760         okay = FALSE;
2761         len = StringLen (str);
2762         for (j = 0; j < len; j++) {
2763           ch = str [j];
2764           if (ch != ' ' && ch != '\t' && ch != '\n') {
2765             okay = TRUE;
2766           }
2767         }
2768         MemFree (str);
2769         if (okay) {
2770           names = ValNodeNew (names);
2771           if (alp->names == NULL) {
2772             alp->names = names;
2773           }
2774           if (names != NULL) {
2775             ap = AuthorNew ();
2776             names->choice = 1;
2777             names->data.ptrvalue = ap;
2778             if (ap != NULL) {
2779               pid = PersonIdNew ();
2780               ap->name = pid;
2781               if (pid != NULL) {
2782                 pid->choice = 2;
2783                 nsp = AuthorSpreadsheetStringToNameStdPtr ((CharPtr) vnp->data.ptrvalue);
2784                 pid->data = nsp;
2785               }
2786             }
2787           }
2788         }
2789       }
2790       if (alp->names == NULL) {
2791         alp = AuthListFree (alp);
2792       }
2793     }
2794   }
2795   return (Pointer) alp;
2796 }
2797 
StrAuthListPtrToAuthorDialog(DialoG d,Pointer data)2798 static void StrAuthListPtrToAuthorDialog (DialoG d, Pointer data)
2799 
2800 {
2801   AuthListPtr  alp;
2802   ValNodePtr   head;
2803   Int2         j;
2804   ValNodePtr   names;
2805   Char         str [128];
2806   TagListPtr   tlp;
2807   ValNodePtr   vnp;
2808 
2809   tlp = (TagListPtr) GetObjectExtra (d);
2810   alp = (AuthListPtr) data;
2811   if (tlp != NULL) {
2812     head = NULL;
2813     if (alp != NULL) {
2814       if (alp->choice == 2 || alp->choice == 3) {
2815         names = alp->names;
2816         while (names != NULL) {
2817           StringNCpy_0 (str, names->data.ptrvalue, sizeof (str) - 2);
2818           StringCat (str, "\n");
2819           vnp = ValNodeNew (head);
2820           if (head == NULL) {
2821             head = vnp;
2822           }
2823           if (vnp != NULL) {
2824             vnp->data.ptrvalue = StringSave (str);
2825           }
2826           names = names->next;
2827         }
2828       } else {
2829         Message (MSG_ERROR, "Unable to handle author type %d", (int) alp->choice);
2830       }
2831     }
2832     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
2833     tlp->vnp = head;
2834     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
2835     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
2836     }
2837     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
2838     CorrectBarMax (tlp->bar, tlp->max);
2839     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
2840   }
2841 }
2842 
AuthorDialogToStrAuthListPtr(DialoG d)2843 static Pointer AuthorDialogToStrAuthListPtr (DialoG d)
2844 
2845 {
2846   AuthListPtr  alp;
2847   Char         ch;
2848   Int2         j;
2849   Int2         len;
2850   ValNodePtr   names;
2851   Boolean      okay;
2852   CharPtr      str;
2853   TagListPtr   tlp;
2854   ValNodePtr   vnp;
2855 
2856   alp = NULL;
2857   tlp = (TagListPtr) GetObjectExtra (d);
2858   if (tlp != NULL && tlp->vnp != NULL) {
2859     alp = AuthListNew ();
2860     if (alp != NULL) {
2861       alp->choice = 2;
2862       names = NULL;
2863       for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
2864         str = (CharPtr) vnp->data.ptrvalue;
2865         okay = FALSE;
2866         len = StringLen (str);
2867         for (j = 0; j < len; j++) {
2868           ch = str [j];
2869           if (ch != ' ' && ch != '\t' && ch != '\n') {
2870             okay = TRUE;
2871           }
2872         }
2873         if (okay) {
2874           names = ValNodeNew (names);
2875           if (alp->names == NULL) {
2876             alp->names = names;
2877           }
2878           if (names != NULL) {
2879             names->choice = 2;
2880             names->data.ptrvalue = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
2881 
2882           }
2883         }
2884       }
2885       if (alp->names == NULL) {
2886         alp = AuthListFree (alp);
2887       }
2888     }
2889   }
2890   return (Pointer) alp;
2891 }
2892 
AuthListPtrToAuthorDialog(DialoG d,Pointer data)2893 static void AuthListPtrToAuthorDialog (DialoG d, Pointer data)
2894 
2895 {
2896   AuthorDialogPtr  adp;
2897   AuthListPtr      alp;
2898 
2899   adp = (AuthorDialogPtr) GetObjectExtra (d);
2900   if (adp != NULL) {
2901     alp = (AuthListPtr) data;
2902     if (alp != NULL) {
2903       adp->type = alp->choice;
2904     }
2905     if (adp->type == 1) {
2906       Hide (adp->strGrp);
2907       Show (adp->stdGrp);
2908       PointerToDialog (adp->stdAuthor, data);
2909     } else if (adp->type == 2 || adp->type == 3) {
2910       Hide (adp->stdGrp);
2911       Show (adp->strGrp);
2912       PointerToDialog (adp->strAuthor, data);
2913     }
2914   }
2915 }
2916 
AuthorDialogToAuthListPtr(DialoG d)2917 static Pointer AuthorDialogToAuthListPtr (DialoG d)
2918 
2919 {
2920   AuthorDialogPtr  adp;
2921   AuthListPtr      alp;
2922 
2923   adp = (AuthorDialogPtr) GetObjectExtra (d);
2924   alp = NULL;
2925   if (adp != NULL) {
2926     if (adp->type == 1) {
2927       alp = (AuthListPtr) DialogToPointer (adp->stdAuthor);
2928     } else if (adp->type == 2 || adp->type == 3) {
2929       if ((alp = (AuthListPtr) DialogToPointer (adp->strAuthor)) != NULL)
2930         alp->choice = adp->type;
2931     }
2932   }
2933   return (Pointer) alp;
2934 }
2935 
AuthorDialogMessage(DialoG d,Int2 mssg)2936 static void AuthorDialogMessage (DialoG d, Int2 mssg)
2937 
2938 {
2939   AuthorDialogPtr  adp;
2940 
2941   adp = (AuthorDialogPtr) GetObjectExtra (d);
2942   if (adp != NULL) {
2943     switch (mssg) {
2944       case VIB_MSG_ENTER :
2945         if (adp->type == 1) {
2946           SendMessageToDialog (adp->stdAuthor, VIB_MSG_ENTER);
2947         } else if (adp->type == 2 || adp->type == 3) {
2948           SendMessageToDialog (adp->strAuthor, VIB_MSG_ENTER);
2949         }
2950         break;
2951       default :
2952         break;
2953     }
2954   }
2955 }
2956 
2957 
IsAuthList(CharPtr path)2958 static Boolean IsAuthList (CharPtr path)
2959 {
2960   FILE *fp;
2961   Char buffer[10];
2962   Int4 len;
2963   Boolean rval = FALSE;
2964 
2965   fp = FileOpen (path, "r");
2966   if (fp == NULL) return FALSE;
2967 
2968   len = fread (buffer, 1, 9, fp);
2969   buffer[9] = 0;
2970   if (StringCmp (buffer, "Auth-list") == 0)
2971   {
2972     rval = TRUE;
2973   }
2974   FileClose (fp);
2975   return rval;
2976 }
2977 
2978 
ReadNameFromString(CharPtr str,CharPtr PNTR next_name,BoolPtr found_special)2979 static NameStdPtr ReadNameFromString (CharPtr str, CharPtr PNTR next_name, BoolPtr found_special)
2980 {
2981   CharPtr cp_end, cp_space;
2982   NameStdPtr n;
2983 
2984   if (StringHasNoText (str))
2985   {
2986     if (next_name != NULL)
2987     {
2988       *next_name = NULL;
2989     }
2990     return NULL;
2991   }
2992 
2993   /* skip over any leading spaces */
2994   str += StringSpn (str, " \t");
2995 
2996   /* skip over "and" if found */
2997   if (StringNCmp (str, "and ", 4) == 0)
2998   {
2999     str += 4;
3000   }
3001   if (StringHasNoText (str)) return NULL;
3002 
3003   cp_end = StringChr (str, ',');
3004   if (cp_end != NULL)
3005   {
3006     *cp_end = 0;
3007     if (next_name != NULL)
3008     {
3009       if (StringHasNoText (cp_end + 1))
3010       {
3011         *next_name = NULL;
3012       }
3013       else
3014       {
3015         *next_name = cp_end + 1;
3016       }
3017     }
3018   }
3019   else if (next_name != NULL)
3020   {
3021     *next_name = NULL;
3022   }
3023 
3024   n = NameStdNew ();
3025   /* look for elements in name */
3026   cp_space = StringRChr (str, ' ');
3027   if (cp_space == NULL)
3028   {
3029     n->names[0] = StringSave (str);
3030   }
3031   else
3032   {
3033     n->names[0] = StringSave (cp_space + 1);
3034     while (isspace (*cp_space))
3035     {
3036       cp_space--;
3037     }
3038     *(cp_space + 1) = 0;
3039     cp_space = StringChr (str, ' ');
3040     if (cp_space == NULL)
3041     {
3042        n->names[1] = StringSave (str);
3043        n->names[4] = (CharPtr) MemNew (sizeof (Char) * 3);
3044        sprintf (n->names[4], "%c.", *(n->names[1]));
3045     }
3046     else
3047     {
3048       *(cp_space) = 0;
3049       n->names[1] = StringSave (str);
3050 
3051       cp_space++;
3052       while (isspace (*cp_space))
3053       {
3054         cp_space++;
3055       }
3056 
3057       n->names[4] = (CharPtr) MemNew (sizeof (Char) * (4 + StringLen (cp_space)));
3058       sprintf (n->names[4], "%c.%s.", *(n->names[1]), cp_space);
3059     }
3060     SpecialCharReplace (&(n->names[1]), NULL, found_special, NULL);
3061     SpecialCharReplace (&(n->names[4]), NULL, found_special, NULL);
3062   }
3063   SpecialCharReplace (&(n->names[0]), NULL, found_special, NULL);
3064 
3065   return n;
3066 }
3067 
3068 
EndsWithComma(CharPtr str)3069 static Boolean EndsWithComma (CharPtr str)
3070 {
3071   CharPtr cp;
3072 
3073   if (StringHasNoText (str)) return FALSE;
3074   cp = str + StringLen (str) - 1;
3075   while (isspace (*cp) && cp > str)
3076   {
3077     cp--;
3078   }
3079   if (*cp == ',')
3080   {
3081     return TRUE;
3082   }
3083   else
3084   {
3085     return FALSE;
3086   }
3087 }
3088 
3089 
ExtendToComma(CharPtr line,ReadBufferPtr rbp)3090 static CharPtr ExtendToComma (CharPtr line, ReadBufferPtr rbp)
3091 {
3092   CharPtr next_line = NULL, tmp;
3093   Boolean end_of_file = FALSE;
3094 
3095   while (!EndsWithComma (line) && !end_of_file)
3096   {
3097     next_line = AbstractReadFunction (rbp);
3098     if (next_line == NULL)
3099     {
3100       end_of_file = TRUE;
3101     }
3102     else if (StringHasNoText (next_line))
3103     {
3104       next_line = MemFree (next_line);
3105     }
3106     else if (StringHasNoText (line))
3107     {
3108       line = MemFree (line);
3109       line = next_line;
3110     }
3111     else
3112     {
3113       tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (line) + StringLen (next_line) + 2));
3114       sprintf (tmp, "%s %s", line, next_line);
3115       next_line = MemFree (next_line);
3116       line = MemFree (line);
3117       line = tmp;
3118     }
3119   }
3120   return line;
3121 }
3122 
3123 
ReadAuthorListFromTextFile(CharPtr path)3124 static AuthListPtr ReadAuthorListFromTextFile (CharPtr path)
3125 {
3126   ReadBufferData rbd;
3127   CharPtr        line;
3128   AuthListPtr    alp = NULL;
3129   AuthorPtr      ap;
3130   CharPtr        cp, next_cp;
3131   NameStdPtr     n;
3132   ValNodePtr     names = NULL;
3133   Boolean        found_special = FALSE;
3134 
3135   rbd.fp = FileOpen (path, "r");
3136   if (rbd.fp == NULL) return FALSE;
3137   rbd.current_data = NULL;
3138 
3139   line = ExtendToComma (NULL, &rbd);
3140   while (line != NULL)
3141   {
3142     cp = line;
3143     next_cp = NULL;
3144     while (cp != NULL)
3145     {
3146       n = ReadNameFromString (cp, &next_cp, &found_special);
3147       if (n != NULL)
3148       {
3149         ap = AuthorNew ();
3150         ap->name = PersonIdNew ();
3151         ap->name->choice = 2;
3152         ap->name->data = n;
3153         ValNodeAddPointer (&names, 0, ap);
3154       }
3155       cp = next_cp;
3156     }
3157     line = MemFree (line);
3158     line = ExtendToComma (NULL, &rbd);
3159   }
3160   if (names != NULL)
3161   {
3162     alp = AuthListNew ();
3163     alp->choice = 1;
3164     alp->names = names;
3165   }
3166   if (found_special)
3167   {
3168     Message (MSG_OK, "Special characters in names were converted");
3169   }
3170 
3171   FileClose (rbd.fp);
3172   return alp;
3173 }
3174 
3175 
ReadAuthorDialog(DialoG d,CharPtr filename)3176 static Boolean ReadAuthorDialog (DialoG d, CharPtr filename)
3177 
3178 {
3179   AuthorDialogPtr  adp;
3180   AsnIoPtr         aip;
3181   AuthListPtr      alp = NULL;
3182   Char             path [PATH_MAX];
3183 
3184   path [0] = '\0';
3185   StringNCpy_0 (path, filename, sizeof (path));
3186   adp = (AuthorDialogPtr) GetObjectExtra (d);
3187   if (adp != NULL) {
3188     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
3189       if (IsAuthList (path)) {
3190         aip = AsnIoOpen (path, "r");
3191         if (aip != NULL) {
3192           alp = AuthListAsnRead (aip, NULL);
3193           AsnIoClose (aip);
3194         }
3195       } else {
3196         alp = ReadAuthorListFromTextFile (path);
3197       }
3198       if (alp != NULL) {
3199         PointerToDialog (adp->dialog, (Pointer) alp);
3200         alp = AuthListFree (alp);
3201         Update ();
3202         return TRUE;
3203       }
3204     }
3205   }
3206   return FALSE;
3207 }
3208 
WriteAuthorDialog(DialoG d,CharPtr filename)3209 static Boolean WriteAuthorDialog (DialoG d, CharPtr filename)
3210 
3211 {
3212   AuthorDialogPtr  adp;
3213   AsnIoPtr         aip;
3214   AuthListPtr      alp;
3215   Char             path [PATH_MAX];
3216 #ifdef WIN_MAC
3217   FILE            *f;
3218 #endif
3219 
3220   path [0] = '\0';
3221   StringNCpy_0 (path, filename, sizeof (path));
3222   adp = (AuthorDialogPtr) GetObjectExtra (d);
3223   if (adp != NULL) {
3224     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
3225 #ifdef WIN_MAC
3226       f = FileOpen (path, "r");
3227       if (f != NULL) {
3228         FileClose (f);
3229       } else {
3230         FileCreate (path, "TEXT", "ttxt");
3231       }
3232 #endif
3233       aip = AsnIoOpen (path, "w");
3234       if (aip != NULL) {
3235         alp = DialogToPointer (adp->dialog);
3236         AuthListAsnWrite (alp, aip, NULL);
3237         AsnIoClose (aip);
3238         alp = AuthListFree (alp);
3239         return TRUE;
3240       }
3241     }
3242   }
3243   return FALSE;
3244 }
3245 
3246 
InsertFirstAuthor(ButtoN b)3247 static void InsertFirstAuthor (ButtoN b)
3248 {
3249   AuthorDialogPtr  adp;
3250   AuthListPtr      alp;
3251   AuthorPtr        ap;
3252   NameStdPtr       nsp;
3253   ValNodePtr       vnp;
3254 
3255   adp = (AuthorDialogPtr) GetObjectExtra (b);
3256   if (adp == NULL) {
3257     return;
3258   }
3259 
3260   alp = DialogToPointer (adp->dialog);
3261   if (alp != NULL && alp->names != NULL) {
3262     vnp = ValNodeNew (NULL);
3263     vnp->next = alp->names;
3264     alp->names = vnp;
3265     if (alp->choice == 1) {
3266       ap = AuthorNew ();
3267       ap->name = PersonIdNew ();
3268       ap->name->choice = 2;
3269       nsp = NameStdNew ();
3270       ap->name->data = nsp;
3271       vnp->data.ptrvalue = ap;
3272     } else {
3273       vnp->data.ptrvalue = StringSave ("");
3274     }
3275     PointerToDialog (adp->dialog, alp);
3276     SendMessageToDialog (adp->dialog, VIB_MSG_ENTER);
3277   }
3278   alp = AuthListFree (alp);
3279 }
3280 
3281 
RemoveTabAndCrFromContextList(ValNodePtr PNTR find_list)3282 static void RemoveTabAndCrFromContextList (ValNodePtr PNTR find_list)
3283 {
3284   ValNodePtr vnp, prev = NULL, vnp_next;
3285 
3286   if (find_list == NULL) {
3287     return;
3288   }
3289   for (vnp = *find_list; vnp != NULL; vnp = vnp_next) {
3290     vnp_next = vnp->next;
3291     if (vnp->choice == '\t' || vnp->choice == '\n') {
3292       if (prev == NULL) {
3293         *find_list = vnp_next;
3294       } else{
3295         prev->next = vnp_next;
3296       }
3297       vnp->next = NULL;
3298       vnp = FreeContextList (vnp);
3299     } else {
3300       prev = vnp;
3301     }
3302   }
3303 }
3304 
3305 
TestAuthorDialog(DialoG d)3306 static ValNodePtr TestAuthorDialog (DialoG d)
3307 {
3308   AuthorDialogPtr  adp;
3309   ValNodePtr       find_list = NULL, vnp;
3310   TagListPtr       tlp;
3311   Boolean          did_find = FALSE;
3312   Boolean          did_change = FALSE;
3313   CharPtr PNTR     vals;
3314   Int4             i;
3315   AuthListPtr      alp;
3316 
3317   adp = (AuthorDialogPtr)GetObjectExtra (d);
3318   if (adp == NULL) {
3319     return NULL;
3320   }
3321   tlp = (TagListPtr) GetObjectExtra (adp->stdAuthor);
3322   if (tlp == NULL || tlp->vnp == NULL) {
3323     return NULL;
3324   }
3325   vals = (CharPtr PNTR) MemNew (sizeof (CharPtr) * ValNodeLen (tlp->vnp));
3326   for (vnp = tlp->vnp, i = 0; vnp != NULL; vnp = vnp->next, i++) {
3327     vals[i] = (CharPtr) vnp->data.ptrvalue;
3328     SpecialCharFindWithContext (vals + i, &find_list, &did_find, &did_change);
3329   }
3330 
3331   RemoveTabAndCrFromContextList (&find_list);
3332   if (find_list != NULL && FixSpecialCharactersForStringsInList (find_list,
3333               "The author names contain special characters. You must replace them.",
3334               TRUE)) {
3335     for (vnp = tlp->vnp, i = 0; vnp != NULL; vnp = vnp->next, i++) {
3336       vnp->data.ptrvalue = vals[i];
3337     }
3338     alp = DialogToPointer (adp->stdAuthor);
3339     PointerToDialog (adp->stdAuthor, alp);
3340     alp = AuthListFree (alp);
3341   }
3342   vals = MemFree (vals);
3343 
3344   find_list = FreeContextList (find_list);
3345   return NULL;
3346 }
3347 
3348 
ImportAuthorsBtn(ButtoN b)3349 static void ImportAuthorsBtn (ButtoN b)
3350 {
3351   AuthorDialogPtr dlg;
3352   Char              path [PATH_MAX];
3353 
3354   dlg = (AuthorDialogPtr) GetObjectExtra (b);
3355   if (dlg == NULL) {
3356     return;
3357   }
3358   path[0] = '\0';
3359   if (GetInputFileName (path, sizeof (path), "", "TEXT")) {
3360     ImportDialog (dlg->dialog, path);
3361     if (dlg->change_notify != NULL) {
3362       (dlg->change_notify)(dlg->change_data);
3363     }
3364   }
3365 }
3366 
3367 
AuthorNotify(Pointer data)3368 static void AuthorNotify (Pointer data)
3369 {
3370   AuthorDialogPtr adp;
3371 
3372   adp = (AuthorDialogPtr) data;
3373   if (adp != NULL && adp->change_notify != NULL) {
3374     (adp->change_notify)(adp->change_data);
3375   }
3376 }
3377 
3378 
3379 static TaglistCallback author_callback_list[4] =
3380  { AuthorNotify, AuthorNotify, AuthorNotify, AuthorNotify };
3381 
3382 
CreateAuthorDialogEx(GrouP prnt,Uint2 rows,Int2 spacing,Boolean use_import_btn,Nlm_ChangeNotifyProc change_notify,Pointer change_data)3383 extern DialoG CreateAuthorDialogEx (GrouP prnt, Uint2 rows, Int2 spacing, Boolean use_import_btn, Nlm_ChangeNotifyProc change_notify, Pointer change_data)
3384 
3385 {
3386   AuthorDialogPtr  adp;
3387   GrouP            k;
3388   GrouP            p, list_grp, btn_grp;
3389   PrompT           p1, p2, p3, p4, p5;
3390   TagListPtr       tlp;
3391   ButtoN           b;
3392 
3393   p = HiddenGroup (prnt, -1, 0, NULL);
3394 
3395   adp = (AuthorDialogPtr) MemNew (sizeof (AuthorDialog));
3396   if (adp != NULL) {
3397 
3398     SetObjectExtra (p, adp, StdCleanupExtraProc);
3399     adp->dialog = (DialoG) p;
3400     adp->todialog = AuthListPtrToAuthorDialog;
3401     adp->fromdialog = AuthorDialogToAuthListPtr;
3402     adp->testdialog = TestAuthorDialog;
3403     adp->importdialog = ReadAuthorDialog;
3404     adp->exportdialog = WriteAuthorDialog;
3405     adp->dialogmessage = AuthorDialogMessage;
3406     adp->change_notify = change_notify;
3407     adp->change_data = change_data;
3408 
3409     list_grp = HiddenGroup (p, 0, 0, NULL);
3410 
3411     adp->strGrp = HiddenGroup (list_grp, -1, 0, NULL);
3412     SetGroupSpacing (adp->strGrp, 3, 2);
3413 
3414     k = HiddenGroup (adp->strGrp, -4, 0, NULL);
3415     SetGroupSpacing (k, spacing, spacing);
3416     p1 = StaticPrompt (k, "Name", 0, 0, programFont, 'c');
3417 
3418     adp->strAuthor = CreateTagListDialogExEx (adp->strGrp, rows, 1, spacing,
3419                                           author_types, str_author_widths, NULL,
3420                                           TRUE, FALSE,
3421                                           StrAuthListPtrToAuthorDialog,
3422                                           AuthorDialogToStrAuthListPtr,
3423                                           author_callback_list, adp, FALSE);
3424     Hide (adp->strGrp);
3425 
3426     adp->stdGrp = HiddenGroup (list_grp, -1, 0, NULL);
3427     SetGroupSpacing (adp->stdGrp, 3, 2);
3428 
3429     k = HiddenGroup (adp->stdGrp, -4, 0, NULL);
3430     SetGroupSpacing (k, spacing, spacing);
3431     p2 = StaticPrompt (k, "First Name", 0, 0, programFont, 'c');
3432     p3 = StaticPrompt (k, "M.I.", 0, 0, programFont, 'c');
3433     p4 = StaticPrompt (k, "Last Name", 0, 0, programFont, 'c');
3434     p5 = StaticPrompt (k, "Sfx", 0, 0, programFont, 'c');
3435 
3436     adp->stdAuthor = CreateTagListDialogEx3 (adp->stdGrp, rows, 4, spacing,
3437                                              author_types, std_author_widths,
3438                                              author_popups,
3439                                              TRUE, FALSE,
3440                                              StdAuthListPtrToAuthorDialog,
3441                                              AuthorDialogToStdAuthListPtr,
3442                                              author_callback_list, adp, FALSE, TRUE);
3443     adp->type = 1;
3444 
3445     tlp = (TagListPtr) GetObjectExtra (adp->strAuthor);
3446     if (tlp != NULL) {
3447       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [0], (HANDLE) p1, NULL);
3448     }
3449     tlp = (TagListPtr) GetObjectExtra (adp->stdAuthor);
3450     if (tlp != NULL) {
3451       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [0], (HANDLE) p2, NULL);
3452       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [1], (HANDLE) p3, NULL);
3453       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [2], (HANDLE) p4, NULL);
3454       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [3], (HANDLE) p5, NULL);
3455     }
3456 
3457     btn_grp = HiddenGroup (p, 2, 0, NULL);
3458     SetGroupSpacing (btn_grp, 10, 10);
3459     b = PushButton (btn_grp, "Insert First Author", InsertFirstAuthor);
3460     SetObjectExtra (b, adp, NULL);
3461     if (use_import_btn) {
3462       b = PushButton (btn_grp, "Import Authors", ImportAuthorsBtn);
3463       SetObjectExtra (b, adp, NULL);
3464     }
3465     AlignObjects (ALIGN_CENTER, (HANDLE) list_grp, (HANDLE) btn_grp, NULL);
3466   }
3467 
3468   return (DialoG) p;
3469 }
3470 
3471 
CreateAuthorDialog(GrouP prnt,Uint2 rows,Int2 spacing)3472 extern DialoG CreateAuthorDialog (GrouP prnt, Uint2 rows, Int2 spacing)
3473 
3474 {
3475   return CreateAuthorDialogEx (prnt, rows, spacing, FALSE, NULL, NULL);
3476 
3477 }
3478 
3479 
3480 typedef struct affildialog {
3481   DIALOG_MESSAGE_BLOCK
3482   TexT            affil;
3483   TexT            div;
3484   TexT            address;
3485   TexT            city;
3486   TexT            state;
3487   TexT            zip;
3488   TexT            country;
3489   TexT            phone;
3490   TexT            fax;
3491   TexT            email;
3492 } AffilDialog, PNTR AffilDialogPtr;
3493 
AffilPtrToAffilDialog(DialoG d,Pointer data)3494 static void AffilPtrToAffilDialog (DialoG d, Pointer data)
3495 
3496 {
3497   AffilDialogPtr  adp;
3498   AffilPtr        ap;
3499 
3500   adp = (AffilDialogPtr) GetObjectExtra (d);
3501   ap = (AffilPtr) data;
3502   if (adp != NULL) {
3503     if (ap != NULL) {
3504       SafeSetTitle (adp->affil, ap->affil);
3505       SafeSetTitle (adp->div, ap->div);
3506       SafeSetTitle (adp->address, ap->street);
3507       SafeSetTitle (adp->city, ap->city);
3508       SafeSetTitle (adp->state, ap->sub);
3509       SafeSetTitle (adp->zip, ap->postal_code);
3510       SafeSetTitle (adp->country, ap->country);
3511       SafeSetTitle (adp->phone, ap->phone);
3512       SafeSetTitle (adp->fax, ap->fax);
3513       SafeSetTitle (adp->email, ap->email);
3514     } else {
3515       SafeSetTitle (adp->affil, "");
3516       SafeSetTitle (adp->div, "");
3517       SafeSetTitle (adp->address, "");
3518       SafeSetTitle (adp->city, "");
3519       SafeSetTitle (adp->state, "");
3520       SafeSetTitle (adp->zip, "");
3521       SafeSetTitle (adp->country, "");
3522       SafeSetTitle (adp->phone, "");
3523       SafeSetTitle (adp->fax, "");
3524       SafeSetTitle (adp->email, "");
3525     }
3526   }
3527 }
3528 
AffilDialogToAffilPtr(DialoG d)3529 static Pointer AffilDialogToAffilPtr (DialoG d)
3530 
3531 {
3532   AffilDialogPtr  adp;
3533   AffilPtr        ap;
3534 
3535   ap = NULL;
3536   adp = (AffilDialogPtr) GetObjectExtra (d);
3537   if (adp != NULL) {
3538     ap = AffilNew ();
3539     if (ap != NULL) {
3540       ap->affil = SaveStringFromText (adp->affil);
3541       ap->div = SaveStringFromText (adp->div);
3542       ap->street = SaveStringFromText (adp->address);
3543       ap->city = SaveStringFromText (adp->city);
3544       ap->sub = SaveStringFromText (adp->state);
3545       ap->postal_code = SaveStringFromText (adp->zip);
3546       ap->country = SaveStringFromText (adp->country);
3547       ap->phone = SaveStringFromText (adp->phone);
3548       ap->fax = SaveStringFromText (adp->fax);
3549       ap->email = SaveStringFromText (adp->email);
3550       if (ap->div == NULL && ap->street == NULL && ap->city == NULL &&
3551            ap->sub == NULL && ap->postal_code == NULL && ap->country == NULL &&
3552            ap->phone == NULL && ap->fax == NULL && ap->email == NULL) {
3553         ap->choice = 1;
3554         if (ap->affil == NULL) {
3555           ap = AffilFree (ap);
3556         }
3557       } else {
3558         ap->choice = 2;
3559       }
3560     }
3561   }
3562   return (Pointer) ap;
3563 }
3564 
AffilDialogMessage(DialoG d,Int2 mssg)3565 static void AffilDialogMessage (DialoG d, Int2 mssg)
3566 
3567 {
3568   AffilDialogPtr  adp;
3569 
3570   adp = (AffilDialogPtr) GetObjectExtra (d);
3571   if (adp != NULL) {
3572     switch (mssg) {
3573       case VIB_MSG_ENTER :
3574         Select (adp->affil);
3575         break;
3576       default :
3577         break;
3578     }
3579   }
3580 }
3581 
CreateAnAffilDialog(GrouP prnt,CharPtr title,Boolean publisher,Boolean split,Boolean proceedings,GrouP PNTR grp1,GrouP PNTR grp2)3582 static DialoG CreateAnAffilDialog (GrouP prnt, CharPtr title,
3583                                    Boolean publisher,
3584                                    Boolean split,
3585                                    Boolean proceedings,
3586                                    GrouP PNTR grp1, GrouP PNTR grp2)
3587 
3588 {
3589   AffilDialogPtr  adp;
3590   GrouP           g;
3591   GrouP           g1, g2;
3592   GrouP           j;
3593   GrouP           m;
3594   GrouP           p;
3595   GrouP           q;
3596   GrouP           s;
3597 #ifdef WIN_MAC
3598   Int2            wid = 20;
3599   Int2            zipw = 6;
3600   Int2            ewid = 8;
3601 #else
3602   Int2            wid = 30;
3603   Int2            zipw = 10;
3604   Int2            ewid = 20;
3605 #endif
3606 
3607   p = HiddenGroup (prnt, 0, 0, NULL);
3608 
3609   adp = (AffilDialogPtr) MemNew (sizeof (AffilDialog));
3610   if (adp != NULL) {
3611 
3612     SetObjectExtra (p, adp, StdCleanupExtraProc);
3613     adp->dialog = (DialoG) p;
3614     adp->todialog = AffilPtrToAffilDialog;
3615     adp->fromdialog = AffilDialogToAffilPtr;
3616     adp->testdialog = NULL;
3617     adp->dialogmessage = AffilDialogMessage;
3618 
3619     if (title != NULL && title [0] != '\0') {
3620       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
3621     } else {
3622       s = HiddenGroup (p, 0, -2, NULL);
3623     }
3624     m = HiddenGroup (s, 0, 0, NULL);
3625 
3626     q = HiddenGroup (m, 2, 0, NULL);
3627     g1 = q;
3628     g2 = NULL;
3629     if (grp1 != NULL) {
3630       *grp1 = q;
3631     }
3632     if (grp2 != NULL) {
3633       *grp2 = NULL;
3634     }
3635     g = HiddenGroup (q, 0, 20, NULL);
3636     if (publisher) {
3637       StaticPrompt (g, "Publisher", 0, dialogTextHeight, programFont, 'l');
3638     } else if (proceedings) {
3639       StaticPrompt (g, "Location", 0, dialogTextHeight, programFont, 'l');
3640     } else {
3641       StaticPrompt (g, "Institution", 0, dialogTextHeight, programFont, 'l');
3642       StaticPrompt (g, "Department", 0, dialogTextHeight, programFont, 'l');
3643     }
3644     StaticPrompt (g, "Street Address", 0, dialogTextHeight, programFont, 'l');
3645     StaticPrompt (g, "City", 0, dialogTextHeight, programFont, 'l');
3646     StaticPrompt (g, "State/Province", 0, dialogTextHeight, programFont, 'l');
3647     StaticPrompt (g, "Country", 0, dialogTextHeight, programFont, 'l');
3648     if (! split) {
3649       if (! proceedings) {
3650         StaticPrompt (g, "", 0, stdLineHeight, programFont, 'l');
3651         StaticPrompt (g, "Phone", 0, dialogTextHeight, programFont, 'l');
3652         if (publisher) {
3653           StaticPrompt (g, "Internet Access", 0, dialogTextHeight, programFont, 'l');
3654         } else {
3655           StaticPrompt (g, "Email", 0, dialogTextHeight, programFont, 'l');
3656         }
3657       }
3658     }
3659     j = HiddenGroup (q, 0, 20, NULL);
3660     g = HiddenGroup (j, 0, 20, NULL);
3661     adp->affil = DialogText (g, "", wid, NULL);
3662     adp->div = NULL;
3663     if (! publisher && ! proceedings) {
3664       adp->div = DialogText (g, "", wid, NULL);
3665     }
3666     adp->address = DialogText (g, "", wid, NULL);
3667     adp->city = DialogText (g, "", wid, NULL);
3668     g = HiddenGroup (j, 3, 0, NULL);
3669     SetGroupSpacing (g, 20, 2);
3670     adp->state = DialogText (g, "", 10, NULL);
3671     if (! proceedings) {
3672       /* StaticPrompt (g, "Zip/Postal Code", 7 * stdCharWidth,
3673                     dialogTextHeight, programFont, 'l'); */
3674       StaticPrompt (g, "Zip/Postal Code", 0, dialogTextHeight, programFont, 'l');
3675       adp->zip = DialogText (g, "", zipw, NULL);
3676     }
3677     g = HiddenGroup (j, 0, 20, NULL);
3678     adp->country = DialogText (g, "", wid, NULL);
3679     if (split) {
3680       if (! proceedings) {
3681         q = HiddenGroup (m, 2, 0, NULL);
3682         g2 = q;
3683         if (grp2 != NULL) {
3684           *grp2 = q;
3685         }
3686         g = HiddenGroup (q, 0, 20, NULL);
3687         StaticPrompt (g, "", 0, stdLineHeight, programFont, 'l');
3688         StaticPrompt (g, "Phone", 0, dialogTextHeight, programFont, 'l');
3689         if (publisher) {
3690           StaticPrompt (g, "Internet Access", 0, dialogTextHeight, programFont, 'l');
3691         } else {
3692           StaticPrompt (g, "Email", 0, dialogTextHeight, programFont, 'l');
3693         }
3694         j = HiddenGroup (q, 0, 20, NULL);
3695       }
3696     }
3697     if (! proceedings) {
3698       StaticPrompt (j, "Please include country code for non-U.S. phone numbers.",
3699                     0, stdLineHeight, programFont, 'l');
3700       g = HiddenGroup (j, 3, 0, NULL);
3701       SetGroupSpacing (g, 20, 2);
3702       adp->phone = DialogText (g, "", 10, NULL);
3703       if (split) {
3704         StaticPrompt (g, "Fax", 0,
3705                       dialogTextHeight, programFont, 'l');
3706       } else {
3707         StaticPrompt (g, "Fax", /* 7 * stdCharWidth */ 0,
3708                       dialogTextHeight, programFont, 'l');
3709       }
3710       adp->fax = DialogText (g, "", 10, NULL);
3711       g = HiddenGroup (j, 0, 20, NULL);
3712       if (split) {
3713         adp->email = DialogText (g, "", ewid, NULL);
3714       } else {
3715         adp->email = DialogText (g, "", ewid, NULL);
3716       }
3717     }
3718 
3719     if (split) {
3720       AlignObjects (ALIGN_RIGHT, (HANDLE) adp->affil,
3721                     (HANDLE) adp->address, (HANDLE) adp->city,
3722                     (HANDLE) adp->zip, (HANDLE) adp->country,
3723                     (HANDLE) adp->div, NULL);
3724       AlignObjects (ALIGN_RIGHT, (HANDLE) adp->fax, (HANDLE) adp->email, NULL);
3725       AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) g2, NULL);
3726       Hide (g1);
3727       Hide (g2);
3728     } else {
3729       AlignObjects (ALIGN_RIGHT, (HANDLE) adp->affil,
3730                     (HANDLE) adp->address, (HANDLE) adp->city,
3731                     (HANDLE) adp->zip, (HANDLE) adp->country,
3732                     (HANDLE) adp->fax, (HANDLE) adp->email,
3733                     (HANDLE) adp->div, NULL);
3734     }
3735   }
3736 
3737   return (DialoG) p;
3738 }
3739 
CreateAffilDialog(GrouP prnt,CharPtr title)3740 extern DialoG CreateAffilDialog (GrouP prnt, CharPtr title)
3741 
3742 {
3743   return CreateAnAffilDialog (prnt, title, FALSE, FALSE, FALSE, NULL, NULL);
3744 }
3745 
CreatePublisherAffilDialog(GrouP prnt,CharPtr title)3746 extern DialoG CreatePublisherAffilDialog (GrouP prnt, CharPtr title)
3747 
3748 {
3749   return CreateAnAffilDialog (prnt, title, TRUE, FALSE, FALSE, NULL, NULL);
3750 }
3751 
CreateProceedingsDialog(GrouP prnt,CharPtr title)3752 extern DialoG CreateProceedingsDialog (GrouP prnt, CharPtr title)
3753 
3754 {
3755   return CreateAnAffilDialog (prnt, title, FALSE, FALSE, TRUE, NULL, NULL);
3756 }
3757 
CreateExtAffilDialog(GrouP prnt,CharPtr title,GrouP PNTR grp1,GrouP PNTR grp2)3758 extern DialoG CreateExtAffilDialog (GrouP prnt, CharPtr title, GrouP PNTR grp1, GrouP PNTR grp2)
3759 
3760 {
3761   return CreateAnAffilDialog (prnt, title, FALSE, TRUE, FALSE, grp1, grp2);
3762 }
3763 
CreateExtPublisherAffilDialog(GrouP prnt,CharPtr title,GrouP PNTR grp1,GrouP PNTR grp2)3764 extern DialoG CreateExtPublisherAffilDialog (GrouP prnt, CharPtr title, GrouP PNTR grp1, GrouP PNTR grp2)
3765 
3766 {
3767   return CreateAnAffilDialog (prnt, title, TRUE, TRUE, FALSE, grp1, grp2);
3768 }
3769 
CreateExtProceedingsDialog(GrouP prnt,CharPtr title,GrouP PNTR grp1,GrouP PNTR grp2)3770 extern DialoG CreateExtProceedingsDialog (GrouP prnt, CharPtr title, GrouP PNTR grp1, GrouP PNTR grp2)
3771 
3772 {
3773   return CreateAnAffilDialog (prnt, title, FALSE, TRUE, TRUE, grp1, grp2);
3774 }
3775 
DatePtrToVibrant(DatePtr dp,PopuP dateMonth,TexT dateDay,TexT dateYear)3776 extern void DatePtrToVibrant (DatePtr dp, PopuP dateMonth, TexT dateDay, TexT dateYear)
3777 
3778 {
3779   Int2  day;
3780   Char  str [32];
3781   Int2  year;
3782 
3783   if (dp != NULL) {
3784     if (dp->data [0] == 0) {
3785       DatePrint (dp, str);
3786     } else if (dp->data [0] == 1) {
3787       SetEnumPopup (dateMonth, months_alist, (UIEnum) dp->data [2]);
3788       day = (Int2) dp->data [3];
3789       if (day > 0 && day <= 31) {
3790         sprintf (str, "%d", (int) day);
3791         SafeSetTitle (dateDay, str);
3792       } else {
3793         SafeSetTitle (dateDay, "");
3794       }
3795       year = (Int2) dp->data [1];
3796       if (year > 0) {
3797         sprintf (str, "%d", (int) (year + 1900));
3798         SafeSetTitle (dateYear, str);
3799       } else {
3800         SafeSetTitle (dateYear, "");
3801       }
3802     } else {
3803       Message (MSG_ERROR, "Unknown date type");
3804     }
3805   } else {
3806     SafeSetValue (dateMonth, 1);
3807     SafeSetTitle (dateDay, "");
3808     SafeSetTitle (dateYear, "");
3809   }
3810 }
3811 
VibrantToDatePtr(PopuP dateMonth,TexT dateDay,TexT dateYear)3812 extern DatePtr VibrantToDatePtr (PopuP dateMonth, TexT dateDay, TexT dateYear)
3813 
3814 {
3815   Int2     day;
3816   Int2     dateType;
3817   DatePtr  dp;
3818   UIEnum   month;
3819   Char     str [32];
3820   Int2     year;
3821 
3822   dp = DateNew ();
3823   if (dp != NULL) {
3824     dateType = 1;
3825     dp->data [0] = (Uint1) dateType;
3826     if (dateType == 0) {
3827     } else if (dateType == 1) {
3828       GetTitle (dateYear, str, sizeof (str));
3829       if (! StringHasNoText (str)) {
3830         StrToInt (str, &year);
3831         if (year >= 1900) {
3832           dp->data [1] = (Uint1) (year - 1900);
3833         } else {
3834           /* dp->data [1] = 0; */
3835           dp = DateFree (dp);
3836           return dp;
3837         }
3838         if (GetEnumPopup (dateMonth, months_alist, &month)) {
3839           dp->data [2] = (Uint1) month;
3840         }
3841         GetTitle (dateDay, str, sizeof (str));
3842         StrToInt (str, &day);
3843         dp->data [3] = (Uint1) day;
3844       } else {
3845         dp = DateFree (dp);
3846       }
3847     } else {
3848       Message (MSG_ERROR, "Unknown date type");
3849     }
3850   }
3851   return dp;
3852 }
3853 
GBQualPtrToQualsDialog(DialoG d,Pointer data)3854 static void GBQualPtrToQualsDialog (DialoG d, Pointer data)
3855 
3856 {
3857   ValNodePtr  head;
3858   Int2        j;
3859   size_t      len;
3860   GBQualPtr   list;
3861   CharPtr     str;
3862   TagListPtr  tlp;
3863   ValNodePtr  vnp;
3864 
3865   tlp = (TagListPtr) GetObjectExtra (d);
3866   list = (GBQualPtr) data;
3867   if (tlp != NULL) {
3868     head = NULL;
3869     while (list != NULL) {
3870       vnp = ValNodeNew (head);
3871       if (head == NULL) {
3872         head = vnp;
3873       }
3874       if (vnp != NULL) {
3875         if (list->qual != NULL && list->val != NULL) {
3876           len = StringLen (list->qual) + StringLen (list->val);
3877           str = MemNew (len + 4);
3878           if (str != NULL) {
3879             StringCpy (str, list->qual);
3880             StringCat (str, "\t");
3881             StringCat (str, list->val);
3882             StringCat (str, "\n");
3883           }
3884           vnp->data.ptrvalue = str;
3885         }
3886       }
3887       list = list->next;
3888     }
3889     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
3890     tlp->vnp = head;
3891     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
3892     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
3893     }
3894     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
3895     CorrectBarMax (tlp->bar, tlp->max);
3896     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
3897   }
3898 }
3899 
QualsDialogToGBQualPtr(DialoG d)3900 static Pointer QualsDialogToGBQualPtr (DialoG d)
3901 
3902 {
3903   Char         ch;
3904   GBQualPtr    gbq;
3905   GBQualPtr    gbqlast;
3906   GBQualPtr    head;
3907   Int2         j;
3908   Int2         len;
3909   Boolean      okay;
3910   CharPtr      str;
3911   TagListPtr   tlp;
3912   ValNodePtr   vnp;
3913 
3914   head = NULL;
3915   tlp = (TagListPtr) GetObjectExtra (d);
3916   if (tlp != NULL && tlp->vnp != NULL) {
3917     gbq = NULL;
3918     gbqlast = NULL;
3919     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
3920       str = (CharPtr) vnp->data.ptrvalue;
3921       okay = FALSE;
3922       len = StringLen (str);
3923       for (j = 0; j < len; j++) {
3924         ch = str [j];
3925         if (ch != ' ' && ch != '\t' && ch != '\n') {
3926           okay = TRUE;
3927         }
3928       }
3929       if (okay) {
3930         gbq = GBQualNew ();
3931         if (gbqlast == NULL) {
3932           head = gbq;
3933         } else {
3934           gbqlast->next = gbq;
3935         }
3936         gbqlast = gbq;
3937         if (gbq != NULL) {
3938           gbq->qual = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
3939           gbq->val = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
3940         }
3941       }
3942     }
3943   }
3944   return (Pointer) head;
3945 }
3946 
3947 Uint2 gbqual_types [] = {
3948   TAGLIST_TEXT, TAGLIST_TEXT
3949 };
3950 
3951 Uint2 gbqual_widths [] = {
3952   0, 0, 0, 0
3953 };
3954 
3955 extern DialoG CreateQualsDialog (GrouP h, Uint2 rows, Int2 spacing,
3956                                  Int2 width1, Int2 width2);
CreateQualsDialog(GrouP h,Uint2 rows,Int2 spacing,Int2 width1,Int2 width2)3957 extern DialoG CreateQualsDialog (GrouP h, Uint2 rows, Int2 spacing,
3958                                  Int2 width1, Int2 width2)
3959 
3960 {
3961   gbqual_widths [0] = width1;
3962   gbqual_widths [1] = width2;
3963   return CreateTagListDialog (h, rows, 2, spacing,
3964                               gbqual_types, gbqual_widths, NULL,
3965                               GBQualPtrToQualsDialog,
3966                               QualsDialogToGBQualPtr);
3967 }
3968 
CreateSeqAlignLabel(SeqAlignPtr salp,CharPtr buf,Int4 buf_size)3969 extern void CreateSeqAlignLabel (SeqAlignPtr salp, CharPtr buf, Int4 buf_size)
3970 {
3971   Int4     remaining_len, aln_pos, id_len;
3972   SeqIdPtr sip;
3973   CharPtr  buf_ptr;
3974 
3975   if (buf == NULL || buf_size < 1)
3976   {
3977     return;
3978   }
3979   MemSet (buf, 0, buf_size);
3980   if (salp == NULL)
3981   {
3982     return;
3983   }
3984   remaining_len = buf_size - 1;
3985   buf_ptr = buf;
3986   StringNCat (buf_ptr, "aln|", remaining_len);
3987   remaining_len -= 4;
3988 
3989   if (remaining_len <= 3)
3990   {
3991     return;
3992   }
3993   buf_ptr += 4;
3994 
3995   for (aln_pos = 1; aln_pos <= salp->dim && remaining_len > 2; aln_pos++)
3996   {
3997     sip = AlnMgr2GetNthSeqIdPtr(salp, aln_pos);
3998     SeqIdWrite (sip, buf_ptr, PRINTID_REPORT, remaining_len);
3999     id_len = StringLen (buf_ptr);
4000     remaining_len -= id_len;
4001     buf_ptr += id_len;
4002     /* put comma between IDs in list */
4003     if (aln_pos < salp->dim && remaining_len > 2)
4004     {
4005       StringCat (buf_ptr, ",");
4006       remaining_len -= 1;
4007       buf_ptr += 1;
4008     }
4009   }
4010 
4011   /* add ellipsis to indicate unshown IDs */
4012   if (remaining_len == 0 && aln_pos < salp->dim)
4013   {
4014     buf_ptr -= 3;
4015     StringCat (buf_ptr, "...");
4016   }
4017 }
4018 
4019 
HasDisqualifyingUserObjects(SeqAnnotPtr sap)4020 static Boolean HasDisqualifyingUserObjects(SeqAnnotPtr sap)
4021 {
4022   AnnotDescrPtr desc;
4023   UserObjectPtr uop;
4024   ObjectIdPtr   oip;
4025 
4026   if (sap == NULL) {
4027     return FALSE;
4028   }
4029 
4030   desc = sap->desc;
4031   while (desc != NULL) {
4032     if (desc->choice == Annot_descr_user) {
4033       uop = (UserObjectPtr) desc->data.ptrvalue;
4034       while(uop) {
4035         if(uop->type) {
4036           oip = uop->type;
4037           if(StringCmp(oip->str, "Hist Seqalign") == 0
4038              || StringCmp (oip->str, "Blast Type") == 0) {
4039             return TRUE;
4040           }
4041         }
4042         uop = uop->next;
4043       }
4044     }
4045     desc = desc->next;
4046   }
4047   return FALSE;
4048 }
4049 
4050 
GetAlignmentsInSeqEntryCallback(SeqAnnotPtr sap,Pointer userdata)4051 extern void GetAlignmentsInSeqEntryCallback (SeqAnnotPtr sap, Pointer userdata)
4052 {
4053   SeqAlignPtr PNTR salp_list;
4054   SeqAlignPtr salp, last_salp;
4055 
4056   if (sap == NULL || sap->type != 2 || userdata == NULL || HasDisqualifyingUserObjects(sap))
4057   {
4058     return;
4059   }
4060   salp_list = (SeqAlignPtr PNTR) userdata;
4061   salp = (SeqAlignPtr) sap->data;
4062   if (salp == NULL) return;
4063   if (salp->segtype == SAS_SPLICED || salp->segtype == SAS_SPARSE) return;
4064   salp = AlnMgr2DupAlnAndIndexes(salp);
4065   AlnMgr2IndexSeqAlign(salp);
4066   if (*salp_list == NULL)
4067   {
4068     *salp_list = salp;
4069   }
4070   else
4071   {
4072     last_salp = *salp_list;
4073     while (last_salp->next != NULL)
4074     {
4075       last_salp = last_salp->next;
4076     }
4077     last_salp->next = salp;
4078   }
4079 }
4080 
4081 typedef struct intervalpage {
4082   DIALOG_MESSAGE_BLOCK
4083   DialoG             ivals;
4084   ButtoN             partial5;
4085   ButtoN             partial3;
4086   ButtoN             nullsBetween;
4087   Int2               count;
4088   SeqIdPtr           PNTR sip_list;
4089   EnumFieldAssoc     PNTR alist;
4090   EnumFieldAssocPtr  alists [5];
4091   Int4               PNTR lengths;
4092   Boolean            nucsOK;
4093   Boolean            protsOK;
4094   Boolean            showIdTags;
4095   FeatureFormPtr     ffp;
4096   IntEdPartialProc   proc;
4097 
4098   Int4               strand_col;  /* column for selecting strand.
4099                                    * 2 if nucsOK, -1 otherwise
4100                                    */
4101   Int4               seqid_col;   /* column for entering SeqIds,
4102                                    * which could be in a different place
4103                                    * depending on nucsOK or -1 if not show_seqid
4104                                    */
4105   Int4               aln_col;     /* column for selecting alignments,
4106                                    * could be in a different place if not show_seqid
4107                                    * or -1 if not use_aln
4108                                    */
4109   Boolean            show_seqids; /* false when entering coordinates for an entire
4110                                    * alignments, true otherwise
4111                                    */
4112 
4113   /* for editing alignment intervals */
4114   SeqAlignPtr        PNTR salp_list;
4115   TaglistCallback    PNTR callbacks;
4116   EnumFieldAssoc     PNTR aln_alist;
4117   Int2               aln_count;
4118   Int4               PNTR aln_lengths;
4119   Boolean            allow_nulls_in_list; /* some sequences may be all gap
4120                                            * in the specified interval -
4121                                            * if this value is FALSE, return
4122                                            * a NULL for the entire list,
4123                                            * otherwise allow NULLs to appear
4124                                            * in the list.
4125                                            */
4126 
4127 } IntervalPage, PNTR IntervalPagePtr;
4128 
4129 #define NUM_IVAL_ROWS  7
4130 #define EXTRA_HEIGHT   2
4131 
ClearBspScratch(BioseqPtr bsp,Pointer userdata)4132 static void ClearBspScratch (BioseqPtr bsp, Pointer userdata)
4133 
4134 {
4135   if (bsp == NULL) return;
4136   bsp->idx.scratch = NULL;
4137 }
4138 
AddToSipList(IntervalPagePtr ipp,BioseqPtr bsp)4139 static void AddToSipList (IntervalPagePtr ipp, BioseqPtr bsp)
4140 
4141 {
4142   /*
4143   Int2      j;
4144   */
4145   SeqIdPtr  sip;
4146 
4147   if (ipp == NULL || bsp == NULL) return;
4148   if (bsp->idx.scratch != NULL) return;
4149   sip = SeqIdFindBest (bsp->id, 0);
4150   if (sip == NULL) return;
4151   /*
4152   for (j = 1; j <= ipp->count; j++) {
4153     if (SeqIdComp (sip, ipp->sip_list [j]) == SIC_YES) return;
4154   }
4155   */
4156   ipp->count++;
4157   ipp->sip_list [ipp->count] = SeqIdDup (sip);
4158   bsp->idx.scratch = (Pointer) bsp;
4159 }
4160 
FillInProducts(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)4161 static void FillInProducts (SeqEntryPtr sep, Pointer mydata,
4162                             Int4 index, Int2 indent)
4163 
4164 {
4165   BioseqPtr        bsp;
4166   IntervalPagePtr  ipp;
4167   SeqIdPtr         sip;
4168   SeqLocPtr        slp;
4169   ValNode          vn;
4170 
4171   if (sep != NULL && mydata != NULL && sep->choice == 1) {
4172     ipp = (IntervalPagePtr) mydata;
4173     bsp = (BioseqPtr) sep->data.ptrvalue;
4174     if (bsp != NULL) {
4175       if ((ipp->nucsOK && ISA_na (bsp->mol)) ||
4176           (ipp->protsOK && ISA_aa (bsp->mol))) {
4177         AddToSipList (ipp, bsp);
4178       }
4179       if (bsp->repr == Seq_repr_seg && bsp->seq_ext != NULL) {
4180         vn.choice = SEQLOC_MIX;
4181         vn.next = NULL;
4182         vn.data.ptrvalue = bsp->seq_ext;
4183         slp = SeqLocFindNext (&vn, NULL);
4184         while (slp != NULL) {
4185           sip = SeqLocId (slp);
4186           if (sip != NULL) {
4187             bsp = BioseqFindCore (sip);
4188             if (bsp != NULL) {
4189               AddToSipList (ipp, bsp);
4190             } else {
4191               bsp = BioseqLockById (sip);
4192               if (bsp != NULL) {
4193                 AddToSipList (ipp, bsp);
4194                 BioseqUnlock (bsp);
4195               }
4196             }
4197           }
4198           slp = SeqLocFindNext (&vn, slp);
4199         }
4200       }
4201     }
4202   }
4203 }
4204 
SegmentedEntryList(SeqEntryPtr sep,Pointer mydata,SeqEntryFunc mycallback,Int4 index,Int2 indent)4205 static Int4 SegmentedEntryList (SeqEntryPtr sep, Pointer mydata,
4206                                 SeqEntryFunc mycallback,
4207                                 Int4 index, Int2 indent)
4208 
4209 {
4210   BioseqPtr     bsp;
4211   BioseqSetPtr  bssp;
4212   SeqLocPtr     slp;
4213   ValNode       vn;
4214 
4215   if (sep == NULL) return index;
4216   if (IS_Bioseq (sep)) {
4217     if (mycallback != NULL)
4218       (*mycallback) (sep, mydata, index, indent);
4219     bsp = (BioseqPtr) sep->data.ptrvalue;
4220     if (bsp != NULL && bsp->repr == Seq_repr_seg && bsp->seq_ext != NULL) {
4221       vn.choice = SEQLOC_MIX;
4222       vn.next = NULL;
4223       vn.data.ptrvalue = bsp->seq_ext;
4224       slp = SeqLocFindNext (&vn, NULL);
4225       while (slp != NULL) {
4226         index++;
4227         slp = SeqLocFindNext (&vn, slp);
4228       }
4229     }
4230     return index + 1;
4231   }
4232   /*
4233   if (Bioseq_set_class (sep) == 4) return index;
4234   index++;
4235   */
4236   bssp = (BioseqSetPtr) sep->data.ptrvalue;
4237   sep = bssp->seq_set;
4238   indent++;
4239   while (sep != NULL) {
4240     index = SegmentedEntryList (sep, mydata, mycallback, index, indent);
4241     sep = sep->next;
4242   }
4243   return index;
4244 }
4245 
4246 #define SegmentedEntryCount( a )  SegmentedEntryList( a ,NULL,NULL,0,0);
4247 
ENUM_ALIST(strand_alist)4248 static ENUM_ALIST(strand_alist)
4249 {" ",             Seq_strand_unknown},  /* 0 */
4250 {"Plus",          Seq_strand_plus},     /* 1 */
4251 {"Minus",         Seq_strand_minus},    /* 2 */
4252 /*
4253 {"Both",          Seq_strand_both},
4254 {"Reverse",       Seq_strand_both_rev},
4255 */
4256 {"Other",         Seq_strand_other},    /* 255 */
4257 END_ENUM_ALIST
4258 
4259 static Boolean IsSeqIdInValNodeList (SeqIdPtr sip, ValNodePtr list)
4260 {
4261   if (sip == NULL)
4262   {
4263     return FALSE;
4264   }
4265   while (list != NULL)
4266   {
4267     if (SeqIdComp (sip, list->data.ptrvalue) == SIC_YES)
4268     {
4269       return TRUE;
4270     }
4271     list = list->next;
4272   }
4273   return FALSE;
4274 }
4275 
FindLastStopForSeqId(SeqLocPtr slp,SeqIdPtr sip)4276 static Int4 FindLastStopForSeqId (SeqLocPtr slp, SeqIdPtr sip)
4277 {
4278   Int4      last_stop = 0, new_stop;
4279   SeqLocPtr tmp_slp;
4280   SeqIdPtr  tmp_sip;
4281 
4282   tmp_slp = SeqLocFindNext (slp, NULL);
4283   while (tmp_slp != NULL)
4284   {
4285     tmp_sip = SeqLocId (tmp_slp);
4286     if (SeqIdComp (sip, tmp_sip) == SIC_YES)
4287     {
4288       new_stop = SeqLocStop (slp);
4289       if (new_stop > last_stop)
4290       {
4291         last_stop = new_stop;
4292       }
4293     }
4294     tmp_slp = SeqLocFindNext (slp, tmp_slp);
4295   }
4296   return last_stop;
4297 }
4298 
4299 extern void UpdateTagListPopupChoices (DialoG d, Int4 column);
4300 
4301 /* We need to make sure that all IDs in the location are found in the enum list
4302  * for the interval editor ID Enum */
CorrectIntervalEditorSeqIdEnum(IntervalPagePtr ipp,SeqLocPtr slp)4303 static void CorrectIntervalEditorSeqIdEnum (IntervalPagePtr ipp, SeqLocPtr slp)
4304 {
4305   SeqLocPtr           tmp_slp;
4306   SeqIdPtr            sip;
4307   Int4                j = 0;
4308   Boolean             found;
4309   ValNodePtr          missing_list = NULL, missing_vnp;
4310   Int4                new_count;
4311   SeqIdPtr PNTR       new_sip_list;
4312   EnumFieldAssoc PNTR new_alist;
4313   Int4 PNTR           new_lengths;
4314   BioseqPtr           bsp;
4315   Char                str [128];
4316   CharPtr             ptr;
4317 
4318   if (ipp == NULL || slp == NULL)
4319   {
4320     return;
4321   }
4322 
4323   tmp_slp = SeqLocFindNext (slp, NULL);
4324   while (tmp_slp != NULL)
4325   {
4326     sip = SeqLocId (tmp_slp);
4327     if (!IsSeqIdInValNodeList (sip, missing_list))
4328     {
4329       found = FALSE;
4330       for (j = 1; j <= ipp->count && !found; j++)
4331       {
4332         if (SeqIdComp (sip, ipp->sip_list [j]) == SIC_YES)
4333         {
4334           found = TRUE;
4335         }
4336       }
4337       /* this process takes longer, so don't combine it with the above
4338        * loop
4339        */
4340       if (!found)
4341       {
4342         for (j = 1; j <= ipp->count && !found; j++)
4343         {
4344           bsp = BioseqFindCore (ipp->sip_list [j]);
4345           if (bsp == NULL) {
4346             bsp = BioseqLockById (ipp->sip_list [j]);
4347             BioseqUnlock (bsp);
4348           }
4349           if (bsp != NULL && SeqIdIn (sip, bsp->id))
4350           {
4351             found = TRUE;
4352           }
4353         }
4354       }
4355       if (!found)
4356       {
4357         ValNodeAddPointer (&missing_list, 0, sip);
4358       }
4359     }
4360 
4361     tmp_slp = SeqLocFindNext (slp, tmp_slp);
4362   }
4363 
4364   if (missing_list != NULL)
4365   {
4366     new_count = ipp->count + 4 + ValNodeLen (missing_list);
4367     new_sip_list = MemNew (sizeof (SeqIdPtr) * (size_t) new_count);
4368     new_alist = MemNew (sizeof (EnumFieldAssoc) * (size_t) new_count);
4369     new_lengths = MemNew (sizeof (Int4) * (size_t) new_count);
4370     if (ipp->sip_list != NULL) {
4371       /* first one is blank, remainder are actual data */
4372       for (j = 0; j < ipp->count + 1; j++)
4373       {
4374         new_sip_list [j] = ipp->sip_list [j];
4375         ipp->sip_list [j] = NULL;
4376         new_alist [j].name = ipp->alist [j].name;
4377         ipp->alist [j].name = NULL;
4378         new_alist [j].value = ipp->alist [j].value;
4379         new_lengths [j] = ipp->lengths [j];
4380       }
4381     }
4382 
4383     missing_vnp = missing_list;
4384     while (j < new_count - 1 && missing_vnp != NULL)
4385     {
4386       new_sip_list [j] = SeqIdDup (missing_vnp->data.ptrvalue);
4387       new_alist [j].value = j;
4388 
4389       sip = new_sip_list [j];
4390       bsp = BioseqFindCore (sip);
4391       if (bsp == NULL) {
4392         bsp = BioseqLockById (sip);
4393         BioseqUnlock (bsp);
4394       }
4395       if (bsp != NULL)
4396       {
4397         new_lengths [j] = bsp->length;
4398         sip = SeqIdFindWorst (bsp->id);
4399       }
4400       else
4401       {
4402         new_lengths [j] = FindLastStopForSeqId (slp, sip);
4403       }
4404       SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str));
4405       ptr = StringChr (str, '|');
4406       if (ptr == NULL) {
4407         ptr = str;
4408       } else {
4409         ptr++;
4410       }
4411       new_alist [j].name = StringSave (ptr);
4412       missing_vnp = missing_vnp->next;
4413       j++;
4414     }
4415     /* set terminator for enum list */
4416     new_alist [j].name = NULL;
4417     new_alist [j].value = (UIEnum) 0;
4418 
4419     ipp->sip_list = MemFree (ipp->sip_list);
4420     ipp->sip_list = new_sip_list;
4421     ipp->alist = MemFree (ipp->alist);
4422     ipp->alist = new_alist;
4423     ipp->lengths = MemFree (ipp->lengths);
4424     ipp->lengths = new_lengths;
4425     ipp->count = j;
4426 
4427     ipp->alists [ipp->seqid_col] = ipp->alist;
4428     UpdateTagListPopupChoices (ipp->ivals, ipp->seqid_col);
4429   }
4430   missing_list = ValNodeFree (missing_list);
4431 }
4432 
4433 static void
BuildIntervalString(IntervalPagePtr ipp,CharPtr fuzz_from_ch,Int4 start,CharPtr fuzz_to_ch,Int4 stop,Uint2 strand,Int4 seq,Int4 salp_num,Boolean isInterval,Boolean isPoint,CharPtr buf,Int4 buf_len)4434 BuildIntervalString
4435 (IntervalPagePtr ipp,
4436  CharPtr         fuzz_from_ch,
4437  Int4            start,
4438  CharPtr         fuzz_to_ch,
4439  Int4            stop,
4440  Uint2           strand,
4441  Int4            seq,
4442  Int4            salp_num,
4443  Boolean         isInterval,
4444  Boolean         isPoint,
4445  CharPtr         buf,
4446  Int4            buf_len)
4447 {
4448   CharPtr cp;
4449   Boolean need_tab = FALSE;
4450 
4451   if (ipp == NULL || fuzz_from_ch == NULL || fuzz_to_ch == NULL || buf == NULL || buf_len == 0)
4452   {
4453     return;
4454   }
4455 
4456   MemSet (buf, 0, buf_len);
4457 
4458   if (isInterval)
4459   {
4460     sprintf (buf, "%s%ld\t%s%ld",
4461              fuzz_from_ch, (long) (start + 1),
4462              fuzz_to_ch, (long) (stop + 1));
4463     need_tab = TRUE;
4464   }
4465   else if (isPoint)
4466   {
4467     sprintf (buf, "%ld%s\t%ld%s",
4468              (long) (start + 1), fuzz_from_ch,
4469              (long) (stop + 1), fuzz_to_ch);
4470     need_tab = TRUE;
4471   }
4472 
4473   cp = buf + StringLen (buf);
4474   if (ipp->strand_col > -1)
4475   {
4476     if (need_tab)
4477     {
4478       StringCat (cp, "\t");
4479       cp++;
4480     }
4481     sprintf (cp, "%d", (int) strand);
4482     need_tab = TRUE;
4483     cp += StringLen (cp);
4484   }
4485 
4486   if (ipp->seqid_col > -1)
4487   {
4488     if (need_tab)
4489     {
4490       StringCat (cp, "\t");
4491       cp++;
4492     }
4493     sprintf (cp, "%d", (int) seq);
4494     need_tab = TRUE;
4495     cp += StringLen (cp);
4496   }
4497 
4498   if (ipp->aln_col > -1)
4499   {
4500     if (need_tab)
4501     {
4502       StringCat (cp, "\t");
4503       cp++;
4504     }
4505     sprintf (cp, "%d", (int) salp_num);
4506     need_tab = TRUE;
4507     cp += StringLen (cp);
4508   }
4509   StringCat (cp, "\n");
4510 }
4511 
SeqLocPtrToIntervalPage(DialoG d,Pointer data)4512 static void SeqLocPtrToIntervalPage (DialoG d, Pointer data)
4513 
4514 {
4515   BioseqPtr        bsp;
4516   SeqLocPtr        firstSlp;
4517   Char             fuzz_from_ch [4];
4518   Char             fuzz_to_ch [4];
4519   ValNodePtr       head;
4520   SeqIdPtr         id;
4521   IntFuzzPtr       ifp;
4522   IntervalPagePtr  ipp;
4523   Boolean          isInterval;
4524   Boolean          isPoint;
4525   Int2             j;
4526   SeqLocPtr        lastSlp;
4527   SeqLocPtr        location;
4528   SeqLocPtr        next;
4529   SeqEntryPtr      oldscope;
4530   Boolean          partial5;
4531   Boolean          partial3;
4532   Int2             seq;
4533   SeqIntPtr        sip;
4534   SeqLocPtr        slp;
4535   SeqPntPtr        spp;
4536   Int4             start;
4537   Int4             stop;
4538   Char             str [255];
4539   Uint1            strand, aln_strand;
4540   TagListPtr       tlp;
4541   ValNodePtr       vnp;
4542   Int4             salp_num, salp_row;
4543   SeqIdPtr         tmp_sip, bsp_id;
4544 
4545   ipp = (IntervalPagePtr) GetObjectExtra (d);
4546   if (ipp == NULL) return;
4547   SafeSetStatus (ipp->partial5, FALSE);
4548   SafeSetStatus (ipp->partial3, FALSE);
4549   tlp = GetObjectExtra (ipp->ivals);
4550   if (tlp == NULL) return;
4551 
4552   location = (SeqLocPtr) data;
4553   partial5 = FALSE;
4554   partial3 = FALSE;
4555   head = NULL;
4556 
4557   if (location == NULL)
4558   {
4559       if (ipp->count == 1)
4560       {
4561        sprintf (str, "\t\t\t1\n");
4562        vnp = ValNodeNew (head);
4563        if (head == NULL) {
4564          head = vnp;
4565        }
4566        if (vnp != NULL) {
4567          vnp->data.ptrvalue = StringSave (str);
4568        }
4569       }
4570   }
4571   if (location != NULL) {
4572     CorrectIntervalEditorSeqIdEnum (ipp, location);
4573     firstSlp = NULL;
4574     lastSlp = NULL;
4575     slp = SeqLocFindNext (location, NULL);
4576     while (slp != NULL) {
4577       if (firstSlp == NULL) {
4578         firstSlp = slp;
4579       }
4580       lastSlp = slp;
4581       next = SeqLocFindNext (location, slp);
4582       if (slp->choice == SEQLOC_NULL) {
4583         SafeSetStatus (ipp->nullsBetween, TRUE);
4584         SafeShow (ipp->nullsBetween);
4585       } else {
4586         id = SeqLocId (slp);
4587         if (id != NULL) {
4588           bsp = BioseqFind (id);
4589           if (bsp == NULL) {
4590             oldscope = SeqEntrySetScope (NULL);
4591             if (oldscope != NULL) {
4592               bsp = BioseqFind (id);
4593               SeqEntrySetScope (oldscope);
4594             }
4595           }
4596           isInterval = TRUE;
4597           isPoint = FALSE;
4598           StringCpy (fuzz_from_ch, "");
4599           StringCpy (fuzz_to_ch, "");
4600           if (bsp == NULL) {
4601             start = SeqLocStart (slp);
4602             stop = SeqLocStop (slp);
4603           }
4604           else
4605           {
4606             start = GetOffsetInBioseq (slp, bsp, SEQLOC_START);
4607             stop = GetOffsetInBioseq (slp, bsp, SEQLOC_STOP);
4608           }
4609           if (start == stop && slp->choice == SEQLOC_PNT) {
4610             spp = (SeqPntPtr) slp->data.ptrvalue;
4611             if (spp != NULL) {
4612               ifp = spp->fuzz;
4613               if (ifp != NULL && ifp->choice == 4 && ifp->a ==  3) {
4614                 isInterval = FALSE;
4615                 isPoint = TRUE;
4616                 StringCpy (fuzz_from_ch, "^");
4617                 /* start--; */  /* compensate for other fix */
4618                 stop++; /* compensate for other fix */
4619               }
4620             }
4621           }
4622           strand = SeqLocStrand (slp);
4623           if (strand > Seq_strand_both_rev && strand != Seq_strand_other) {
4624             strand = Seq_strand_unknown;
4625           }
4626           /*
4627           if (strand == Seq_strand_unknown) {
4628             strand = Seq_strand_plus;
4629           }
4630           */
4631           if (! ipp->nucsOK) {
4632             strand = 0;
4633           }
4634           seq = 0;
4635           if (ipp->sip_list != NULL && bsp != NULL) {
4636             for (j = 1; j <= ipp->count && seq == 0; j++) {
4637               if (SeqIdComp (SeqIdFindBest (bsp->id, 0), ipp->sip_list[j]) == SIC_YES) {
4638                 seq = j;
4639               }
4640             }
4641           }
4642 
4643           salp_num = 0;
4644           salp_row = 0;
4645           if (seq > 0 && ipp->salp_list != NULL)
4646           {
4647             salp_num = 1;
4648             while (salp_num <= ipp->aln_count
4649                    && salp_row == 0)
4650             {
4651               tmp_sip = SeqIdPtrFromSeqAlign (ipp->salp_list [salp_num]);
4652               bsp = BioseqFind (ipp->sip_list [seq]);
4653               if (bsp != NULL)
4654               {
4655                 for (bsp_id = bsp->id;
4656                      bsp_id != NULL && salp_row == 0;
4657                      bsp_id = bsp_id->next)
4658                 {
4659                   salp_row = SeqIdOrderInBioseqIdList(bsp_id, tmp_sip);
4660                 }
4661               }
4662               if (salp_row < 1)
4663               {
4664                 salp_num++;
4665               }
4666             }
4667             if (salp_row < 1)
4668             {
4669               salp_num = 0;
4670             }
4671             else
4672             {
4673               start = AlnMgr2MapBioseqToSeqAlign(ipp->salp_list [salp_num], start, salp_row);
4674               stop = AlnMgr2MapBioseqToSeqAlign(ipp->salp_list [salp_num], stop, salp_row);
4675               aln_strand = AlnMgr2GetNthStrand (ipp->salp_list [salp_num], salp_row);
4676               /* if reverse strand in alignment, reverse strand for location */
4677               if (aln_strand == Seq_strand_minus)
4678               {
4679                 if (strand == Seq_strand_minus)
4680                 {
4681                   strand = Seq_strand_plus;
4682                 }
4683                 else if (strand == Seq_strand_plus)
4684                 {
4685                   strand = Seq_strand_minus;
4686                 }
4687               }
4688             }
4689           }
4690 
4691           BuildIntervalString (ipp, fuzz_from_ch, start, fuzz_to_ch, stop,
4692                                strand, seq, salp_num, isInterval, isPoint,
4693                                str, sizeof (str));
4694           vnp = ValNodeNew (head);
4695           if (head == NULL) {
4696             head = vnp;
4697           }
4698           if (vnp != NULL) {
4699             vnp->data.ptrvalue = StringSave (str);
4700           }
4701         }
4702       }
4703       slp = next;
4704     }
4705     if (firstSlp != NULL) {
4706       if (firstSlp->choice == SEQLOC_INT && firstSlp->data.ptrvalue != NULL) {
4707         sip = (SeqIntPtr) firstSlp->data.ptrvalue;
4708         if (sip->strand == Seq_strand_minus || sip->strand == Seq_strand_both_rev) {
4709           ifp = sip->if_to;
4710           if (ifp != NULL && ifp->choice == 4 && ifp->a == 1) {
4711             partial5 = TRUE;
4712           }
4713         } else {
4714           ifp = sip->if_from;
4715           if (ifp != NULL && ifp->choice == 4 && ifp->a == 2) {
4716             partial5 = TRUE;
4717           }
4718         }
4719       } else if (firstSlp->choice == SEQLOC_PNT && firstSlp->data.ptrvalue != NULL) {
4720         spp = (SeqPntPtr) firstSlp->data.ptrvalue;
4721         if (spp->strand == Seq_strand_minus || spp->strand == Seq_strand_both_rev) {
4722           ifp = spp->fuzz;
4723           if (ifp != NULL && ifp->choice == 4 && ifp->a == 1) {
4724             partial5 = TRUE;
4725           }
4726         } else {
4727           ifp = spp->fuzz;
4728           if (ifp != NULL && ifp->choice == 4 && ifp->a == 2) {
4729             partial5 = TRUE;
4730           }
4731         }
4732       }
4733     }
4734     if (lastSlp != NULL) {
4735       if (lastSlp->choice == SEQLOC_INT && lastSlp->data.ptrvalue != NULL) {
4736         sip = (SeqIntPtr) lastSlp->data.ptrvalue;
4737         if (sip->strand == Seq_strand_minus || sip->strand == Seq_strand_both_rev) {
4738           ifp = sip->if_from;
4739           if (ifp != NULL && ifp->choice == 4 && ifp->a == 2) {
4740             partial3 = TRUE;
4741           }
4742         } else {
4743           ifp = sip->if_to;
4744           if (ifp != NULL && ifp->choice == 4 && ifp->a == 1) {
4745             partial3 = TRUE;
4746           }
4747         }
4748       } else if (lastSlp->choice == SEQLOC_PNT && lastSlp->data.ptrvalue != NULL) {
4749         spp = (SeqPntPtr) lastSlp->data.ptrvalue;
4750         if (spp->strand == Seq_strand_minus || spp->strand == Seq_strand_both_rev) {
4751           ifp = spp->fuzz;
4752           if (ifp != NULL && ifp->choice == 4 && ifp->a == 2) {
4753             partial3 = TRUE;
4754           }
4755         } else {
4756           ifp = spp->fuzz;
4757           if (ifp != NULL && ifp->choice == 4 && ifp->a == 1) {
4758             partial3 = TRUE;
4759           }
4760         }
4761       }
4762     }
4763   }
4764   SafeSetStatus (ipp->partial5, partial5);
4765   SafeSetStatus (ipp->partial3, partial3);
4766 
4767   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
4768   tlp->vnp = head;
4769   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
4770   for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
4771   }
4772   tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
4773   CorrectBarMax (tlp->bar, tlp->max);
4774   CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
4775 }
4776 
SetSequenceAndStrandForIntervalPage(DialoG d)4777 extern void SetSequenceAndStrandForIntervalPage (DialoG d)
4778 {
4779   SendMessageToDialog (d, NUM_VIB_MSG + 1);
4780 }
4781 
4782 static Boolean
ReadFromValueFromDialogLine(CharPtr line,Int4Ptr p_from_val,BoolPtr fuzz_after)4783 ReadFromValueFromDialogLine
4784 (CharPtr line,
4785  Int4Ptr p_from_val,
4786  BoolPtr fuzz_after)
4787 {
4788   CharPtr txt, ptr;
4789   Int4    len;
4790   Boolean okay;
4791   Int4    val;
4792   Int4    j;
4793   Char    ch;
4794 
4795   if (p_from_val == NULL || fuzz_after == NULL || StringHasNoText (line))
4796   {
4797     return FALSE;
4798   }
4799 
4800   txt = ExtractTagListColumn (line, 0);
4801   okay = FALSE;
4802   len = StringLen (txt);
4803   for (j = 0; j < len; j++) {
4804     ch = txt [j];
4805     if (ch != ' ' && ch != '\t' && ch != '\n') {
4806       okay = TRUE;
4807     }
4808   }
4809   if (okay) {
4810     *fuzz_after = FALSE;
4811     *p_from_val = 0;
4812 
4813     ptr = StringChr (txt, '<');
4814     if (ptr != NULL) {
4815       *ptr = ' ';
4816     }
4817     ptr = StringChr (txt, '>');
4818     if (ptr != NULL) {
4819       *ptr = ' ';
4820     }
4821     ptr = StringChr (txt, '^');
4822     if (ptr != NULL) {
4823       *fuzz_after = TRUE;
4824       *ptr = ' ';
4825     }
4826     TrimSpacesAroundString (txt);
4827     if (StrToLong (txt, &val)) {
4828       *p_from_val = val;
4829     } else {
4830       okay = FALSE;
4831     }
4832   } else {
4833     okay = FALSE;
4834   }
4835   MemFree (txt);
4836   return okay;
4837 }
4838 
4839 static Boolean
ReadToValueFromDialogLine(CharPtr line,Int4Ptr p_to_val,Int4Ptr p_from_val,BoolPtr fuzz_after,BoolPtr isInterval,BoolPtr isPoint,Boolean partial5,Boolean partial3)4840 ReadToValueFromDialogLine
4841 (CharPtr line,
4842  Int4Ptr p_to_val,
4843  Int4Ptr p_from_val,
4844  BoolPtr fuzz_after,
4845  BoolPtr isInterval,
4846  BoolPtr isPoint,
4847  Boolean partial5,
4848  Boolean partial3)
4849 {
4850   CharPtr txt, ptr;
4851   Int4    val, tmp;
4852   Boolean okay = TRUE;
4853 
4854   if (p_to_val == NULL || p_from_val == NULL || fuzz_after == NULL
4855       || isInterval == NULL || isPoint == NULL)
4856   {
4857     return FALSE;
4858   }
4859 
4860   *p_to_val = 0;
4861 
4862   txt = ExtractTagListColumn (line, 1);
4863   if (! StringHasNoText (txt)) {
4864     ptr = StringChr (txt, '<');
4865     if (ptr != NULL) {
4866       *ptr = ' ';
4867     }
4868     ptr = StringChr (txt, '>');
4869     if (ptr != NULL) {
4870       *ptr = ' ';
4871     }
4872     ptr = StringChr (txt, '^');
4873     if (ptr != NULL) {
4874       *fuzz_after = TRUE;
4875       *ptr = ' ';
4876     }
4877     TrimSpacesAroundString (txt);
4878     if (StrToLong (txt, &val)) {
4879       *p_to_val = val;
4880       if (*fuzz_after && *p_to_val == *p_from_val + 1) {
4881         *isInterval = FALSE;
4882         *isPoint = TRUE;
4883         /* from++; */ /* this was causing point to be thrown off */
4884       } else if (*p_to_val == *p_from_val && (! partial5) && (! partial3)) {
4885         *isInterval = FALSE;
4886         *isPoint = TRUE;
4887       }
4888     } else {
4889       okay = FALSE;
4890     }
4891   } else {
4892     /*
4893     okay = FALSE;
4894     */
4895     *isInterval = FALSE;
4896     *isPoint = TRUE;
4897     *p_to_val = *p_from_val;
4898   }
4899   MemFree (txt);
4900 
4901   if (okay && *isInterval) {
4902     if (*p_from_val > *p_to_val) {
4903       tmp = *p_from_val;
4904       *p_from_val = *p_to_val;
4905       *p_to_val = tmp;
4906     }
4907   }
4908 
4909 
4910   return okay;
4911 }
4912 
4913 static Boolean
ReadStrandFromDialogLine(CharPtr line,Int4 strand_col,Uint2Ptr p_strand_val,Uint2Ptr p_prev_strand_val)4914 ReadStrandFromDialogLine
4915 (CharPtr  line,
4916  Int4     strand_col,
4917  Uint2Ptr p_strand_val,
4918  Uint2Ptr p_prev_strand_val)
4919 {
4920   CharPtr txt;
4921   Int2    val2;
4922 
4923   if (p_strand_val == NULL
4924       || p_prev_strand_val == NULL)
4925   {
4926     return FALSE;
4927   }
4928 
4929   *p_strand_val = Seq_strand_unknown;
4930   if (strand_col > -1) {
4931     txt = ExtractTagListColumn (line, strand_col);
4932     if (txt != NULL && StrToInt (txt, &val2)) {
4933       *p_strand_val = val2;
4934       if (*p_strand_val > Seq_strand_both_rev) {
4935         *p_strand_val = Seq_strand_other;
4936       }
4937       *p_prev_strand_val = *p_strand_val;
4938     } else {
4939       *p_strand_val = *p_prev_strand_val;
4940     }
4941     MemFree (txt);
4942   }
4943   if (*p_strand_val == Seq_strand_unknown) {
4944     *p_strand_val = Seq_strand_plus;
4945   }
4946   return TRUE;
4947 }
4948 
4949 static Boolean
ReadSeqIdFromDialogLine(CharPtr line,Int4 seqid_col,SeqIdPtr PNTR p_sip_val,SeqIdPtr PNTR p_prev_sip_val,SeqIdPtr PNTR sip_list,Int4 sip_count)4950 ReadSeqIdFromDialogLine
4951 (CharPtr       line,
4952  Int4          seqid_col,
4953  SeqIdPtr PNTR p_sip_val,
4954  SeqIdPtr PNTR p_prev_sip_val,
4955  SeqIdPtr PNTR sip_list,
4956  Int4          sip_count)
4957 {
4958   CharPtr txt;
4959   Int2    val2;
4960   Boolean okay = TRUE;
4961 
4962   if (p_sip_val == NULL || p_prev_sip_val == NULL
4963       || sip_count == 0 || sip_list == NULL
4964       || seqid_col < 0)
4965   {
4966     return FALSE;
4967   }
4968   *p_sip_val = NULL;
4969   txt = ExtractTagListColumn (line, seqid_col);
4970   if (txt != NULL) {
4971     if (! StrToInt (txt, &val2) || val2 <= 0)
4972     {
4973       if (*p_prev_sip_val != NULL)
4974       {
4975         *p_sip_val = *p_prev_sip_val;
4976       }
4977       else
4978       {
4979         okay = FALSE;
4980       }
4981     }
4982     else if (val2 <= sip_count)
4983     {
4984       *p_sip_val = sip_list [val2];
4985       *p_prev_sip_val = *p_sip_val;
4986     } else {
4987       okay = FALSE;
4988     }
4989   }
4990   else
4991   {
4992     okay = FALSE;
4993   }
4994   MemFree (txt);
4995   return okay;
4996 }
4997 
4998 static Boolean
ReadSeqAlignFromDialogLine(CharPtr line,Int4 aln_col,SeqAlignPtr PNTR p_salp_val,SeqAlignPtr PNTR p_prev_salp_val,SeqAlignPtr PNTR salp_list,Int4 salp_count)4999 ReadSeqAlignFromDialogLine
5000 (CharPtr          line,
5001  Int4             aln_col,
5002  SeqAlignPtr PNTR p_salp_val,
5003  SeqAlignPtr PNTR p_prev_salp_val,
5004  SeqAlignPtr PNTR salp_list,
5005  Int4             salp_count)
5006 {
5007   CharPtr txt;
5008   Int2    val2;
5009   Boolean okay = TRUE;
5010 
5011   if (p_salp_val == NULL || p_prev_salp_val == NULL
5012       || salp_count == 0 || salp_list == NULL
5013       || aln_col < 0)
5014   {
5015     return FALSE;
5016   }
5017 
5018   txt = ExtractTagListColumn (line, aln_col);
5019   if (txt != NULL) {
5020     if (! StrToInt (txt, &val2) || val2 <= 0)
5021     {
5022       if (*p_prev_salp_val != NULL)
5023       {
5024         *p_salp_val = *p_prev_salp_val;
5025       }
5026       else
5027       {
5028         okay = FALSE;
5029       }
5030     }
5031     else if (val2 <= salp_count)
5032     {
5033       *p_salp_val = salp_list [val2];
5034       *p_prev_salp_val = *p_salp_val;
5035     } else {
5036       okay = FALSE;
5037     }
5038   }
5039   else
5040   {
5041     if (*p_prev_salp_val == NULL)
5042     {
5043       okay = FALSE;
5044     }
5045     else
5046     {
5047       *p_salp_val = *p_prev_salp_val;
5048     }
5049  }
5050  MemFree (txt);
5051  return okay;
5052 }
5053 
5054 static Boolean
GetBioseqAlignmentRow(SeqAlignPtr salp,BioseqPtr bsp,Int4Ptr aln_row)5055 GetBioseqAlignmentRow
5056 (SeqAlignPtr salp,
5057  BioseqPtr   bsp,
5058  Int4Ptr     aln_row)
5059 {
5060   SeqIdPtr  tmp_sip, bsp_id;
5061   if (salp == NULL || bsp == NULL || aln_row == NULL)
5062   {
5063     return FALSE;
5064   }
5065 
5066   *aln_row = 0;
5067 
5068   tmp_sip = SeqIdPtrFromSeqAlign (salp);
5069 
5070   for (bsp_id = bsp->id;
5071        bsp_id != NULL && *aln_row == 0;
5072        bsp_id = bsp_id->next)
5073   {
5074     *aln_row = SeqIdOrderInBioseqIdList(bsp_id, tmp_sip);
5075   }
5076   if (*aln_row < 1)
5077   {
5078     return FALSE;
5079   }
5080   else
5081   {
5082     return TRUE;
5083   }
5084 }
5085 
5086 static void
ListAlignmentsThatContainSequence(SeqAlignPtr PNTR salp_list,Int4 salp_count,BioseqPtr bsp,SeqIdPtr sip,ValNodePtr PNTR head)5087 ListAlignmentsThatContainSequence
5088 (SeqAlignPtr PNTR salp_list,
5089  Int4        salp_count,
5090  BioseqPtr   bsp,
5091  SeqIdPtr    sip,
5092  ValNodePtr  PNTR head)
5093 {
5094   Int4       i;
5095   Char       str [34];
5096   Char       id_label [128];
5097   Int4       aln_row;
5098   ValNodePtr good_aln = NULL;
5099   CharPtr    none_found_fmt = "%s is not found in any alignments";
5100   CharPtr    one_found_fmt = "%s is found in %s";
5101   CharPtr    some_found_fmt = "%s is found in the following alignments";
5102   CharPtr    err_msg;
5103   CharPtr    cp;
5104 
5105   if (head == NULL || bsp == NULL || sip == NULL)
5106   {
5107     return;
5108   }
5109   SeqIdWrite (sip, id_label, PRINTID_REPORT, sizeof (id_label));
5110 
5111   /* indent the names of the alignments */
5112   str [0] = ' ';
5113   str [1] = ' ';
5114   str [2] = ' ';
5115   str [3] = ' ';
5116   for (i = 0; i < salp_count; i++)
5117   {
5118     if (GetBioseqAlignmentRow (salp_list [i], bsp, &aln_row))
5119     {
5120       CreateSeqAlignLabel (salp_list [i], str + 4, sizeof (str) - 4);
5121       ValNodeAddPointer (&good_aln, 0, StringSave (str));
5122     }
5123   }
5124   if (good_aln == NULL)
5125   {
5126     err_msg = (CharPtr) MemNew ((StringLen (none_found_fmt) + StringLen (id_label))
5127                                 * sizeof (Char));
5128     if (err_msg != NULL)
5129     {
5130       sprintf (err_msg, none_found_fmt, id_label);
5131       ValNodeAddPointer (head, 0, err_msg);
5132     }
5133   }
5134   else if (good_aln->next == NULL)
5135   {
5136     err_msg = (CharPtr) MemNew ((StringLen (one_found_fmt)
5137                                  + StringLen (id_label)
5138                                  + StringLen (good_aln->data.ptrvalue))
5139                                 * sizeof (Char));
5140     if (err_msg != NULL)
5141     {
5142       cp = (CharPtr) good_aln->data.ptrvalue;
5143       /* skip over indented space */
5144       cp += 4;
5145       sprintf (err_msg, one_found_fmt, id_label, cp);
5146       ValNodeAddPointer (head, 0, err_msg);
5147       good_aln = ValNodeFreeData (good_aln);
5148     }
5149   }
5150   else
5151   {
5152     err_msg = (CharPtr) MemNew ((StringLen (some_found_fmt)
5153                                  + StringLen (id_label))
5154                                 * sizeof (Char));
5155     if (err_msg != NULL)
5156     {
5157       sprintf (err_msg, some_found_fmt, id_label);
5158       ValNodeAddPointer (head, 0, err_msg);
5159       ValNodeLink (head, good_aln);
5160     }
5161   }
5162 }
5163 
5164 static void
ListSequencesInAlignment(SeqIdPtr PNTR sip_list,Int4 sip_count,SeqAlignPtr salp,ValNodePtr PNTR head)5165 ListSequencesInAlignment
5166 (SeqIdPtr    PNTR sip_list,
5167  Int4        sip_count,
5168  SeqAlignPtr salp,
5169  ValNodePtr  PNTR head)
5170 {
5171   SeqIdPtr   tmp_sip, aln_id;
5172   BioseqPtr  bsp;
5173   Int4       i;
5174   Boolean    found;
5175   Char       id_label [128];
5176 
5177   if (salp == NULL || head == NULL)
5178   {
5179     return;
5180   }
5181 
5182   tmp_sip = SeqIdPtrFromSeqAlign (salp);
5183   if (tmp_sip == NULL)
5184   {
5185     ValNodeAddPointer (head, 0, StringSave ("Selected alignment contains no sequences"));
5186     return;
5187   }
5188   /* indent list of sequence IDs */
5189   id_label [0] = ' ';
5190   id_label [1] = ' ';
5191   id_label [2] = ' ';
5192   id_label [3] = ' ';
5193   ValNodeAddPointer (head, 0, StringSave ("The selected alignment contains the following sequences:"));
5194   for (aln_id = tmp_sip; aln_id != NULL; aln_id = aln_id->next)
5195   {
5196     bsp = BioseqFind (aln_id);
5197     if (bsp == NULL)
5198     {
5199       continue;
5200     }
5201     found = FALSE;
5202     for (i = 0; i < sip_count && ! found; i++)
5203     {
5204       if (SeqIdIn (sip_list [i], bsp->id))
5205       {
5206         SeqIdWrite (sip_list [i], id_label + 4, PRINTID_REPORT, sizeof (id_label) - 4);
5207         ValNodeAddPointer (head, 0, StringSave (id_label));
5208         found = TRUE;
5209       }
5210     }
5211   }
5212 }
5213 
AdjustFromForGap(Int4Ptr p_from,SeqAlignPtr salp,Int4 aln_len,Int4 aln_row)5214 extern Boolean AdjustFromForGap (Int4Ptr p_from, SeqAlignPtr salp, Int4 aln_len, Int4 aln_row)
5215 {
5216   Int4 aln_from, aln_offset = 0;
5217 
5218   if (p_from == NULL || salp == NULL || aln_len == 0 || aln_row == 0
5219       || *p_from < 1)
5220   {
5221     return FALSE;
5222   }
5223 
5224   aln_from = AlnMgr2MapSeqAlignToBioseq(salp, (*p_from) - 1, aln_row);
5225 
5226   while (aln_from == -2 && (*p_from) + aln_offset < aln_len)
5227   {
5228     aln_offset ++;
5229     aln_from = AlnMgr2MapSeqAlignToBioseq(salp, (*p_from) + aln_offset - 1, aln_row);
5230   }
5231   if (aln_from < 0)
5232   {
5233     return FALSE;
5234   }
5235   else
5236   {
5237     *p_from = aln_from + 1;
5238     return TRUE;
5239   }
5240 }
5241 
AdjustToForGap(Int4Ptr p_to,SeqAlignPtr salp,Int4 aln_row)5242 extern Boolean AdjustToForGap (Int4Ptr p_to, SeqAlignPtr salp, Int4 aln_row)
5243 {
5244   Int4 aln_to, aln_offset = 0;
5245 
5246   if (p_to == NULL || salp == NULL || aln_row == 0
5247       || *p_to < 1)
5248   {
5249     return FALSE;
5250   }
5251 
5252   aln_to = AlnMgr2MapSeqAlignToBioseq(salp, (*p_to) - 1, aln_row);
5253   aln_offset = 0;
5254   while (aln_to == -2 && (*p_to) - 1 - aln_offset >= 0)
5255   {
5256     aln_offset ++;
5257     aln_to = AlnMgr2MapSeqAlignToBioseq(salp, (*p_to) - 1 - aln_offset, aln_row);
5258   }
5259   if (aln_to < 0)
5260   {
5261     return FALSE;
5262   }
5263   else
5264   {
5265     *p_to = aln_to + 1;
5266     return TRUE;
5267   }
5268 }
5269 
AdjustStrandForAlignment(Uint2Ptr p_strand,SeqAlignPtr salp,Int4 aln_row)5270 static Boolean AdjustStrandForAlignment (Uint2Ptr p_strand, SeqAlignPtr salp, Int4 aln_row)
5271 {
5272   Uint2 aln_strand;
5273 
5274   if (p_strand == NULL || salp == NULL || aln_row < 1)
5275   {
5276     return FALSE;
5277   }
5278 
5279   aln_strand = AlnMgr2GetNthStrand (salp, aln_row);
5280   if (aln_strand == Seq_strand_minus)
5281   {
5282     /* if alignment strand is minus, reverse strand of location */
5283     if (*p_strand == Seq_strand_minus)
5284     {
5285       *p_strand = Seq_strand_plus;
5286     }
5287     else if (*p_strand == Seq_strand_plus)
5288     {
5289       *p_strand = Seq_strand_minus;
5290     }
5291   }
5292   return TRUE;
5293 }
5294 
CoordinatesValidForBioseq(Int4 from,Int4 to,BioseqPtr bsp)5295 static Boolean CoordinatesValidForBioseq (Int4 from, Int4 to, BioseqPtr bsp)
5296 {
5297   if (bsp == NULL || from < 1 || to > bsp->length)
5298   {
5299     return FALSE;
5300   }
5301   else
5302   {
5303     return TRUE;
5304   }
5305 }
5306 
TestIntervalEditor(DialoG d)5307 static ValNodePtr TestIntervalEditor (DialoG d)
5308 {
5309   IntervalPagePtr  ipp;
5310   TagListPtr       tlp;
5311   ValNodePtr       head = NULL, vnp;
5312   Boolean          from_ok, to_ok, seqid_ok, salp_ok;
5313   Boolean          partial5, partial3;
5314   Int4             to, from, aln_row;
5315   Int4             interval_num;
5316   Uint2            strand, prev_strand = Seq_strand_unknown;
5317   SeqIdPtr         seqid, prev_seqid = NULL;
5318   SeqAlignPtr      salp, prev_salp = NULL;
5319   Char             err_msg[200];
5320   BioseqPtr        bsp = NULL;
5321   Int4             aln_len;
5322   Boolean          isInterval, isPoint, fuzz_before, fuzz_after;
5323   Int2             fuzz_from;
5324   Int2             fuzz_to;
5325 
5326   ipp = (IntervalPagePtr) GetObjectExtra (d);
5327   if (ipp == NULL)
5328   {
5329     ValNodeAddPointer (&head, 0, StringSave ("No dialog data"));
5330     return head;
5331   }
5332 
5333   tlp = GetObjectExtra (ipp->ivals);
5334   if (tlp == NULL)
5335   {
5336     ValNodeAddPointer (&head, 0, StringSave ("No dialog data"));
5337     return head;
5338   }
5339 
5340   if (tlp->vnp == NULL)
5341   {
5342     ValNodeAddPointer (&head, 0, StringSave ("No location intervals listed!"));
5343   }
5344 
5345   partial5 = GetStatus (ipp->partial5);
5346   partial3 = GetStatus (ipp->partial3);
5347 
5348   for (vnp = tlp->vnp, interval_num = 1;
5349        vnp != NULL;
5350        vnp = vnp->next, interval_num++) {
5351     isInterval = TRUE;
5352     isPoint = FALSE;
5353     fuzz_from = -1;
5354     fuzz_to = -1;
5355     fuzz_before = FALSE;
5356     fuzz_after = FALSE;
5357     from = 0;
5358     to = 0;
5359 
5360     from_ok = ReadFromValueFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5361                                            &from, &fuzz_after);
5362     if (!from_ok)
5363     {
5364       /* we'll silently ignore lines that have no from value */
5365       continue;
5366     }
5367 
5368     to_ok = ReadToValueFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5369                                          &to, &from, &fuzz_after, &isInterval, &isPoint,
5370                                          partial5, partial3);
5371     if (!to_ok)
5372     {
5373       sprintf (err_msg, "Bad to value in interval %d", interval_num);
5374       ValNodeAddPointer (&head, 0, StringSave ("err_msg"));
5375     }
5376     strand = Seq_strand_unknown;
5377     ReadStrandFromDialogLine (vnp->data.ptrvalue, ipp->strand_col,
5378                               &strand, &prev_strand);
5379 
5380     seqid_ok = ReadSeqIdFromDialogLine (vnp->data.ptrvalue, ipp->seqid_col,
5381                                          &seqid, &prev_seqid,
5382                                          ipp->sip_list, ipp->count);
5383     if (seqid_ok)
5384     {
5385       bsp = BioseqFind (seqid);
5386       if (bsp == NULL)
5387       {
5388         sprintf (err_msg, "Can't find bioseq for interval %d", interval_num);
5389         ValNodeAddPointer (&head, 0, StringSave (err_msg));
5390         seqid_ok = FALSE;
5391       }
5392     }
5393     else
5394     {
5395       sprintf (err_msg, "No sequence ID in interval %d", interval_num);
5396       ValNodeAddPointer (&head, 0, StringSave (err_msg));
5397     }
5398 
5399 
5400     /* get SeqAlign */
5401     salp = NULL;
5402     if (ipp->salp_list == NULL)
5403     {
5404       salp_ok = TRUE;
5405       if (bsp != NULL)
5406       {
5407         if (!CoordinatesValidForBioseq (from, to, bsp))
5408         {
5409           sprintf (err_msg, "Coordinates for interval %d are not in sequence (1-%d)",
5410                    interval_num, bsp->length);
5411           ValNodeAddPointer (&head, 0, StringSave (err_msg));
5412         }
5413       }
5414     }
5415     else
5416     {
5417       salp_ok = ReadSeqAlignFromDialogLine (vnp->data.ptrvalue,
5418                                             ipp->aln_col,
5419                                             &salp, &prev_salp,
5420                                             ipp->salp_list,
5421                                             ipp->aln_count);
5422       if (!salp_ok)
5423       {
5424         sprintf (err_msg, "No alignment for interval %d", interval_num);
5425         ValNodeAddPointer (&head, 0, StringSave (err_msg));
5426       }
5427 
5428       if (salp_ok && seqid_ok)
5429       {
5430         aln_row = 0;
5431         if (GetBioseqAlignmentRow (salp, bsp, &aln_row))
5432         {
5433           aln_len = SeqAlignLength (salp);
5434           if (from < 1 || to > aln_len)
5435           {
5436             sprintf (err_msg, "Coordinates for interval %d are not in alignment interval (%d-%d)",
5437                      interval_num, 1, aln_len);
5438             ValNodeAddPointer (&head, 0, StringSave (err_msg));
5439           }
5440           else
5441           {
5442             /* check for locations in gaps */
5443             if (!AdjustFromForGap (&from, salp, aln_len, aln_row)
5444                 || ! AdjustToForGap (&to, salp, aln_row))
5445             {
5446               sprintf (err_msg, "Interval %d is completely contained in a gap in the alignment.",
5447                        interval_num);
5448               ValNodeAddPointer (&head, 0, StringSave (err_msg));
5449             }
5450           }
5451         }
5452         else
5453         {
5454           sprintf (err_msg, "Sequence for interval %d not in selected alignment", interval_num);
5455           ValNodeAddPointer (&head, 0, StringSave (err_msg));
5456           ListAlignmentsThatContainSequence (ipp->salp_list, ipp->aln_count,
5457                                              bsp, seqid, &head);
5458           ListSequencesInAlignment (ipp->sip_list, ipp->count, salp, &head);
5459         }
5460       }
5461     }
5462   }
5463 
5464   return head;
5465 }
5466 
5467 
5468 static Boolean
AddLocToList(SeqIdPtr seqid,Uint2 strand,Int4 from,Int4 to,Boolean add_null,Int2 fuzz_from,Int2 fuzz_to,Boolean fuzz_before,Boolean fuzz_after,Boolean partial5,Boolean partial3,SeqLocPtr PNTR pslp)5469 AddLocToList
5470 (SeqIdPtr       seqid,
5471  Uint2          strand,
5472  Int4           from,
5473  Int4           to,
5474  Boolean        add_null,
5475  Int2           fuzz_from,
5476  Int2           fuzz_to,
5477  Boolean        fuzz_before,
5478  Boolean        fuzz_after,
5479  Boolean        partial5,
5480  Boolean        partial3,
5481  SeqLocPtr PNTR pslp)
5482 {
5483   SeqLocPtr slp;
5484   SeqLocPtr tmploc1, tmploc2;
5485   Boolean   isInterval;
5486   Boolean   isPoint;
5487   Int4      tmp;
5488 
5489   if (pslp == NULL || seqid == NULL)
5490   {
5491     return FALSE;
5492   }
5493 
5494   if (add_null) {
5495     /* add NULL location between last location and this one */
5496     slp = ValNodeNew (NULL);
5497     if (slp != NULL) {
5498       slp->choice = SEQLOC_NULL;
5499       tmploc1 = *pslp;
5500       if (tmploc1 != NULL) {
5501         if (tmploc1->choice == SEQLOC_MIX) {
5502           tmploc2 = (ValNodePtr) (tmploc1->data.ptrvalue);
5503           if (tmploc2 != NULL) {
5504             while (tmploc2->next != NULL) {
5505               tmploc2 = tmploc2->next;
5506             }
5507             tmploc2->next = slp;
5508           }
5509         } else {
5510           tmploc2 = ValNodeNew (NULL);
5511           if (tmploc2 != NULL) {
5512             tmploc2->choice = SEQLOC_MIX;
5513             tmploc2->data.ptrvalue = (Pointer) tmploc1;
5514             tmploc1->next = slp;
5515             *pslp = tmploc2;
5516           }
5517         }
5518       }
5519     }
5520   }
5521 
5522   isInterval = TRUE;
5523   isPoint = FALSE;
5524 
5525   /* make sure from and to are in correct order */
5526   if (from > to)
5527   {
5528     tmp = from;
5529     from = to;
5530     to = tmp;
5531   }
5532 
5533   if (fuzz_after && to == from + 1) {
5534     isInterval = FALSE;
5535     isPoint = TRUE;
5536     /* from++; */ /* this was causing point to be thrown off */
5537   } else if (to == from && (! partial5) && (! partial3)) {
5538     isInterval = FALSE;
5539     isPoint = TRUE;
5540   }
5541 
5542   if (isInterval) {
5543     AddIntToSeqLoc (pslp, from - 1, to - 1, seqid,
5544                     fuzz_from, fuzz_to, strand);
5545   } else if (isPoint) {
5546     AddSeqLocPoint (pslp, seqid, from, fuzz_before, fuzz_after, strand);
5547   }
5548   return TRUE;
5549 }
5550 
SetPartialsForOneLocation(SeqLocPtr master_slp,Boolean partial5,Boolean partial3)5551 static void SetPartialsForOneLocation (SeqLocPtr master_slp, Boolean partial5, Boolean partial3)
5552 {
5553   SeqLocPtr  firstSlp, lastSlp, tmp_slp;
5554   IntFuzzPtr ifp;
5555   SeqIntPtr  sip;
5556   SeqPntPtr  spp;
5557 
5558   if (master_slp == NULL)
5559   {
5560     return;
5561   }
5562 
5563   /* now set partials for location */
5564   firstSlp = NULL;
5565   lastSlp = NULL;
5566   tmp_slp = SeqLocFindNext (master_slp, NULL);
5567   while (tmp_slp != NULL) {
5568     if (firstSlp == NULL) {
5569       firstSlp = tmp_slp;
5570     }
5571     lastSlp = tmp_slp;
5572     tmp_slp = SeqLocFindNext (master_slp, tmp_slp);
5573   }
5574   if (firstSlp != NULL && partial5) {
5575     if (firstSlp->choice == SEQLOC_INT && firstSlp->data.ptrvalue != NULL) {
5576       sip = (SeqIntPtr) firstSlp->data.ptrvalue;
5577       ifp = IntFuzzNew ();
5578       if (ifp != NULL) {
5579         ifp->choice = 4;
5580         if (sip->strand == Seq_strand_minus || sip->strand == Seq_strand_both_rev) {
5581           sip->if_to = ifp;
5582           ifp->a = 1;
5583         } else {
5584           sip->if_from = ifp;
5585           ifp->a = 2;
5586         }
5587       }
5588     } else if (firstSlp->choice == SEQLOC_PNT && firstSlp->data.ptrvalue != NULL) {
5589       spp = (SeqPntPtr) firstSlp->data.ptrvalue;
5590       ifp = IntFuzzNew ();
5591       if (ifp != NULL) {
5592         ifp->choice = 4;
5593         if (spp->strand == Seq_strand_minus || spp->strand == Seq_strand_both_rev) {
5594           spp->fuzz = ifp;
5595           ifp->a = 1;
5596         } else {
5597           spp->fuzz = ifp;
5598           ifp->a = 2;
5599         }
5600       }
5601     }
5602   }
5603   if (lastSlp != NULL && partial3) {
5604     if (lastSlp->choice == SEQLOC_INT && lastSlp->data.ptrvalue != NULL) {
5605       sip = (SeqIntPtr) lastSlp->data.ptrvalue;
5606       ifp = IntFuzzNew ();
5607       if (ifp != NULL) {
5608         ifp->choice = 4;
5609         if (sip->strand == Seq_strand_minus || sip->strand == Seq_strand_both_rev) {
5610           sip->if_from = ifp;
5611           ifp->a = 2;
5612         } else {
5613           sip->if_to = ifp;
5614           ifp->a = 1;
5615         }
5616       }
5617     } else if (lastSlp->choice == SEQLOC_PNT && lastSlp->data.ptrvalue != NULL) {
5618       spp = (SeqPntPtr) lastSlp->data.ptrvalue;
5619       ifp = IntFuzzNew ();
5620       if (ifp != NULL) {
5621         ifp->choice = 4;
5622         if (spp->strand == Seq_strand_minus || spp->strand == Seq_strand_both_rev) {
5623           spp->fuzz = ifp;
5624           ifp->a = 2;
5625         } else {
5626           spp->fuzz = ifp;
5627           ifp->a = 1;
5628         }
5629       }
5630     }
5631   }
5632 }
5633 
5634 static SeqLocPtr
ReadSingleSeqLoc(TagListPtr tlp,IntervalPagePtr ipp,Boolean partial5,Boolean partial3,Boolean nullsBetween)5635 ReadSingleSeqLoc
5636 (TagListPtr      tlp,
5637  IntervalPagePtr ipp,
5638  Boolean         partial5,
5639  Boolean         partial3,
5640  Boolean         nullsBetween)
5641 {
5642   Int4             from, to, aln_row, aln_len;
5643   Boolean          fuzz_after;
5644   Boolean          fuzz_before;
5645   Int2             fuzz_from;
5646   Int2             fuzz_to;
5647   Boolean          isInterval;
5648   Boolean          isPoint;
5649   Boolean          notFirst;
5650   Boolean          okay;
5651   SeqIdPtr         seqid, prev_sip;
5652   SeqLocPtr        master_slp;
5653   Uint2            strand, prev_strand;
5654   ValNodePtr       vnp;
5655   SeqAlignPtr      salp, prev_salp;
5656   BioseqPtr        bsp;
5657 
5658   if (tlp == NULL)
5659   {
5660     return NULL;
5661   }
5662 
5663   prev_sip = NULL;
5664   prev_salp = NULL;
5665   prev_strand = Seq_strand_unknown;
5666   master_slp = NULL;
5667 
5668   notFirst = FALSE;
5669   for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
5670     if (StringHasNoText (vnp->data.ptrvalue))
5671     {
5672       continue;
5673     }
5674     fuzz_from = -1;
5675     fuzz_to = -1;
5676     fuzz_before = FALSE;
5677     fuzz_after = FALSE;
5678     from = 0;
5679     to = 0;
5680     isInterval = TRUE;
5681     isPoint = FALSE;
5682     strand = Seq_strand_unknown;
5683     seqid = NULL;
5684     salp = NULL;
5685     aln_row = 0;
5686     if (!ReadFromValueFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5687                                            &from, &fuzz_after))
5688     {
5689       continue;
5690     }
5691     okay = ReadToValueFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5692                                          &to, &from, &fuzz_after,
5693                                          &isInterval, &isPoint,
5694                                          partial5, partial3)
5695            && ReadStrandFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5696                                         ipp->strand_col,
5697                                         &strand, &prev_strand)
5698            && ReadSeqIdFromDialogLine ((CharPtr) vnp->data.ptrvalue, ipp->seqid_col,
5699                                        &seqid, &prev_sip,
5700                                        ipp->sip_list, ipp->count)
5701            && (ipp->salp_list == NULL
5702                || ReadSeqAlignFromDialogLine ((CharPtr) vnp->data.ptrvalue, ipp->aln_col,
5703                                               &salp, &prev_salp,
5704                                               ipp->salp_list, ipp->aln_count))
5705            && ((bsp = BioseqFind (seqid)) != NULL)
5706            && (salp != NULL || CoordinatesValidForBioseq (from, to, bsp))
5707            && (salp == NULL ||
5708                 (GetBioseqAlignmentRow (salp, bsp, &aln_row)
5709                  && AdjustStrandForAlignment (&strand, salp, aln_row)
5710                  && (aln_len = SeqAlignLength (salp)) > 0
5711                  && AdjustFromForGap (&from, salp, aln_len, aln_row)
5712                  && AdjustToForGap (&to, salp, aln_row)))
5713            && AddLocToList (seqid, strand, from, to,
5714                             (nullsBetween  && notFirst),
5715                             fuzz_from, fuzz_to,
5716                             fuzz_before, fuzz_after,
5717                             partial5, partial3,
5718                             &(master_slp));
5719     if (okay)
5720     {
5721       notFirst = TRUE;
5722     }
5723     else
5724     {
5725       master_slp = SeqLocFree (master_slp);
5726       return NULL;
5727     }
5728   }
5729 
5730   /* now set partials for location */
5731   SetPartialsForOneLocation (master_slp, partial5, partial3);
5732   return master_slp;
5733 }
5734 
FreeSeqLocArray(SeqLocPtr PNTR loc_list,Int4 num_loc)5735 static SeqLocPtr PNTR FreeSeqLocArray (SeqLocPtr PNTR loc_list, Int4 num_loc)
5736 {
5737   Int4 j;
5738   if (loc_list != NULL)
5739   {
5740     for (j = 0; j < num_loc; j++)
5741     {
5742       loc_list [j] = SeqLocFree (loc_list [j]);
5743     }
5744     loc_list = MemFree (loc_list);
5745   }
5746   return loc_list;
5747 }
5748 
5749 static SeqLocPtr
ReadAlignedSeqLocList(TagListPtr tlp,IntervalPagePtr ipp,Boolean partial5,Boolean partial3,Boolean nullsBetween)5750 ReadAlignedSeqLocList
5751 (TagListPtr      tlp,
5752  IntervalPagePtr ipp,
5753  Boolean         partial5,
5754  Boolean         partial3,
5755  Boolean         nullsBetween)
5756 {
5757   Int4             from, to, aln_from, aln_to, aln_row, aln_len = 0;
5758   Boolean          fuzz_after;
5759   Boolean          fuzz_before;
5760   Int2             fuzz_from;
5761   Int2             fuzz_to;
5762   Boolean          isInterval;
5763   Boolean          isPoint;
5764   Boolean          notFirst;
5765   Boolean          okay;
5766   SeqIdPtr         seqid;
5767   SeqLocPtr        master_slp, tmp_slp;
5768   Uint2            strand, prev_strand, aln_strand;
5769   ValNodePtr       vnp;
5770   SeqAlignPtr      salp, prev_salp;
5771   BioseqPtr        bsp;
5772   SeqLocPtr PNTR   loc_list;
5773   Int4             loc_num, max_locs;
5774   Boolean          asked_about_repair = FALSE;
5775   MsgAnswer        ans = ANS_YES;
5776 
5777   if (tlp == NULL || ipp == NULL || ipp->salp_list == NULL)
5778   {
5779     return NULL;
5780   }
5781 
5782   prev_salp = NULL;
5783   prev_strand = Seq_strand_unknown;
5784   master_slp = NULL;
5785 
5786   max_locs = 0;
5787   for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next)
5788   {
5789     if (!ReadSeqAlignFromDialogLine ((CharPtr) vnp->data.ptrvalue, ipp->aln_col,
5790                                      &salp, &prev_salp,
5791                                      ipp->salp_list, ipp->aln_count))
5792     {
5793       return NULL;
5794     }
5795     else
5796     {
5797       max_locs = MAX (max_locs, salp->dim);
5798     }
5799   }
5800   if (max_locs == 0)
5801   {
5802     return NULL;
5803   }
5804 
5805   loc_list = (SeqLocPtr PNTR) MemNew (max_locs * sizeof (SeqLocPtr));
5806   if (loc_list == NULL)
5807   {
5808     return NULL;
5809   }
5810 
5811   prev_salp = NULL;
5812 
5813   okay = TRUE;
5814   notFirst = FALSE;
5815   for (vnp = tlp->vnp; vnp != NULL && okay; vnp = vnp->next) {
5816     if (StringHasNoText (vnp->data.ptrvalue))
5817     {
5818       continue;
5819     }
5820     fuzz_from = -1;
5821     fuzz_to = -1;
5822     fuzz_before = FALSE;
5823     fuzz_after = FALSE;
5824     from = 0;
5825     to = 0;
5826     isInterval = TRUE;
5827     isPoint = FALSE;
5828     strand = Seq_strand_unknown;
5829     seqid = NULL;
5830     salp = NULL;
5831     aln_row = 0;
5832     if (! ReadFromValueFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5833                                            &from, &fuzz_after))
5834     {
5835       continue;
5836     }
5837     okay = ReadToValueFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5838                                        &to, &from, &fuzz_after,
5839                                        &isInterval, &isPoint,
5840                                        partial5, partial3)
5841            && ReadStrandFromDialogLine ((CharPtr) vnp->data.ptrvalue,
5842                                         ipp->strand_col,
5843                                         &strand, &prev_strand)
5844            && ReadSeqAlignFromDialogLine ((CharPtr) vnp->data.ptrvalue, ipp->aln_col,
5845                                               &salp, &prev_salp,
5846                                               ipp->salp_list, ipp->aln_count);
5847     if (okay)
5848     {
5849       for (loc_num = 0; loc_num < salp->dim; loc_num++)
5850       {
5851         aln_row = loc_num + 1;
5852         aln_from = from;
5853         aln_to = to;
5854         aln_strand = strand;
5855         seqid = AlnMgr2GetNthSeqIdPtr (salp, aln_row);
5856         okay = ((bsp = BioseqFind (seqid)) != NULL)
5857                  && AdjustStrandForAlignment (&aln_strand, salp, aln_row)
5858                  && (aln_len = SeqAlignLength (salp)) > 0;
5859         if (okay)
5860         {
5861           if (ipp->allow_nulls_in_list)
5862           {
5863             if (! AdjustFromForGap (&aln_from, salp, aln_len, aln_row)
5864                 || ! AdjustToForGap (&aln_to, salp, aln_row)
5865                 || ! AddLocToList (seqid, aln_strand, aln_from, aln_to,
5866                                    (nullsBetween  && notFirst),
5867                                    fuzz_from, fuzz_to,
5868                                    fuzz_before, fuzz_after,
5869                                    partial5, partial3,
5870                                    &(loc_list [loc_num])))
5871             {
5872               if (loc_list[loc_num] == NULL)
5873               {
5874                 loc_list [loc_num] = ValNodeNew (NULL);
5875                 loc_list [loc_num]->choice = SEQLOC_NULL;
5876               }
5877             }
5878           }
5879           else
5880           {
5881             okay = AdjustFromForGap (&aln_from, salp, aln_len, aln_row)
5882                    && AdjustToForGap (&aln_to, salp, aln_row)
5883                    && AddLocToList (seqid, aln_strand, aln_from, aln_to,
5884                               (nullsBetween  && notFirst),
5885                               fuzz_from, fuzz_to,
5886                               fuzz_before, fuzz_after,
5887                               partial5, partial3,
5888                               &(loc_list [loc_num]));
5889           }
5890         }
5891       }
5892     }
5893 
5894     notFirst = TRUE;
5895   }
5896 
5897   if (!okay)
5898   {
5899     loc_list = FreeSeqLocArray (loc_list, max_locs);
5900     return NULL;
5901   }
5902 
5903   /* now fix intervals that are out of order and set partials for locations */
5904   for (loc_num = 0; loc_num < max_locs && loc_list [loc_num] != NULL; loc_num++)
5905   {
5906     bsp = BioseqFindFromSeqLoc (loc_list [loc_num]);
5907     if (bsp != NULL && SeqLocBadSortOrder (bsp, loc_list [loc_num]))
5908     {
5909       if (!asked_about_repair)
5910       {
5911         ans = Message (MSG_YN,
5912             "Feature location intervals are out of order.  Do you want them repaired?");
5913         asked_about_repair = TRUE;
5914       }
5915       if (ans == ANS_YES) {
5916         tmp_slp = SeqLocMerge (bsp, loc_list [loc_num], NULL, FALSE, FALSE, nullsBetween);
5917         loc_list [loc_num] = SeqLocFree (loc_list [loc_num]);
5918         loc_list [loc_num] = tmp_slp;
5919         if (bsp->repr == Seq_repr_seg) {
5920           tmp_slp = SegLocToParts (bsp, loc_list [loc_num]);
5921           loc_list [loc_num] = SeqLocFree (loc_list [loc_num]);
5922           loc_list [loc_num] = tmp_slp;
5923         }
5924         FreeAllFuzz (loc_list [loc_num]);
5925       }
5926     }
5927     SetSeqLocPartial (loc_list [loc_num], partial5, partial3);
5928   }
5929 
5930   /* now make chain */
5931   master_slp = loc_list [0];
5932   tmp_slp = loc_list [0];
5933   for (tmp_slp = loc_list [0], loc_num = 1;
5934        tmp_slp != NULL && loc_num < max_locs;
5935        loc_num++)
5936   {
5937     tmp_slp->next = loc_list [loc_num];
5938     tmp_slp = tmp_slp->next;
5939   }
5940 
5941   loc_list = MemFree (loc_list);
5942 
5943   return master_slp;
5944 }
5945 
IntervalPageToSeqLocPtr(DialoG d)5946 static Pointer IntervalPageToSeqLocPtr (DialoG d)
5947 
5948 {
5949   IntervalPagePtr  ipp;
5950   Boolean          nullsBetween;
5951   Boolean          partial5;
5952   Boolean          partial3;
5953   SeqLocPtr        master_slp;
5954   TagListPtr       tlp;
5955 
5956   ipp = (IntervalPagePtr) GetObjectExtra (d);
5957   if (ipp == NULL) return NULL;
5958   tlp = GetObjectExtra (ipp->ivals);
5959   if (tlp == NULL) return NULL;
5960 
5961 
5962   nullsBetween = GetStatus (ipp->nullsBetween);
5963   partial5 = GetStatus (ipp->partial5);
5964   partial3 = GetStatus (ipp->partial3);
5965 
5966   if (ipp->seqid_col > -1)
5967   {
5968     master_slp = ReadSingleSeqLoc (tlp, ipp, partial5, partial3, nullsBetween);
5969   }
5970   else
5971   {
5972     master_slp = ReadAlignedSeqLocList (tlp, ipp, partial5, partial3, nullsBetween);
5973   }
5974   return (Pointer) master_slp;
5975 }
5976 
CleanupIntervalPage(GraphiC g,VoidPtr data)5977 static void CleanupIntervalPage (GraphiC g, VoidPtr data)
5978 
5979 {
5980   IntervalPagePtr  ipp;
5981   Int2             j;
5982 
5983   ipp = (IntervalPagePtr) data;
5984   if (ipp != NULL) {
5985     /* free seq ID list */
5986     if (ipp->sip_list != NULL)
5987     {
5988       for (j = 0; j <= ipp->count + 1; j++) {
5989         ipp->sip_list [j] = SeqIdFree (ipp->sip_list [j]);
5990       }
5991     }
5992     MemFree (ipp->sip_list);
5993     if (ipp->alist != NULL) {
5994       for (j = 0; j <= ipp->count + 1; j++) {
5995         MemFree (ipp->alist [j].name);
5996       }
5997     }
5998     MemFree (ipp->alist);
5999     MemFree (ipp->lengths);
6000 
6001     /* free list of alignments */
6002     if (ipp->salp_list != NULL)
6003     {
6004       for (j = 0; j <= ipp->aln_count + 1; j++) {
6005         ipp->salp_list [j] = SeqAlignFree (ipp->salp_list [j]);
6006       }
6007     }
6008     MemFree (ipp->salp_list);
6009     /* free alignment tags */
6010     if (ipp->aln_alist != NULL) {
6011       for (j = 0; j <= ipp->aln_count + 1; j++) {
6012         MemFree (ipp->aln_alist [j].name);
6013       }
6014     }
6015     MemFree (ipp->aln_alist);
6016     /* free alignment lengths */
6017     MemFree (ipp->aln_lengths);
6018 
6019 
6020     /* free callback list */
6021     MemFree (ipp->callbacks);
6022   }
6023   MemFree (data);
6024 }
6025 
6026 Uint2 interval_types [] = {
6027   TAGLIST_TEXT, TAGLIST_TEXT, TAGLIST_POPUP, TAGLIST_POPUP, TAGLIST_POPUP
6028 };
6029 
6030 Uint2 interval_widths [] = {
6031   5, 5, 0, 0, 0
6032 };
6033 
ReadSeqLocDialog(DialoG d,CharPtr filename)6034 static Boolean ReadSeqLocDialog (DialoG d, CharPtr filename)
6035 
6036 {
6037   AsnIoPtr         aip;
6038   IntervalPagePtr  ipp;
6039   SeqLocPtr        slp;
6040   Char             path [PATH_MAX];
6041 
6042   path [0] = '\0';
6043   StringNCpy_0 (path, filename, sizeof (path));
6044   ipp = (IntervalPagePtr) GetObjectExtra (d);
6045   if (ipp != NULL) {
6046     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
6047       aip = AsnIoOpen (path, "r");
6048       if (aip != NULL) {
6049         slp = SeqLocAsnRead (aip, NULL);
6050         AsnIoClose (aip);
6051         if (slp != NULL) {
6052           SeqLocPtrToIntervalPage (ipp->dialog, slp);
6053           slp = SeqLocFree (slp);
6054           Update ();
6055           return TRUE;
6056         }
6057       }
6058     }
6059   }
6060   return FALSE;
6061 }
6062 
WriteSeqLocDialog(DialoG d,CharPtr filename)6063 static Boolean WriteSeqLocDialog (DialoG d, CharPtr filename)
6064 
6065 {
6066   AsnIoPtr         aip;
6067   IntervalPagePtr  ipp;
6068   SeqLocPtr        slp;
6069   Char             path [PATH_MAX];
6070 #ifdef WIN_MAC
6071   FILE            *f;
6072 #endif
6073 
6074   path [0] = '\0';
6075   StringNCpy_0 (path, filename, sizeof (path));
6076   ipp = (IntervalPagePtr) GetObjectExtra (d);
6077   if (ipp != NULL) {
6078     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
6079 #ifdef WIN_MAC
6080       f = FileOpen (path, "r");
6081       if (f != NULL) {
6082         FileClose (f);
6083       } else {
6084         FileCreate (path, "TEXT", "ttxt");
6085       }
6086 #endif
6087       aip = AsnIoOpen (path, "w");
6088       if (aip != NULL) {
6089         slp = IntervalPageToSeqLocPtr (ipp->dialog);
6090         SeqLocAsnWrite (slp, aip, NULL);
6091         AsnIoClose (aip);
6092         slp = SeqLocFree (slp);
6093         return TRUE;
6094       }
6095     }
6096   }
6097   return FALSE;
6098 }
6099 
SetOnlySequenceAndStrand(IntervalPagePtr ipp)6100 static void SetOnlySequenceAndStrand (IntervalPagePtr ipp)
6101 {
6102   TagListPtr       tlp;
6103   ValNodePtr       vnp;
6104   CharPtr          cp;
6105   CharPtr          tabptr;
6106   ValNodePtr       saved_list;
6107 
6108   if (ipp == NULL) return;
6109   tlp = GetObjectExtra (ipp->ivals);
6110   if (tlp == NULL) return;
6111   saved_list = tlp->vnp;
6112   tlp->vnp = NULL;
6113   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
6114   tlp->vnp = saved_list;
6115   for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next)
6116   {
6117     cp = vnp->data.ptrvalue;
6118     if (cp != NULL)
6119     {
6120       tabptr = StringChr (cp, '\t');
6121       if (tabptr != NULL)
6122       {
6123           tabptr = StringChr (tabptr + 1, '\t');
6124       }
6125       if (tabptr != NULL)
6126       {
6127           cp[0] = '\t';
6128           cp++;
6129           while (*tabptr != 0)
6130           {
6131             *cp = *tabptr;
6132             cp++;
6133             tabptr++;
6134           }
6135           *cp = 0;
6136       }
6137     }
6138   }
6139 
6140   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
6141 }
6142 
ClearLocationPartialCheckboxes(IntervalPagePtr ipp)6143 static void ClearLocationPartialCheckboxes (IntervalPagePtr ipp)
6144 {
6145   if (ipp != NULL)
6146   {
6147     SetStatus (ipp->partial5, FALSE);
6148     SetStatus (ipp->partial3, FALSE);
6149     SetStatus (ipp->nullsBetween, FALSE);
6150     if (ipp->proc != NULL) {
6151       ipp->proc (ipp->ffp, FALSE, FALSE, FALSE);
6152     }
6153   }
6154 }
6155 
IntervalEditorMessage(DialoG d,Int2 mssg)6156 static void IntervalEditorMessage (DialoG d, Int2 mssg)
6157 
6158 {
6159   IntervalPagePtr  ipp;
6160 
6161   ipp = (IntervalPagePtr) GetObjectExtra (d);
6162   if (ipp != NULL) {
6163     switch (mssg) {
6164       case VIB_MSG_INIT:
6165         SeqLocPtrToIntervalPage (d, NULL);
6166         break;
6167       case VIB_MSG_ENTER:
6168         SendMessageToDialog (ipp->ivals, VIB_MSG_ENTER);
6169         break;
6170       case VIB_MSG_RESET:
6171         /* do nothing */
6172         break;
6173       case NUM_VIB_MSG + 1:
6174         SetOnlySequenceAndStrand (ipp);
6175         break;
6176       case NUM_VIB_MSG + 2:
6177         ClearLocationPartialCheckboxes (ipp);
6178         break;
6179       case VIB_MSG_CUT :
6180         StdCutTextProc (NULL);
6181         break;
6182       case VIB_MSG_COPY :
6183         StdCopyTextProc (NULL);
6184         break;
6185       case VIB_MSG_PASTE :
6186         StdPasteTextProc (NULL);
6187         break;
6188       case VIB_MSG_DELETE :
6189         StdDeleteTextProc (NULL);
6190         break;
6191     }
6192   }
6193 }
6194 
StdFeatIntEdPartialCallback(FeatureFormPtr ffp,Boolean partial5,Boolean partial3,Boolean order)6195 extern void StdFeatIntEdPartialCallback (FeatureFormPtr ffp, Boolean partial5, Boolean partial3, Boolean order)
6196 
6197 {
6198   if (ffp == NULL) return;
6199   SafeSetStatus (ffp->partial, (partial5 || partial3 || order));
6200   Update ();
6201 }
6202 
ChangedPartialProc(ButtoN b)6203 static void ChangedPartialProc (ButtoN b)
6204 
6205 {
6206   IntervalPagePtr  ipp;
6207 
6208   ipp = (IntervalPagePtr) GetObjectExtra (b);
6209   if (ipp == NULL) return;
6210   if (ipp->proc != NULL) {
6211     ipp->proc (ipp->ffp, GetStatus (ipp->partial5),
6212                GetStatus (ipp->partial3), GetStatus (ipp->nullsBetween));
6213   }
6214 }
6215 
6216 
MakeBlankLocationLine(CharPtr orig)6217 static CharPtr MakeBlankLocationLine (CharPtr orig)
6218 {
6219   CharPtr cp, rval = NULL;
6220 
6221   if (StringHasNoText (orig)) {
6222     return StringSave ("");
6223   }
6224   /* skip first two values, keep the rest */
6225   cp = StringChr (orig, '\t');
6226   if (cp == NULL) {
6227     return StringSave ("");
6228   }
6229   cp = StringChr (cp + 1, '\t');
6230   if (cp == NULL) {
6231     return StringSave ("");
6232   }
6233   cp++;
6234 
6235   rval = (CharPtr) MemNew (sizeof (Char) * (StringLen (cp) + 3));
6236   sprintf (rval, "\t\t%s", cp);
6237   return rval;
6238 }
6239 
6240 
InsertFirstLocation(ButtoN b)6241 static void InsertFirstLocation (ButtoN b)
6242 {
6243   DialoG ivals;
6244   TagListPtr tlp;
6245   ValNodePtr vnp;
6246   Int2 j;
6247 
6248   ivals = (DialoG) GetObjectExtra (b);
6249   if (ivals == NULL) {
6250     return;
6251   }
6252   tlp = (TagListPtr) GetObjectExtra (ivals);
6253   if (tlp == NULL || tlp->vnp == NULL || StringHasNoText (tlp->vnp->data.ptrvalue)) {
6254     return;
6255   }
6256 
6257   /* add blank line to current lines */
6258   vnp = ValNodeNew (NULL);
6259   vnp->data.ptrvalue = MakeBlankLocationLine (tlp->vnp->data.ptrvalue);
6260   vnp->next = tlp->vnp;
6261   /* disconnect lines from taglist, so they won't be erased by the reset */
6262   tlp->vnp = NULL;
6263 
6264   /* reset the dialog */
6265   SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
6266 
6267   /* attach the lines to the dialog */
6268   tlp->vnp = vnp;
6269 
6270   /* redraw dialog */
6271   SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
6272   /* adjust scroll bars */
6273   for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
6274   }
6275   tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
6276   CorrectBarMax (tlp->bar, tlp->max);
6277   CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
6278   SendMessageToDialog (tlp->dialog, VIB_MSG_ENTER);
6279 }
6280 
6281 extern DialoG CreateTagListDialogEx (GrouP h, Uint2 rows, Uint2 cols,
6282                                      Int2 spacing, Uint2Ptr types,
6283                                      Uint2Ptr textWidths, EnumFieldAssocPtr PNTR alists,
6284                                      Boolean useBar, Boolean noExtend,
6285                                      ToDialogFunc tofunc, FromDialogFunc fromfunc);
6286 
CreateIntervalEditorDialogExEx(GrouP h,CharPtr title,Uint2 rows,Int2 spacing,SeqEntryPtr sep,Boolean nucsOK,Boolean protsOK,Boolean useBar,Boolean showPartials,Boolean allowGaps,FeatureFormPtr ffp,IntEdPartialProc proc,Boolean use_aln,Boolean show_seqid,TaglistCallback tlp_callback,Pointer callback_data,Boolean allow_nulls_in_list)6287 extern DialoG CreateIntervalEditorDialogExEx (GrouP h, CharPtr title, Uint2 rows,
6288                                               Int2 spacing, SeqEntryPtr sep,
6289                                               Boolean nucsOK, Boolean protsOK,
6290                                               Boolean useBar, Boolean showPartials,
6291                                               Boolean allowGaps, FeatureFormPtr ffp,
6292                                               IntEdPartialProc proc,
6293                                               Boolean use_aln, Boolean show_seqid,
6294                                               TaglistCallback tlp_callback,
6295                                               Pointer callback_data,
6296                                               Boolean allow_nulls_in_list)
6297 
6298 {
6299   BioseqPtr        bsp;
6300   Int4             count;
6301   GrouP            f;
6302   IntervalPagePtr  ipp;
6303   Int2             j;
6304   GrouP            m;
6305   GrouP            p;
6306   GrouP            btn_grp;
6307   PrompT           p1;
6308   PrompT           p2;
6309   PrompT           p3;
6310   PrompT           p_from, p_to;
6311   CharPtr          ptr;
6312   GrouP            q;
6313   GrouP            s;
6314   Boolean          showIdTags;
6315   SeqIdPtr         sip;
6316   Char             str [128];
6317   TagListPtr       tlp;
6318   SeqAlignPtr      salp_list = NULL, salp;
6319   Int4             num_cols;
6320   ButtoN           b;
6321 
6322   p = HiddenGroup (h, 1, 0, NULL);
6323   SetGroupSpacing (p, 10, 10);
6324 
6325   ipp = (IntervalPagePtr) MemNew (sizeof (IntervalPage));
6326   if (ipp != NULL) {
6327 
6328     SetObjectExtra (p, ipp, CleanupIntervalPage);
6329     ipp->dialog = (DialoG) p;
6330     ipp->todialog = SeqLocPtrToIntervalPage;
6331     ipp->fromdialog = IntervalPageToSeqLocPtr;
6332     ipp->dialogmessage = IntervalEditorMessage;
6333     ipp->testdialog = TestIntervalEditor;
6334     ipp->importdialog = ReadSeqLocDialog;
6335     ipp->exportdialog = WriteSeqLocDialog;
6336 
6337     ipp->ffp = ffp;
6338     ipp->proc = proc;
6339 
6340     ipp->allow_nulls_in_list = allow_nulls_in_list;
6341 
6342     if (title != NULL && title [0] != '\0') {
6343       s = NormalGroup (p, 0, -2, title, systemFont, NULL);
6344     } else {
6345       s = HiddenGroup (p, 0, -2, NULL);
6346     }
6347     m = HiddenGroup (s, -1, 0, NULL);
6348     /*
6349     SetGroupSpacing (m, 10, 10);
6350     */
6351 
6352     ipp->nucsOK = nucsOK;
6353     ipp->protsOK = protsOK;
6354     ipp->showIdTags = FALSE;
6355     ipp->count = 0;
6356 
6357     if (ipp->nucsOK)
6358     {
6359       ipp->strand_col = 2;
6360     }
6361     else
6362     {
6363       ipp->strand_col = -1;
6364     }
6365 
6366     ipp->aln_col = -1;
6367     if (show_seqid)
6368     {
6369       if (ipp->nucsOK)
6370       {
6371         ipp->seqid_col = 3;
6372       }
6373       else
6374       {
6375         ipp->seqid_col = 2;
6376       }
6377       if (use_aln)
6378       {
6379         ipp->aln_col = ipp->seqid_col + 1;
6380       }
6381     }
6382     else
6383     {
6384       ipp->seqid_col = -1;
6385       if (use_aln)
6386       {
6387         if (ipp->nucsOK)
6388         {
6389           ipp->aln_col = 3;
6390         }
6391         else
6392         {
6393           ipp->aln_col = 2;
6394         }
6395       }
6396     }
6397 
6398     /* set up callbacks */
6399     ipp->callbacks = (TaglistCallback PNTR) MemNew (5 * sizeof (TaglistCallback));
6400     if (ipp->callbacks != NULL)
6401     {
6402       ipp->callbacks [0] = NULL;
6403       ipp->callbacks [1] = NULL;
6404       ipp->callbacks [2] = NULL;
6405       ipp->callbacks [3] = NULL;
6406       ipp->callbacks [4] = NULL;
6407 
6408       if (ipp->seqid_col > -1)
6409       {
6410         ipp->callbacks [ipp->seqid_col] = tlp_callback;
6411       }
6412       if (ipp->aln_col > -1)
6413       {
6414         ipp->callbacks [ipp->aln_col] = tlp_callback;
6415       }
6416     }
6417 
6418     if (sep != NULL) {
6419       if (use_aln)
6420       {
6421         VisitAnnotsInSep (sep, &salp_list, GetAlignmentsInSeqEntryCallback);
6422         count = 4;
6423         salp = salp_list;
6424         while (salp != NULL)
6425         {
6426           count++;
6427           salp = salp->next;
6428         }
6429 
6430         ipp->salp_list = (SeqAlignPtr PNTR) MemNew (sizeof (SeqAlignPtr) * count);
6431         ipp->aln_alist = MemNew (sizeof (EnumFieldAssoc) * (size_t) count);
6432         ipp->aln_lengths = MemNew (sizeof (Int4) * (size_t) count);
6433         ipp->aln_count = 0;
6434         if (ipp->salp_list != NULL && ipp->aln_alist != NULL && ipp->aln_lengths != NULL)
6435         {
6436           /* first one is NULL */
6437           ipp->salp_list [0] = NULL;
6438           ipp->aln_lengths [0] = 0;
6439           ipp->aln_alist [0].name = StringSave ("     ");
6440           ipp->aln_alist [0].value = (UIEnum) 0;
6441           ipp->aln_count ++;
6442           salp = salp_list;
6443           while (salp != NULL)
6444           {
6445             ipp->salp_list [ipp->aln_count] = salp;
6446             ipp->aln_lengths [ipp->aln_count] = SeqAlignLength (ipp->salp_list [ipp->aln_count]);
6447             CreateSeqAlignLabel (ipp->salp_list [ipp->aln_count], str, 30);
6448             ipp->aln_alist [ipp->aln_count].name = StringSave (str);
6449             ipp->aln_alist [ipp->aln_count].value = (UIEnum) ipp->aln_count;
6450 
6451             salp = salp->next;
6452             /* sever chain */
6453             ipp->salp_list [ipp->aln_count]->next = NULL;
6454             ipp->aln_count++;
6455           }
6456           /* add end of list marker */
6457           ipp->aln_alist [ipp->aln_count].name = NULL;
6458           ipp->aln_alist [ipp->aln_count].value = (UIEnum) 0;
6459         }
6460 
6461       }
6462       else
6463       {
6464         ipp->salp_list = NULL;
6465         ipp->aln_alist = NULL;
6466         ipp->aln_lengths = NULL;
6467         ipp->aln_count = 0;
6468       }
6469       count = SegmentedEntryCount (sep);
6470       count += 4;
6471       ipp->sip_list = MemNew (sizeof (SeqIdPtr) * (size_t) count);
6472       ipp->alist = MemNew (sizeof (EnumFieldAssoc) * (size_t) count);
6473       ipp->lengths = MemNew (sizeof (Int4) * (size_t) count);
6474       ipp->count = 0;
6475 
6476       if (ipp->sip_list != NULL && ipp->alist != NULL && ipp->lengths != NULL) {
6477         VisitBioseqsInSep (sep, NULL, ClearBspScratch);
6478         SeqEntryExplore (sep, (Pointer) ipp, FillInProducts);
6479         VisitBioseqsInSep (sep, NULL, ClearBspScratch);
6480         j = 0;
6481         ipp->alist [j].name = StringSave ("     ");
6482         ipp->alist [j].value = (UIEnum) 0;
6483         for (j = 1; j <= ipp->count; j++) {
6484           sip = ipp->sip_list [j];
6485           if (sip != NULL) {
6486             bsp = BioseqFindCore (sip);
6487             if (bsp == NULL) {
6488               bsp = BioseqLockById (sip);
6489               BioseqUnlock (bsp);
6490             }
6491             if (bsp != NULL)
6492             {
6493               ipp->lengths [j] = bsp->length;
6494               sip = SeqIdFindWorst (bsp->id);
6495             }
6496             SeqIdWrite (sip, str, PRINTID_REPORT, sizeof (str));
6497             ptr = StringChr (str, '|');
6498             showIdTags = FALSE;
6499             if (ptr == NULL) {
6500               ptr = str;
6501             } else if (showIdTags) {
6502               ptr = str;
6503             } else {
6504               ptr++;
6505             }
6506             ipp->alist [j].name = StringSave (ptr);
6507             ipp->alist [j].value = (UIEnum) j;
6508           }
6509         }
6510         /* add end of list marker */
6511         j = ipp->count + 1;
6512         ipp->alist [j].name = NULL;
6513         ipp->alist [j].value = (UIEnum) 0;
6514       }
6515 #ifdef WIN_MOTIF
6516       if (ipp->count > 31) {
6517         if (ipp->seqid_col > -1)
6518         {
6519           interval_types [ipp->seqid_col] = TAGLIST_LIST;
6520         }
6521         if (ipp->aln_col > -1)
6522         {
6523           interval_types [ipp->aln_col] = TAGLIST_LIST;
6524         }
6525       } else {
6526         interval_types [2] = TAGLIST_POPUP;
6527         interval_types [3] = TAGLIST_POPUP;
6528         interval_types [4] = TAGLIST_POPUP;
6529       }
6530 #endif
6531 
6532     } else {
6533       ipp->alist = MemNew (sizeof (EnumFieldAssoc) * (size_t) 4);
6534       if (ipp->alist != NULL) {
6535         j = 0;
6536         ipp->alist [j].name = StringSave ("     ");
6537         ipp->alist [j].value = (UIEnum) 0;
6538         j = 1;
6539         ipp->alist [j].name = NULL;
6540         ipp->alist [j].value = (UIEnum) 0;
6541 
6542       }
6543     }
6544 
6545     ipp->alists [0] = NULL;
6546     ipp->alists [1] = NULL;
6547     ipp->alists [2] = NULL;
6548     ipp->alists [3] = NULL;
6549     ipp->alists [4] = NULL;
6550     if (ipp->strand_col > -1)
6551     {
6552       ipp->alists [ipp->strand_col] = strand_alist;
6553     }
6554     if (ipp->seqid_col > -1)
6555     {
6556       ipp->alists [ipp->seqid_col] = ipp->alist;
6557     }
6558     if (ipp->aln_col > -1)
6559     {
6560       ipp->alists [ipp->aln_col] = ipp->aln_alist;
6561     }
6562 
6563     q = NULL;
6564     if (showPartials) {
6565       q = HiddenGroup (m, 4, 0, NULL);
6566       SetGroupSpacing (q, 20, 2);
6567       if (nucsOK) {
6568         ipp->partial5 = CheckBox (q, "5' Partial", ChangedPartialProc);
6569       } else {
6570         ipp->partial5 = CheckBox (q, "NH2 Partial", ChangedPartialProc);
6571       }
6572       SetObjectExtra (ipp->partial5, ipp, NULL);
6573       if (nucsOK) {
6574         ipp->partial3 = CheckBox (q, "3' Partial", ChangedPartialProc);
6575       } else {
6576         ipp->partial3 = CheckBox (q, "CO2H Partial", ChangedPartialProc);
6577       }
6578       SetObjectExtra (ipp->partial3, ipp, NULL);
6579     }
6580 
6581     f = HiddenGroup (m, 5, 0, NULL);
6582     p_from = StaticPrompt (f, "From", 5 * stdCharWidth, 0, programFont, 'c');
6583     p_to = StaticPrompt (f, "To", 5 * stdCharWidth, 0, programFont, 'c');
6584     p1 = NULL;
6585     p2 = NULL;
6586     p3 = NULL;
6587     if (ipp->strand_col > -1)
6588     {
6589       p1 = StaticPrompt (f, "Strand", 0, 0, programFont, 'c');
6590     }
6591     if (ipp->seqid_col > -1)
6592     {
6593       p2 = StaticPrompt (f, "SeqID", 0, 0, programFont, 'c');
6594     }
6595     if (ipp->aln_col > -1)
6596     {
6597       p3 = StaticPrompt (f, "Alignment", 0, 0, programFont, 'c');
6598     }
6599 
6600     f = HiddenGroup (m, 0, 4, NULL);
6601     SetGroupSpacing (f, 0, 0);
6602 
6603     num_cols = 2;
6604     if (ipp->strand_col > -1)
6605     {
6606       num_cols ++;
6607     }
6608     if (ipp->seqid_col > -1)
6609     {
6610       num_cols ++;
6611     }
6612     if (ipp->aln_col > -1)
6613     {
6614       num_cols ++;
6615     }
6616 
6617     ipp->ivals = CreateTagListDialogEx3 (f, rows, num_cols, spacing,
6618                                         interval_types, interval_widths, ipp->alists,
6619                                         useBar, FALSE, NULL, NULL,
6620                                         ipp->callbacks, callback_data, FALSE, TRUE);
6621 
6622     /* put back static interval_types values that may have been changed */
6623     interval_types [2] = TAGLIST_POPUP;
6624     interval_types [3] = TAGLIST_POPUP;
6625     interval_types [4] = TAGLIST_POPUP;
6626     btn_grp = HiddenGroup (m, 2, 0, NULL);
6627     SetGroupSpacing (btn_grp, 10, 10);
6628     ipp->nullsBetween = CheckBox (btn_grp, "'order' (intersperse intervals with gaps)", ChangedPartialProc);
6629     SetObjectExtra (ipp->nullsBetween, ipp, NULL);
6630     b = PushButton (btn_grp, "Insert First Location", InsertFirstLocation);
6631     SetObjectExtra (b, ipp->ivals, NULL);
6632 
6633     AlignObjects (ALIGN_CENTER, (HANDLE) ipp->ivals,
6634                   (HANDLE) q, (HANDLE) btn_grp, NULL);
6635     tlp = (TagListPtr) GetObjectExtra (ipp->ivals);
6636     if (tlp != NULL) {
6637       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [0], (HANDLE) p_from, NULL);
6638       AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [1], (HANDLE) p_to, NULL);
6639       if (ipp->strand_col > -1)
6640       {
6641         AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [ipp->strand_col], (HANDLE) p1, NULL);
6642       }
6643       if (ipp->seqid_col > -1)
6644       {
6645         AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [ipp->seqid_col], (HANDLE) p2, NULL);
6646       }
6647       if (ipp->aln_col > -1)
6648       {
6649         AlignObjects (ALIGN_JUSTIFY, (HANDLE) tlp->control [ipp->aln_col], (HANDLE) p3, NULL);
6650       }
6651     }
6652   }
6653 
6654   return (DialoG) p;
6655 }
6656 
6657 typedef struct intervalchoice
6658 {
6659   DIALOG_MESSAGE_BLOCK
6660   GrouP  seq_or_aln;
6661   DialoG aln_dlg;
6662   DialoG seq_dlg;
6663 } IntervalChoiceData, PNTR IntervalChoicePtr;
6664 
IntervalChoiceCallback(Pointer userdata)6665 static void IntervalChoiceCallback (Pointer userdata)
6666 {
6667   IntervalChoicePtr dlg;
6668   SeqLocPtr         slp, slp_tmp;
6669   Boolean           ok_for_aln = FALSE;
6670   BioseqPtr         bsp;
6671   SeqAlignPtr       salp, salp_next;
6672 
6673   if (userdata == NULL)
6674   {
6675     return;
6676   }
6677 
6678   dlg = (IntervalChoicePtr) userdata;
6679 
6680   if (GetValue (dlg->seq_or_aln) == 1)
6681   {
6682     slp = DialogToPointer (dlg->seq_dlg);
6683     if (slp != NULL)
6684     {
6685       ok_for_aln = TRUE;
6686       slp_tmp = SeqLocFindNext (slp, NULL);
6687       while (slp_tmp != NULL && ok_for_aln)
6688       {
6689         bsp = BioseqFindFromSeqLoc (slp_tmp);
6690         salp = FindAlignmentsForBioseq (bsp);
6691         if (salp == NULL)
6692         {
6693           ok_for_aln = FALSE;
6694         }
6695         else
6696         {
6697           while (salp != NULL)
6698           {
6699             salp_next = salp->next;
6700             salp->next = NULL;
6701             salp = SeqAlignFree (salp);
6702             salp = salp_next;
6703           }
6704         }
6705         slp_tmp = SeqLocFindNext (slp, slp_tmp);
6706       }
6707     }
6708     if (ok_for_aln)
6709     {
6710       Enable (dlg->seq_or_aln);
6711     }
6712     else
6713     {
6714       Disable (dlg->seq_or_aln);
6715     }
6716   }
6717 }
6718 
SeqLocToIntervalChoiceEditor(DialoG d,Pointer userdata)6719 static void SeqLocToIntervalChoiceEditor (DialoG d, Pointer userdata)
6720 {
6721   IntervalChoicePtr dlg;
6722 
6723   dlg = (IntervalChoicePtr) GetObjectExtra (d);
6724   if (dlg == NULL)
6725   {
6726     return;
6727   }
6728   PointerToDialog (dlg->seq_dlg, userdata);
6729   PointerToDialog (dlg->aln_dlg, userdata);
6730   IntervalChoiceCallback (dlg);
6731 }
6732 
IntervalChoiceEditorToSeqLoc(DialoG d)6733 static Pointer IntervalChoiceEditorToSeqLoc (DialoG d)
6734 {
6735   IntervalChoicePtr dlg;
6736 
6737   dlg = (IntervalChoicePtr) GetObjectExtra (d);
6738   if (dlg == NULL)
6739   {
6740     return NULL;
6741   }
6742   if (GetValue (dlg->seq_or_aln) == 1)
6743   {
6744     return DialogToPointer (dlg->seq_dlg);
6745   }
6746   else
6747   {
6748     return DialogToPointer (dlg->aln_dlg);
6749   }
6750 }
6751 
6752 
WriteIntervalChoiceDialog(DialoG d,CharPtr filename)6753 static Boolean WriteIntervalChoiceDialog (DialoG d, CharPtr filename)
6754 
6755 {
6756   AsnIoPtr          aip;
6757   IntervalChoicePtr dlg;
6758   SeqLocPtr         slp;
6759   Char              path [PATH_MAX];
6760 #ifdef WIN_MAC
6761   FILE            *f;
6762 #endif
6763 
6764   path [0] = '\0';
6765   StringNCpy_0 (path, filename, sizeof (path));
6766   dlg = (IntervalChoicePtr) GetObjectExtra (d);
6767   if (dlg != NULL) {
6768     if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
6769 #ifdef WIN_MAC
6770       f = FileOpen (path, "r");
6771       if (f != NULL) {
6772         FileClose (f);
6773       } else {
6774         FileCreate (path, "TEXT", "ttxt");
6775       }
6776 #endif
6777       aip = AsnIoOpen (path, "w");
6778       if (aip != NULL) {
6779         slp = IntervalChoiceEditorToSeqLoc (dlg->dialog);
6780         SeqLocAsnWrite (slp, aip, NULL);
6781         AsnIoClose (aip);
6782         slp = SeqLocFree (slp);
6783         return TRUE;
6784       }
6785     }
6786   }
6787   return FALSE;
6788 }
6789 
6790 
ReadIntervalChoiceDialog(DialoG d,CharPtr filename)6791 static Boolean ReadIntervalChoiceDialog (DialoG d, CharPtr filename)
6792 
6793 {
6794   AsnIoPtr          aip;
6795   IntervalChoicePtr dlg;
6796   SeqLocPtr         slp;
6797   Char              path [PATH_MAX];
6798 
6799   path [0] = '\0';
6800   StringNCpy_0 (path, filename, sizeof (path));
6801   dlg = (IntervalChoicePtr) GetObjectExtra (d);
6802   if (dlg != NULL) {
6803     if (path [0] != '\0' || GetInputFileName (path, sizeof (path), "", "TEXT")) {
6804       aip = AsnIoOpen (path, "r");
6805       if (aip != NULL) {
6806         slp = SeqLocAsnRead (aip, NULL);
6807         AsnIoClose (aip);
6808         if (slp != NULL) {
6809           SeqLocToIntervalChoiceEditor (dlg->dialog, slp);
6810           slp = SeqLocFree (slp);
6811           Update ();
6812           return TRUE;
6813         }
6814       }
6815     }
6816   }
6817   return FALSE;
6818 }
6819 
6820 
IntervalChoiceEditorMessage(DialoG d,Int2 mssg)6821 static void IntervalChoiceEditorMessage (DialoG d, Int2 mssg)
6822 
6823 {
6824   IntervalChoicePtr dlg;
6825 
6826   dlg = (IntervalChoicePtr) GetObjectExtra (d);
6827   if (dlg != NULL) {
6828     if (GetValue (dlg->seq_or_aln) == 1)
6829     {
6830       SendMessageToDialog (dlg->seq_dlg, mssg);
6831     }
6832     else
6833     {
6834       SendMessageToDialog (dlg->aln_dlg, mssg);
6835     }
6836   }
6837 }
6838 
TestIntervalChoiceEditor(DialoG d)6839 static ValNodePtr TestIntervalChoiceEditor (DialoG d)
6840 {
6841   IntervalChoicePtr dlg;
6842 
6843   dlg = (IntervalChoicePtr) GetObjectExtra (d);
6844   if (dlg == NULL)
6845   {
6846     return NULL;
6847   }
6848   else if (GetValue (dlg->seq_or_aln) == 1)
6849   {
6850     return TestDialog (dlg->seq_dlg);
6851   }
6852   else
6853   {
6854     return TestDialog (dlg->aln_dlg);
6855   }
6856 }
6857 
DisplayErrorMessagesOk(ButtoN b)6858 static void DisplayErrorMessagesOk (ButtoN b)
6859 {
6860   BoolPtr pdone;
6861 
6862   pdone = (BoolPtr) GetObjectExtra (b);
6863   if (pdone != NULL)
6864   {
6865     *pdone = TRUE;
6866   }
6867 }
6868 
DisplayErrorMessages(CharPtr title,ValNodePtr err_list)6869 extern void DisplayErrorMessages (CharPtr title, ValNodePtr err_list)
6870 {
6871   WindoW     w;
6872   GrouP      h;
6873   DoC        doc;
6874   ButtoN     b;
6875   ValNodePtr vnp;
6876   Boolean    done = FALSE;
6877 
6878   w = MovableModalWindow(-20, -13, -10, -10, title, NULL);
6879   h = HiddenGroup (w, -1, 0, NULL);
6880   SetGroupSpacing (h, 10, 10);
6881 
6882   doc = DocumentPanel (h, stdCharWidth * 27, stdLineHeight * 8);
6883   SetDocAutoAdjust (doc, TRUE);
6884   for (vnp = err_list; vnp != NULL; vnp = vnp->next)
6885   {
6886     if (!StringHasNoText (vnp->data.ptrvalue))
6887     {
6888       AppendText (doc, vnp->data.ptrvalue, NULL, NULL, programFont);
6889     }
6890   }
6891   b = PushButton (h, "OK", DisplayErrorMessagesOk);
6892   SetObjectExtra (b, &done, NULL);
6893   AlignObjects (ALIGN_CENTER, (HANDLE) doc,
6894                               (HANDLE) b,
6895                               NULL);
6896   Show (w);
6897   Select (w);
6898   while (!done)
6899   {
6900     ProcessExternalEvent ();
6901     Update ();
6902   }
6903   ProcessAnEvent ();
6904   Remove (w);
6905 }
6906 
ShowIntervalChoice(IntervalChoicePtr dlg)6907 static void ShowIntervalChoice (IntervalChoicePtr dlg)
6908 {
6909   if (dlg == NULL)
6910   {
6911     return;
6912   }
6913   if (GetValue (dlg->seq_or_aln) == 1)
6914   {
6915     Hide (dlg->aln_dlg);
6916     Update ();
6917     Show (dlg->seq_dlg);
6918     Update ();
6919   }
6920   else
6921   {
6922     Hide (dlg->seq_dlg);
6923     Update ();
6924     Show (dlg->aln_dlg);
6925     Update ();
6926   }
6927 }
6928 
ChangeIntervalChoice(GrouP g)6929 static void ChangeIntervalChoice (GrouP g)
6930 {
6931   IntervalChoicePtr dlg;
6932   SeqLocPtr         slp;
6933   ValNodePtr        err_list = NULL;
6934   CharPtr           title = NULL;
6935 
6936   dlg = (IntervalChoicePtr) GetObjectExtra (g);
6937   if (dlg == NULL)
6938   {
6939     return;
6940   }
6941   if (GetValue (dlg->seq_or_aln) == 1)
6942   {
6943     title = "Unable to translate to sequence coordinates";
6944     err_list = TestDialog (dlg->aln_dlg);
6945     if (err_list == NULL)
6946     {
6947       slp = DialogToPointer (dlg->aln_dlg);
6948       PointerToDialog (dlg->seq_dlg, slp);
6949       slp = SeqLocFree (slp);
6950       err_list = TestDialog (dlg->seq_dlg);
6951     }
6952     if (err_list != NULL)
6953     {
6954       SetValue (dlg->seq_or_aln, 2);
6955     }
6956   }
6957   else
6958   {
6959     title = "Unable to translate to alignment coordinates";
6960     err_list = TestDialog (dlg->seq_dlg);
6961     if (err_list == NULL)
6962     {
6963       slp = DialogToPointer (dlg->seq_dlg);
6964       PointerToDialog (dlg->aln_dlg, slp);
6965       slp = SeqLocFree (slp);
6966       err_list = TestDialog (dlg->aln_dlg);
6967     }
6968     if (err_list != NULL)
6969     {
6970       SetValue (dlg->seq_or_aln, 1);
6971     }
6972   }
6973   ShowIntervalChoice (dlg);
6974   if (err_list != NULL)
6975   {
6976     DisplayErrorMessages (title, err_list);
6977     err_list = ValNodeFreeData (err_list);
6978   }
6979 }
6980 
CreateIntervalEditorDialogAlnChoice(GrouP h,CharPtr title,Uint2 rows,Int2 spacing,SeqEntryPtr sep,Boolean nucsOK,Boolean protsOK,Boolean useBar,Boolean showPartials,Boolean allowGaps,FeatureFormPtr ffp,IntEdPartialProc proc)6981 static DialoG CreateIntervalEditorDialogAlnChoice (GrouP h, CharPtr title, Uint2 rows,
6982                                             Int2 spacing, SeqEntryPtr sep,
6983                                             Boolean nucsOK, Boolean protsOK,
6984                                             Boolean useBar, Boolean showPartials,
6985                                             Boolean allowGaps, FeatureFormPtr ffp,
6986                                             IntEdPartialProc proc)
6987 {
6988   SeqAlignPtr       salp_list = NULL;
6989   GrouP             p, g;
6990   IntervalChoicePtr dlg;
6991 
6992   VisitAnnotsInSep (sep, &salp_list, GetAlignmentsInSeqEntryCallback);
6993   if (salp_list == NULL)
6994   {
6995     return CreateIntervalEditorDialogExEx (h, title, rows, spacing, sep,
6996                                          nucsOK, protsOK, useBar, showPartials,
6997                                          allowGaps, ffp, proc, FALSE, TRUE,
6998                                          NULL, NULL, FALSE);
6999   }
7000   else
7001   {
7002     dlg = (IntervalChoicePtr) MemNew (sizeof (IntervalChoiceData));
7003     if (dlg == NULL)
7004     {
7005       return NULL;
7006     }
7007 
7008     p = HiddenGroup (h, -1, 0, NULL);
7009     SetGroupSpacing (p, 10, 10);
7010     SetObjectExtra (p, dlg, StdCleanupExtraProc);
7011 
7012     dlg->dialog = (DialoG) p;
7013     dlg->todialog = SeqLocToIntervalChoiceEditor;
7014     dlg->fromdialog = IntervalChoiceEditorToSeqLoc;
7015     dlg->dialogmessage = IntervalChoiceEditorMessage;
7016     dlg->testdialog = TestIntervalChoiceEditor;
7017     dlg->exportdialog = WriteIntervalChoiceDialog;
7018     dlg->importdialog = ReadIntervalChoiceDialog;
7019 
7020     g = HiddenGroup (p, 0, 0, NULL);
7021     dlg->seq_dlg = CreateIntervalEditorDialogExEx (g, title, rows, spacing, sep,
7022                                          nucsOK, protsOK, useBar, showPartials,
7023                                          allowGaps, ffp, proc, FALSE, TRUE,
7024                                          IntervalChoiceCallback, dlg, FALSE);
7025 
7026     dlg->aln_dlg = CreateIntervalEditorDialogExEx (g, title, rows, spacing, sep,
7027                                          nucsOK, protsOK, useBar, showPartials,
7028                                          allowGaps, ffp, proc, TRUE, TRUE,
7029                                          IntervalChoiceCallback, dlg, FALSE);
7030     AlignObjects (ALIGN_CENTER, (HANDLE)dlg->seq_dlg, (HANDLE) dlg->aln_dlg, NULL);
7031     dlg->seq_or_aln = HiddenGroup (p, 2, 0, ChangeIntervalChoice);
7032     SetObjectExtra (dlg->seq_or_aln, dlg, NULL);
7033     RadioButton (dlg->seq_or_aln, "Sequence Coordinates");
7034     RadioButton (dlg->seq_or_aln, "Alignment Coordinates");
7035     SetValue (dlg->seq_or_aln, 1);
7036 
7037     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) dlg->seq_or_aln, NULL);
7038     ShowIntervalChoice (dlg);
7039     IntervalChoiceCallback (dlg);
7040     return (DialoG) p;
7041   }
7042 }
7043 
CreateIntervalEditorDialogEx(GrouP h,CharPtr title,Uint2 rows,Int2 spacing,SeqEntryPtr sep,Boolean nucsOK,Boolean protsOK,Boolean useBar,Boolean showPartials,Boolean allowGaps,FeatureFormPtr ffp,IntEdPartialProc proc)7044 extern DialoG CreateIntervalEditorDialogEx (GrouP h, CharPtr title, Uint2 rows,
7045                                             Int2 spacing, SeqEntryPtr sep,
7046                                             Boolean nucsOK, Boolean protsOK,
7047                                             Boolean useBar, Boolean showPartials,
7048                                             Boolean allowGaps, FeatureFormPtr ffp,
7049                                             IntEdPartialProc proc)
7050 {
7051   return CreateIntervalEditorDialogAlnChoice (h, title, rows, spacing, sep,
7052                                          nucsOK, protsOK, useBar, showPartials,
7053                                          allowGaps, ffp, proc);
7054 }
7055 
CreateIntervalEditorDialog(GrouP h,CharPtr title,Uint2 rows,Int2 spacing,SeqEntryPtr sep,Boolean nucsOK,Boolean protsOK)7056 extern DialoG CreateIntervalEditorDialog (GrouP h, CharPtr title, Uint2 rows,
7057                                           Int2 spacing, SeqEntryPtr sep,
7058                                           Boolean nucsOK, Boolean protsOK)
7059 
7060 {
7061   return CreateIntervalEditorDialogEx (h, title, rows, spacing, sep,
7062                                        nucsOK, protsOK, TRUE, TRUE, FALSE,
7063                                        NULL, NULL);
7064 }
7065 
ValNodePtrToVisStringDialog(DialoG d,Pointer data)7066 static void ValNodePtrToVisStringDialog (DialoG d, Pointer data)
7067 
7068 {
7069   ValNodePtr   head;
7070   Int2         j;
7071   ValNodePtr   list;
7072   CharPtr      str;
7073   TagListPtr   tlp;
7074   ValNodePtr   vnp;
7075 
7076   tlp = (TagListPtr) GetObjectExtra (d);
7077   list = (ValNodePtr) data;
7078   if (tlp != NULL) {
7079     head = NULL;
7080     while (list != NULL) {
7081       vnp = ValNodeNew (head);
7082       if (head == NULL) {
7083         head = vnp;
7084       }
7085       if (vnp != NULL) {
7086         str = MemNew (StringLen ((CharPtr) list->data.ptrvalue) + 3);
7087         if (str != NULL) {
7088           StringCpy (str, (CharPtr) list->data.ptrvalue);
7089           StringCat (str, "\n");
7090         }
7091         vnp->data.ptrvalue = str;
7092       }
7093       list = list->next;
7094     }
7095     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
7096     tlp->vnp = head;
7097     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
7098     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
7099     }
7100     tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
7101     CorrectBarMax (tlp->bar, tlp->max);
7102     CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
7103   }
7104 }
7105 
VisStringDialogToValNodePtr(DialoG d)7106 static Pointer VisStringDialogToValNodePtr (DialoG d)
7107 
7108 {
7109   Char         ch;
7110   ValNodePtr   head;
7111   Int2         j;
7112   Int2         len;
7113   ValNodePtr   list;
7114   Boolean      okay;
7115   CharPtr      str;
7116   TagListPtr   tlp;
7117   ValNodePtr   vnp;
7118 
7119   head = NULL;
7120   tlp = (TagListPtr) GetObjectExtra (d);
7121   if (tlp != NULL && tlp->vnp != NULL) {
7122     list = NULL;
7123     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
7124       str = (CharPtr) vnp->data.ptrvalue;
7125       okay = FALSE;
7126       len = StringLen (str);
7127       for (j = 0; j < len; j++) {
7128         ch = str [j];
7129         if (ch != ' ' && ch != '\t' && ch != '\n') {
7130           okay = TRUE;
7131         }
7132       }
7133       if (okay) {
7134         list = ValNodeNew (list);
7135         if (head == NULL) {
7136           head = list;
7137         }
7138         if (list != NULL) {
7139           list->choice = 0;
7140           list->data.ptrvalue = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
7141         }
7142       }
7143     }
7144   }
7145   return (Pointer) head;
7146 }
7147 
DbtagPtrToDbtagDialog(DialoG d,Pointer data,Boolean readOnly)7148 static void DbtagPtrToDbtagDialog (DialoG d, Pointer data, Boolean readOnly)
7149 
7150 {
7151   DbtagPtr     dp;
7152   ValNodePtr   head;
7153   Int2         j;
7154   size_t       len;
7155   ValNodePtr   list;
7156   ObjectIdPtr  oid;
7157   CharPtr      ptr;
7158   CharPtr      str;
7159   TagListPtr   tlp;
7160   Char         tmp [16];
7161   ValNodePtr   vnp;
7162 
7163   tlp = (TagListPtr) GetObjectExtra (d);
7164   list = (ValNodePtr) data;
7165   if (tlp != NULL) {
7166     head = NULL;
7167     while (list != NULL) {
7168       vnp = ValNodeNew (head);
7169       if (head == NULL) {
7170         head = vnp;
7171       }
7172       if (vnp != NULL) {
7173         dp = (DbtagPtr) list->data.ptrvalue;
7174         if (dp != NULL && dp->db != NULL && dp->tag != NULL) {
7175           oid = dp->tag;
7176           ptr = NULL;
7177           if (oid->str != NULL) {
7178             ptr = oid->str;
7179             if (StringNCmp (ptr, "HGNC:", 5) == 0) {
7180               ptr += 5;
7181             } else if (StringNCmp (ptr, "MGI:", 4) == 0) {
7182               ptr += 4;
7183             }
7184           } else {
7185             sprintf (tmp, "%ld", (long) oid->id);
7186             ptr = tmp;
7187           }
7188           len = StringLen (dp->db) + StringLen (ptr);
7189           str = MemNew (len + 4);
7190           if (str != NULL) {
7191             StringCpy (str, dp->db);
7192             StringCat (str, "\t");
7193             StringCat (str, ptr);
7194             StringCat (str, "\n");
7195           }
7196           vnp->data.ptrvalue = str;
7197         }
7198       }
7199       list = list->next;
7200     }
7201     SendMessageToDialog (tlp->dialog, VIB_MSG_RESET);
7202     tlp->vnp = head;
7203     SendMessageToDialog (tlp->dialog, VIB_MSG_REDRAW);
7204     for (j = 0, vnp = tlp->vnp; vnp != NULL; j++, vnp = vnp->next) {
7205     }
7206     if (readOnly) {
7207       tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows));
7208       CorrectBarMax (tlp->bar, tlp->max);
7209       CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
7210       if (tlp->max > 0) {
7211         SafeShow (tlp->bar);
7212       } else {
7213         SafeHide (tlp->bar);
7214       }
7215     } else {
7216       tlp->max = MAX ((Int2) 0, (Int2) (j - tlp->rows + 1));
7217       CorrectBarMax (tlp->bar, tlp->max);
7218       CorrectBarPage (tlp->bar, tlp->rows - 1, tlp->rows - 1);
7219     }
7220   }
7221 }
7222 
DbtagPtrToRODbtagDialog(DialoG d,Pointer data)7223 static void DbtagPtrToRODbtagDialog (DialoG d, Pointer data)
7224 
7225 {
7226   DbtagPtrToDbtagDialog (d, data, TRUE);
7227 }
7228 
DbtagPtrToRWDbtagDialog(DialoG d,Pointer data)7229 static void DbtagPtrToRWDbtagDialog (DialoG d, Pointer data)
7230 
7231 {
7232   DbtagPtrToDbtagDialog (d, data, FALSE);
7233 }
7234 
DbtagDialogToDbtagPtr(DialoG d)7235 static Pointer DbtagDialogToDbtagPtr (DialoG d)
7236 
7237 {
7238   Boolean      alldigits;
7239   Char         ch;
7240   DbtagPtr     dp;
7241   ValNodePtr   head;
7242   Int2         j;
7243   Boolean      leadingzero;
7244   Int2         len;
7245   ValNodePtr   list;
7246   Boolean      notallzero;
7247   Int2         num_digits;
7248   ObjectIdPtr  oid;
7249   Boolean      okay;
7250   CharPtr      ptr;
7251   CharPtr      str;
7252   TagListPtr   tlp;
7253   CharPtr      tmp;
7254   long int     val;
7255   ValNodePtr   vnp;
7256 
7257   head = NULL;
7258   tlp = (TagListPtr) GetObjectExtra (d);
7259   if (tlp != NULL && tlp->vnp != NULL) {
7260     list = NULL;
7261     for (vnp = tlp->vnp; vnp != NULL; vnp = vnp->next) {
7262       str = (CharPtr) vnp->data.ptrvalue;
7263       okay = FALSE;
7264       len = StringLen (str);
7265       for (j = 0; j < len; j++) {
7266         ch = str [j];
7267         if (ch != ' ' && ch != '\t' && ch != '\n') {
7268           okay = TRUE;
7269         }
7270       }
7271       if (okay) {
7272         list = ValNodeNew (list);
7273         if (head == NULL) {
7274           head = list;
7275         }
7276         if (list != NULL) {
7277           list->choice = 0;
7278           dp = DbtagNew ();
7279           list->data.ptrvalue = (Pointer) dp;
7280           if (dp != NULL) {
7281             dp->db = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
7282             oid = ObjectIdNew ();
7283             dp->tag = oid;
7284             if (oid != NULL) {
7285               tmp = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
7286               TrimSpacesAroundString (tmp);
7287               if (tmp != NULL) {
7288                 SetObjectIdString(oid, tmp, ExistingTextOption_replace_old);
7289               } else {
7290                 oid->str = StringSave ("?");
7291               }
7292             }
7293           }
7294         }
7295       }
7296     }
7297   }
7298   return (Pointer) head;
7299 }
7300 
7301 Uint2 visstring_types [] = {
7302   TAGLIST_TEXT, TAGLIST_TEXT
7303 };
7304 
7305 Uint2 readonlystring_types [] = {
7306   TAGLIST_PROMPT, TAGLIST_PROMPT
7307 };
7308 
7309 Uint2 visstring_widths [] = {
7310   0, 0, 0, 0
7311 };
7312 
CreateVisibleStringDialog(GrouP h,Uint2 rows,Int2 spacing,Int2 width)7313 extern DialoG CreateVisibleStringDialog (GrouP h, Uint2 rows,
7314                                          Int2 spacing, Int2 width)
7315 
7316 {
7317   visstring_widths [0] = width;
7318   return CreateTagListDialog (h, rows, 1, spacing,
7319                               visstring_types, visstring_widths, NULL,
7320                               ValNodePtrToVisStringDialog,
7321                               VisStringDialogToValNodePtr);
7322 }
7323 
CreateDbtagDialog(GrouP h,Uint2 rows,Int2 spacing,Int2 width1,Int2 width2)7324 extern DialoG CreateDbtagDialog (GrouP h, Uint2 rows, Int2 spacing,
7325                                  Int2 width1, Int2 width2)
7326 
7327 {
7328   DialoG      d;
7329   TagListPtr  tlp;
7330 
7331   visstring_widths [0] = width1;
7332   visstring_widths [1] = width2;
7333   if (GetAppProperty ("ReadOnlyDbTags") == NULL) {
7334     return CreateTagListDialog (h, rows, 2, spacing,
7335                                 visstring_types, visstring_widths, NULL,
7336                                 DbtagPtrToRWDbtagDialog,
7337                                 DbtagDialogToDbtagPtr);
7338   } else {
7339     d = CreateTagListDialog (h, rows, 2, spacing,
7340                              readonlystring_types, visstring_widths, NULL,
7341                              DbtagPtrToRODbtagDialog,
7342                              DbtagDialogToDbtagPtr);
7343     tlp = (TagListPtr) GetObjectExtra (d);
7344     if (tlp != NULL) {
7345       Hide (tlp->bar);
7346     }
7347     return d;
7348   }
7349 }
7350 
7351 /* ValueList Editor */
combine_strings(CharPtr s,CharPtr add)7352 static CharPtr combine_strings (CharPtr s, CharPtr add)
7353 {
7354   CharPtr total;
7355   if (StringHasNoText (add))
7356   {
7357     return s;
7358   }
7359   if (StringHasNoText (s))
7360   {
7361     s = MemFree (s);
7362     s = StringSave (add);
7363   }
7364   else
7365   {
7366     total = (CharPtr) MemNew (sizeof (Char) * (StringLen (s) + StringLen (add) + 2));
7367     sprintf (total, "%s;%s", s, add);
7368     s = MemFree (s);
7369     s = total;
7370   }
7371   return s;
7372 }
7373 
7374 
7375 
7376 typedef struct simpletextvalueedit {
7377   DIALOG_MESSAGE_BLOCK
7378   TaglistCallback change_notify;
7379   Pointer         change_userdata;
7380   TexT text;
7381 } SimpleTextValueEditData, PNTR SimpleTextValueEditPtr;
7382 
SimpleTextValueEditChange(TexT t)7383 static void SimpleTextValueEditChange (TexT t)
7384 {
7385   SimpleTextValueEditPtr dlg;
7386   dlg = (SimpleTextValueEditPtr) GetObjectExtra (t);
7387   if (dlg != NULL && dlg->change_notify != NULL)
7388   {
7389     (dlg->change_notify) (dlg->change_userdata);
7390   }
7391 }
7392 
StringToSimpleTextValueEditDialog(DialoG d,Pointer data)7393 static void StringToSimpleTextValueEditDialog (DialoG d, Pointer data)
7394 {
7395   SimpleTextValueEditPtr dlg;
7396   dlg = (SimpleTextValueEditPtr) GetObjectExtra (d);
7397 
7398   if (dlg != NULL)
7399   {
7400     SetTitle (dlg->text, (CharPtr) data);
7401     if (dlg->change_notify != NULL)
7402     {
7403       (dlg->change_notify) (dlg->change_userdata);
7404     }
7405   }
7406 }
7407 
7408 
SimpleTextValueEditDialogToString(DialoG d)7409 static Pointer SimpleTextValueEditDialogToString (DialoG d)
7410 {
7411   SimpleTextValueEditPtr dlg;
7412   dlg = (SimpleTextValueEditPtr) GetObjectExtra (d);
7413 
7414   if (dlg != NULL)
7415   {
7416     return SaveStringFromText (dlg->text);
7417   }
7418   else
7419   {
7420     return NULL;
7421   }
7422 }
7423 
SimpleTextValueEditDialog(GrouP h,Int2 width,ValueListParentPtr parent,TaglistCallback change_notify,Pointer change_userdata)7424 static DialoG SimpleTextValueEditDialog (GrouP h, Int2 width, ValueListParentPtr parent, TaglistCallback change_notify, Pointer change_userdata)
7425 {
7426   SimpleTextValueEditPtr dlg;
7427   GrouP           p;
7428 
7429   p = HiddenGroup (h, -1, 0, NULL);
7430   SetGroupSpacing (p, 10, 10);
7431   dlg = (SimpleTextValueEditPtr) MemNew (sizeof(SimpleTextValueEditData));
7432 
7433   SetObjectExtra (p, dlg, StdCleanupExtraProc);
7434   dlg->dialog = (DialoG) p;
7435   dlg->todialog = StringToSimpleTextValueEditDialog;
7436   dlg->fromdialog = SimpleTextValueEditDialogToString;
7437   dlg->testdialog = NULL;
7438   dlg->dialogmessage = NULL;
7439   dlg->change_notify = change_notify;
7440   dlg->change_userdata = change_userdata;
7441 
7442   dlg->text = DialogText (p, "", width, SimpleTextValueEditChange);
7443   SetObjectExtra (dlg->text, dlg, NULL);
7444   return (DialoG) p;
7445 }
7446 
7447 #define STRUCTURED_VALUE_EDIT_FIELDS \
7448   DIALOG_MESSAGE_BLOCK \
7449   TaglistCallback     change_notify; \
7450   Pointer             change_userdata; \
7451   GrouP               unparsable; \
7452   TexT                text; \
7453   ValueListParentPtr  parent; \
7454   DialoG              dlg; \
7455   ParseOK             parse_func;
7456 
7457 typedef struct structuredvalueeditdlg {
7458   STRUCTURED_VALUE_EDIT_FIELDS
7459 } StructuredValueEditDlgData, PNTR StructuredValueEditDlgPtr;
7460 
7461 
CopyUnparsableToNote(ButtoN b)7462 static void CopyUnparsableToNote (ButtoN b)
7463 {
7464   StructuredValueEditDlgPtr dlg;
7465   CharPtr                   old_note, new_note;
7466 
7467   dlg = (StructuredValueEditDlgPtr) GetObjectExtra (b);
7468 
7469   if (dlg != NULL && dlg->parent != NULL && dlg->parent->note != NULL)
7470   {
7471     old_note = SaveStringFromText (dlg->parent->note);
7472     new_note = SaveStringFromText (dlg->text);
7473     old_note = combine_strings (old_note, new_note);
7474     SetTitle (dlg->parent->note, old_note);
7475     new_note = MemFree (new_note);
7476     old_note = MemFree (old_note);
7477     SetTitle (dlg->text, "");
7478     Hide (dlg->unparsable);
7479     if (dlg != NULL && dlg->change_notify != NULL)
7480     {
7481       (dlg->change_notify) (dlg->change_userdata);
7482     }
7483   }
7484 }
7485 
7486 
EraseUnparsable(ButtoN b)7487 static void EraseUnparsable (ButtoN b)
7488 {
7489   StructuredValueEditDlgPtr dlg;
7490 
7491   dlg = (StructuredValueEditDlgPtr) GetObjectExtra (b);
7492 
7493   if (dlg != NULL)
7494   {
7495     SetTitle (dlg->text, "");
7496     Hide (dlg->unparsable);
7497     if (dlg != NULL && dlg->change_notify != NULL)
7498     {
7499       (dlg->change_notify) (dlg->change_userdata);
7500     }
7501   }
7502 }
7503 
7504 
StringToStructuredValueEditDialog(DialoG d,Pointer data)7505 static void StringToStructuredValueEditDialog (DialoG d, Pointer data)
7506 {
7507   StructuredValueEditDlgPtr dlg;
7508   CharPtr                   txt;
7509 
7510   dlg = (StructuredValueEditDlgPtr) GetObjectExtra (d);
7511 
7512   txt = (CharPtr) data;
7513 
7514   if (dlg != NULL)
7515   {
7516     if (StringHasNoText (txt) || (dlg->parse_func != NULL && (dlg->parse_func) (txt)))
7517     {
7518       PointerToDialog (dlg->dlg, txt);
7519       SetTitle (dlg->text, "");
7520       Hide (dlg->unparsable);
7521     }
7522     else
7523     {
7524       SetTitle (dlg->text, (CharPtr) data);
7525       Show (dlg->unparsable);
7526     }
7527     if (dlg->change_notify != NULL)
7528     {
7529       (dlg->change_notify) (dlg->change_userdata);
7530     }
7531   }
7532 }
7533 
7534 
StructuredValueEditDialogToString(DialoG d)7535 static Pointer StructuredValueEditDialogToString (DialoG d)
7536 {
7537   StructuredValueEditDlgPtr dlg;
7538   CharPtr                   txt = NULL, tmp;
7539 
7540   dlg = (StructuredValueEditDlgPtr) GetObjectExtra (d);
7541 
7542   if (dlg != NULL)
7543   {
7544     if (dlg->dlg == NULL)
7545     {
7546       txt = StringSave ("");
7547     }
7548     else
7549     {
7550       txt = DialogToPointer (dlg->dlg);
7551     }
7552 
7553     if (!TextHasNoText (dlg->text))
7554     {
7555       tmp = SaveStringFromText (dlg->text);
7556       txt = combine_strings (txt, tmp);
7557       tmp = MemFree (tmp);
7558     }
7559   }
7560   return txt;
7561 
7562 }
7563 
7564 
StructuredValueEditChange(TexT t)7565 static void StructuredValueEditChange (TexT t)
7566 {
7567   StructuredValueEditDlgPtr dlg;
7568   CharPtr                    txt, tmp;
7569 
7570   dlg = (StructuredValueEditDlgPtr) GetObjectExtra (t);
7571 
7572   if (TextHasNoText (dlg->text))
7573   {
7574     Hide (dlg->unparsable);
7575   }
7576   else if (dlg->dlg != NULL)
7577   {
7578     txt = SaveStringFromText(dlg->text);
7579     tmp = DialogToPointer (dlg->dlg);
7580     if (StringHasNoText (tmp) && dlg->parse_func != NULL && (dlg->parse_func)(txt))
7581     {
7582       PointerToDialog (dlg->dlg, txt);
7583       SetTitle (dlg->text, "");
7584       Hide (dlg->unparsable);
7585     }
7586     txt = MemFree (txt);
7587     tmp = MemFree (tmp);
7588   }
7589 
7590   if (dlg != NULL && dlg->change_notify != NULL)
7591   {
7592     (dlg->change_notify) (dlg->change_userdata);
7593   }
7594 }
7595 
7596 
7597 
7598 typedef struct truefalsevalueedit {
7599   STRUCTURED_VALUE_EDIT_FIELDS
7600 } TrueFalseValueEditData, PNTR TrueFalseValueEditPtr;
7601 
TrueFalseValueEditDialog(GrouP h,Int2 width,ValueListParentPtr parent,TaglistCallback change_notify,Pointer change_userdata)7602 static DialoG TrueFalseValueEditDialog (GrouP h, Int2 width, ValueListParentPtr parent, TaglistCallback change_notify, Pointer change_userdata)
7603 {
7604   TrueFalseValueEditPtr dlg;
7605   GrouP           p;
7606   ButtoN          b;
7607 
7608   p = HiddenGroup (h, 2, 0, NULL);
7609   SetGroupSpacing (p, 10, 10);
7610   dlg = (TrueFalseValueEditPtr) MemNew (sizeof(TrueFalseValueEditData));
7611 
7612   SetObjectExtra (p, dlg, StdCleanupExtraProc);
7613   dlg->dialog = (DialoG) p;
7614   dlg->todialog = StringToStructuredValueEditDialog;
7615   dlg->fromdialog = StructuredValueEditDialogToString;
7616   dlg->testdialog = NULL;
7617   dlg->dialogmessage = NULL;
7618   dlg->change_notify = change_notify;
7619   dlg->change_userdata = change_userdata;
7620   dlg->parent = parent;
7621 
7622   StaticPrompt (p, "TRUE", 0, 0, programFont, 'c');
7623 
7624   dlg->unparsable = HiddenGroup (p, 3, 0, NULL);
7625   SetGroupSpacing (dlg->unparsable, 10, 10);
7626   dlg->text = DialogText (dlg->unparsable, "", width - 15, StructuredValueEditChange);
7627   SetObjectExtra (dlg->text, dlg, NULL);
7628 
7629   b = PushButton (dlg->unparsable, "Copy to Note", CopyUnparsableToNote);
7630   SetObjectExtra (b, dlg, NULL);
7631 
7632   b = PushButton (dlg->unparsable, "Erase", EraseUnparsable);
7633   SetObjectExtra (b, dlg, NULL);
7634 
7635   Hide (dlg->unparsable);
7636 
7637   return (DialoG) p;
7638 }
7639 
7640 
7641 typedef struct latlondlg {
7642   DIALOG_MESSAGE_BLOCK
7643 
7644   PopuP dir_ns;
7645   PopuP dir_ew;
7646   TexT  deg_ns;
7647   TexT  deg_ew;
7648 
7649   TaglistCallback change_notify;
7650   Pointer change_userdata;
7651 
7652 } LatLonDlgData, PNTR LatLonDlgPtr;
7653 
7654 
ResetLatLonDlg(LatLonDlgPtr dlg)7655 static void ResetLatLonDlg (LatLonDlgPtr dlg)
7656 {
7657   if (dlg == NULL) return;
7658 
7659   SetTitle (dlg->deg_ns, "");
7660   SetValue (dlg->dir_ns, 1);
7661   SetTitle (dlg->deg_ew, "");
7662   SetValue (dlg->dir_ew, 1);
7663 }
7664 
7665 
StringToLatLonDlg(DialoG d,Pointer data)7666 static void StringToLatLonDlg (DialoG d, Pointer data)
7667 {
7668   LatLonDlgPtr dlg;
7669   CharPtr      str, ns, ew, tmp;
7670   Int4         len;
7671 
7672   dlg = (LatLonDlgPtr) GetObjectExtra (d);
7673   if (dlg == NULL) return;
7674 
7675   str = (CharPtr) data;
7676   if (str == NULL)
7677   {
7678     ResetLatLonDlg (dlg);
7679     return;
7680   }
7681 
7682   ew = str + StringLen (str) - 1;
7683   if (*ew != 'E' && *ew != 'W')
7684   {
7685     ResetLatLonDlg (dlg);
7686     return;
7687   }
7688 
7689   ns = StringChr (str, 'N');
7690   if (ns == NULL)
7691   {
7692     ns = StringChr (str, 'S');
7693   }
7694   if (ns == NULL)
7695   {
7696     ResetLatLonDlg (dlg);
7697     return;
7698   }
7699 
7700   len = ns - str + 1;
7701   tmp = (CharPtr) MemNew (sizeof (Char) * len);
7702   StringNCpy (tmp, str, len - 1);
7703   tmp [len - 1] = 0;
7704   TrimSpacesAroundString (tmp);
7705   SetTitle (dlg->deg_ns, tmp);
7706   tmp = MemFree (tmp);
7707   SetValue (dlg->dir_ns, *ns == 'N' ? 1 : 2);
7708 
7709   len = ew - ns;
7710   tmp = (CharPtr) MemNew (sizeof (Char) * len);
7711   StringNCpy (tmp, ns + 1, len - 1);
7712   tmp [len - 1] = 0;
7713   TrimSpacesAroundString (tmp);
7714   SetTitle (dlg->deg_ew, tmp);
7715   tmp = MemFree (tmp);
7716   SetValue (dlg->dir_ew, *ew == 'E' ? 1 : 2);
7717 
7718 }
7719 
7720 
LatLonDlgToString(DialoG d)7721 static Pointer LatLonDlgToString (DialoG d)
7722 {
7723   LatLonDlgPtr dlg;
7724   CharPtr      str, ns, ew;
7725   Int4         len;
7726 
7727   dlg = (LatLonDlgPtr) GetObjectExtra (d);
7728   if (dlg == NULL) return NULL;
7729 
7730   if (TextHasNoText (dlg->deg_ns) && TextHasNoText (dlg->deg_ew))
7731   {
7732     return NULL;
7733   }
7734 
7735   ns = SaveStringFromText (dlg->deg_ns);
7736   ew = SaveStringFromText (dlg->deg_ew);
7737   len = StringLen (ns) + StringLen (ew) + 6;
7738   str = (CharPtr) MemNew (sizeof(Char) * len);
7739   sprintf (str, "%s %c %s %c",
7740            ns == NULL ? "" : ns,
7741            GetValue (dlg->dir_ns) == 1 ? 'N' : 'S',
7742            ew == NULL ? "" : ew,
7743            GetValue (dlg->dir_ew) == 1 ? 'E' : 'W');
7744   ns = MemFree (ns);
7745   ew = MemFree (ew);
7746   return str;
7747 }
7748 
LatLonTextChange(TexT t)7749 static void LatLonTextChange (TexT t)
7750 {
7751   LatLonDlgPtr dlg;
7752 
7753   dlg = (LatLonDlgPtr) GetObjectExtra (t);
7754   if (dlg == NULL) return;
7755 
7756 
7757   if (dlg->change_notify != NULL)
7758   {
7759     (dlg->change_notify) (dlg->change_userdata);
7760   }
7761 }
7762 
7763 
LatLonPopupChange(PopuP p)7764 static void LatLonPopupChange (PopuP p)
7765 {
7766   LatLonDlgPtr dlg;
7767 
7768   dlg = (LatLonDlgPtr) GetObjectExtra (p);
7769   if (dlg == NULL) return;
7770 
7771 
7772   if (dlg->change_notify != NULL)
7773   {
7774     (dlg->change_notify) (dlg->change_userdata);
7775   }
7776 }
7777 
7778 
LatLonDialog(GrouP h,TaglistCallback change_notify,Pointer change_userdata)7779 static DialoG LatLonDialog (GrouP h, TaglistCallback change_notify, Pointer change_userdata)
7780 {
7781   LatLonDlgPtr dlg;
7782   GrouP        p;
7783 
7784   p = HiddenGroup (h, 4, 0, NULL);
7785   SetGroupSpacing (p, 10, 10);
7786   dlg = (LatLonDlgPtr) MemNew (sizeof(LatLonDlgData));
7787 
7788   SetObjectExtra (p, dlg, StdCleanupExtraProc);
7789   dlg->dialog = (DialoG) p;
7790   dlg->todialog = StringToLatLonDlg;
7791   dlg->fromdialog = LatLonDlgToString;
7792   dlg->testdialog = NULL;
7793   dlg->dialogmessage = NULL;
7794   dlg->change_notify = change_notify;
7795   dlg->change_userdata = change_userdata;
7796 
7797   dlg->deg_ns = DialogText (p, "", 3, LatLonTextChange);
7798   SetObjectExtra (dlg->deg_ns, dlg, NULL);
7799   dlg->dir_ns = PopupList (p, TRUE, LatLonPopupChange);
7800   SetObjectExtra (dlg->dir_ns, dlg, NULL);
7801   PopupItem (dlg->dir_ns, "N");
7802   PopupItem (dlg->dir_ns, "S");
7803   SetValue (dlg->dir_ns, 1);
7804 
7805   dlg->deg_ew = DialogText (p, "", 3, LatLonTextChange);
7806   SetObjectExtra (dlg->deg_ew, dlg, NULL);
7807   dlg->dir_ew = PopupList (p, TRUE, LatLonPopupChange);
7808   SetObjectExtra (dlg->dir_ew, dlg, NULL);
7809   PopupItem (dlg->dir_ew, "E");
7810   PopupItem (dlg->dir_ew, "W");
7811 
7812   SetValue (dlg->dir_ew, 1);
7813 
7814   return (DialoG) p;
7815 }
7816 
7817 
ParseLatLonOk(CharPtr str)7818 static Boolean ParseLatLonOk (CharPtr str)
7819 {
7820   CharPtr ns, ew, cp;
7821 
7822   if (StringHasNoText (str))
7823   {
7824     return TRUE;
7825   }
7826   ew = str + StringLen (str) - 1;
7827   if (*ew != 'E' && *ew != 'W')
7828   {
7829     return FALSE;
7830   }
7831   ns = str;
7832   while (ns < ew && !isalpha (*ns))
7833   {
7834     ns++;
7835   }
7836   if (*ns != 'N' && *ns != 'S')
7837   {
7838     return FALSE;
7839   }
7840 
7841   cp = ns + 1;
7842   while (cp < ew)
7843   {
7844     if (isalpha (*cp))
7845     {
7846       return FALSE;
7847     }
7848     cp++;
7849   }
7850   return TRUE;
7851 }
7852 
7853 
ValueListLatLonDialog(GrouP h,Int2 width,ValueListParentPtr parent,TaglistCallback change_notify,Pointer change_userdata)7854 static DialoG ValueListLatLonDialog (GrouP h, Int2 width, ValueListParentPtr parent, TaglistCallback change_notify, Pointer change_userdata)
7855 {
7856   StructuredValueEditDlgPtr dlg;
7857   GrouP           p;
7858   ButtoN          b;
7859 
7860 
7861   p = HiddenGroup (h, 2, 0, NULL);
7862   SetGroupSpacing (p, 10, 10);
7863   dlg = (StructuredValueEditDlgPtr) MemNew (sizeof(StructuredValueEditDlgData));
7864 
7865   SetObjectExtra (p, dlg, StdCleanupExtraProc);
7866   dlg->dialog = (DialoG) p;
7867   dlg->todialog = StringToStructuredValueEditDialog;
7868   dlg->fromdialog = StructuredValueEditDialogToString;
7869   dlg->testdialog = NULL;
7870   dlg->dialogmessage = NULL;
7871   dlg->change_notify = change_notify;
7872   dlg->change_userdata = change_userdata;
7873   dlg->parent = parent;
7874 
7875   dlg->dlg = LatLonDialog (p, change_notify, change_userdata);
7876   dlg->parse_func = ParseLatLonOk;
7877 
7878   dlg->unparsable = HiddenGroup (p, 3, 0, NULL);
7879   SetGroupSpacing (dlg->unparsable, 10, 10);
7880   dlg->text = DialogText (dlg->unparsable, "", width - 15, StructuredValueEditChange);
7881   SetObjectExtra (dlg->text, dlg, NULL);
7882 
7883   b = PushButton (dlg->unparsable, "Copy to Note", CopyUnparsableToNote);
7884   SetObjectExtra (b, dlg, NULL);
7885 
7886   b = PushButton (dlg->unparsable, "Erase", EraseUnparsable);
7887   SetObjectExtra (b, dlg, NULL);
7888 
7889   Hide (dlg->unparsable);
7890 
7891   return (DialoG) p;
7892 }
7893 
7894 
7895 typedef struct specimenvoucherdlg {
7896   DIALOG_MESSAGE_BLOCK
7897 
7898   TexT  institution_code;
7899   TexT  collection_code;
7900   TexT  free_text;
7901 
7902   TaglistCallback change_notify;
7903   Pointer change_userdata;
7904 
7905 } SpecimenVoucherDlgData, PNTR SpecimenVoucherDlgPtr;
7906 
7907 
ResetSpecimenVoucherDlg(SpecimenVoucherDlgPtr dlg)7908 static void ResetSpecimenVoucherDlg (SpecimenVoucherDlgPtr dlg)
7909 {
7910   if (dlg == NULL) return;
7911 
7912   SetTitle (dlg->institution_code, "");
7913   SetTitle (dlg->collection_code, "");
7914   SetTitle (dlg->free_text, "");
7915 }
7916 
7917 
StringToSpecimenVoucherDlg(DialoG d,Pointer data)7918 static void StringToSpecimenVoucherDlg (DialoG d, Pointer data)
7919 {
7920   SpecimenVoucherDlgPtr dlg;
7921   CharPtr      str, ptr, cp;
7922 
7923   dlg = (SpecimenVoucherDlgPtr) GetObjectExtra (d);
7924   if (dlg == NULL) return;
7925 
7926   ResetSpecimenVoucherDlg (dlg);
7927   str = (CharPtr) data;
7928   if (str == NULL)
7929   {
7930     return;
7931   }
7932 
7933   /* make copy so we don't worry about changing data */
7934   str = StringSave (str);
7935 
7936   cp = StringChr (str, ':');
7937   if (cp == NULL)
7938   {
7939     SetTitle (dlg->free_text, str);
7940   }
7941   else
7942   {
7943     *cp = 0;
7944     SetTitle (dlg->institution_code, str);
7945     ptr = cp + 1;
7946     cp = StringChr (ptr, ':');
7947     if (cp == NULL)
7948     {
7949       SetTitle (dlg->free_text, ptr);
7950     }
7951     else
7952     {
7953       *cp = 0;
7954       SetTitle (dlg->collection_code, ptr);
7955       SetTitle (dlg->free_text, cp + 1);
7956     }
7957   }
7958   str = MemFree (str);
7959 }
7960 
7961 
SpecimenVoucherDlgToString(DialoG d)7962 static Pointer SpecimenVoucherDlgToString (DialoG d)
7963 {
7964   SpecimenVoucherDlgPtr dlg;
7965   CharPtr      str;
7966   Int4         len;
7967   CharPtr      inst, coll, free_text;
7968 
7969   dlg = (SpecimenVoucherDlgPtr) GetObjectExtra (d);
7970   if (dlg == NULL) return NULL;
7971 
7972   if (TextHasNoText (dlg->institution_code) && TextHasNoText (dlg->collection_code) && TextHasNoText (dlg->free_text))
7973   {
7974     return NULL;
7975   }
7976 
7977   inst = SaveStringFromText (dlg->institution_code);
7978   coll = SaveStringFromText (dlg->collection_code);
7979   free_text = SaveStringFromText (dlg->free_text);
7980 
7981   len = StringLen (inst) + StringLen (coll) + StringLen (free_text) + 3;
7982   str = (CharPtr) MemNew (sizeof(Char) * len);
7983   if (StringHasNoText (inst) && StringHasNoText (coll))
7984   {
7985     sprintf (str, "%s", free_text);
7986   }
7987   else if (StringHasNoText (coll))
7988   {
7989     sprintf (str, "%s:%s", inst, free_text == NULL ? "" : free_text);
7990   }
7991   else
7992   {
7993     sprintf (str, "%s:%s:%s", inst == NULL ? "" : inst,
7994                               coll == NULL ? "" : coll,
7995                               free_text == NULL ? "" : free_text);
7996   }
7997   inst = MemFree (inst);
7998   coll = MemFree (coll);
7999   free_text = MemFree (free_text);
8000   return str;
8001 }
8002 
SpecimenVoucherTextChange(TexT t)8003 static void SpecimenVoucherTextChange (TexT t)
8004 {
8005   SpecimenVoucherDlgPtr dlg;
8006 
8007   dlg = (SpecimenVoucherDlgPtr) GetObjectExtra (t);
8008   if (dlg == NULL) return;
8009 
8010 
8011   if (dlg->change_notify != NULL)
8012   {
8013     (dlg->change_notify) (dlg->change_userdata);
8014   }
8015 }
8016 
8017 
SpecimenVoucherDialog(GrouP h,Int2 width,ValueListParentPtr parent,TaglistCallback change_notify,Pointer change_userdata)8018 static DialoG SpecimenVoucherDialog (GrouP h, Int2 width, ValueListParentPtr parent, TaglistCallback change_notify, Pointer change_userdata)
8019 {
8020   SpecimenVoucherDlgPtr dlg;
8021   GrouP        p;
8022 
8023   p = HiddenGroup (h, 6, 0, NULL);
8024   SetGroupSpacing (p, 10, 10);
8025   dlg = (SpecimenVoucherDlgPtr) MemNew (sizeof(SpecimenVoucherDlgData));
8026 
8027   SetObjectExtra (p, dlg, StdCleanupExtraProc);
8028   dlg->dialog = (DialoG) p;
8029   dlg->todialog = StringToSpecimenVoucherDlg;
8030   dlg->fromdialog = SpecimenVoucherDlgToString;
8031   dlg->testdialog = NULL;
8032   dlg->dialogmessage = NULL;
8033   dlg->change_notify = change_notify;
8034   dlg->change_userdata = change_userdata;
8035 
8036   StaticPrompt (p, "Inst", 0, 0, programFont, 'r');
8037   dlg->institution_code = DialogText (p, "", 4, SpecimenVoucherTextChange);
8038   SetObjectExtra (dlg->institution_code, dlg, NULL);
8039   StaticPrompt (p, "Coll", 0, 0, programFont, 'r');
8040   dlg->collection_code = DialogText (p, "", 4, SpecimenVoucherTextChange);
8041   SetObjectExtra (dlg->collection_code, dlg, NULL);
8042 
8043   StaticPrompt (p, "SpecID/Text", 0, 0, programFont, 'r');
8044   dlg->free_text = DialogText (p, "", width - 8, SpecimenVoucherTextChange);
8045   SetObjectExtra (dlg->free_text, dlg, NULL);
8046 
8047   return (DialoG) p;
8048 }
8049 
8050 
ParseSpecimenVoucherOk(CharPtr str)8051 static Boolean ParseSpecimenVoucherOk (CharPtr str)
8052 {
8053   return TRUE;
8054 }
8055 
8056 
8057 typedef struct altitudedlg {
8058   DIALOG_MESSAGE_BLOCK
8059 
8060   TexT  val;
8061 
8062   TaglistCallback change_notify;
8063   Pointer change_userdata;
8064 
8065 } AltitudeDlgData, PNTR AltitudeDlgPtr;
8066 
8067 
ResetAltitudeDlg(AltitudeDlgPtr dlg)8068 static void ResetAltitudeDlg (AltitudeDlgPtr dlg)
8069 {
8070   if (dlg == NULL) return;
8071 
8072   SetTitle (dlg->val, "");
8073 }
8074 
8075 
StringToAltitudeDlg(DialoG d,Pointer data)8076 static void StringToAltitudeDlg (DialoG d, Pointer data)
8077 {
8078   AltitudeDlgPtr dlg;
8079   CharPtr      str, stp, tmp;
8080   Int4         len;
8081 
8082   dlg = (AltitudeDlgPtr) GetObjectExtra (d);
8083   if (dlg == NULL) return;
8084 
8085   str = (CharPtr) data;
8086   if (str == NULL)
8087   {
8088     ResetAltitudeDlg (dlg);
8089     return;
8090   }
8091 
8092   stp = StringChr (str, 'm');
8093   if (stp == NULL) {
8094     ResetAltitudeDlg (dlg);
8095     return;
8096   }
8097 
8098   len = stp - str + 1;
8099   tmp = (CharPtr) MemNew (sizeof (Char) * len);
8100   StringNCpy (tmp, str, len - 1);
8101   tmp [len - 1] = 0;
8102   TrimSpacesAroundString (tmp);
8103   SetTitle (dlg->val, tmp);
8104   tmp = MemFree (tmp);
8105 }
8106 
8107 
ParseAltitudeNumberOnly(CharPtr str)8108 static Boolean ParseAltitudeNumberOnly (CharPtr str)
8109 {
8110   CharPtr cp;
8111   Boolean any_digit = FALSE;
8112 
8113   if (StringHasNoText (str))
8114   {
8115     return TRUE;
8116   }
8117   cp = str;
8118   if (*cp == '-') {
8119     /* allow negative */
8120     cp++;
8121   }
8122   while (isdigit(*cp)) {
8123     any_digit = TRUE;
8124     cp++;
8125   }
8126   if (*cp == '.') {
8127     cp++;
8128     while (isdigit(*cp)) {
8129       cp++;
8130       any_digit = TRUE;
8131     }
8132   }
8133   if (!any_digit || *cp != 0) {
8134     return FALSE;
8135   }
8136   return TRUE;
8137 }
8138 
8139 
AltitudeDlgToString(DialoG d)8140 static Pointer AltitudeDlgToString (DialoG d)
8141 {
8142   AltitudeDlgPtr dlg;
8143   CharPtr      str, val;
8144   CharPtr      m = " m.";
8145   Int4         len;
8146 
8147   dlg = (AltitudeDlgPtr) GetObjectExtra (d);
8148   if (dlg == NULL) return NULL;
8149 
8150   if (TextHasNoText (dlg->val))
8151   {
8152     return NULL;
8153   }
8154 
8155   val = SaveStringFromText (dlg->val);
8156   if (ParseAltitudeNumberOnly(val)) {
8157     len = StringLen (val) + StringLen (m) + 1;
8158     str = (CharPtr) MemNew (sizeof(Char) * len);
8159     sprintf (str, "%s%s", val, m);
8160     val = MemFree (val);
8161   } else {
8162     str = val;
8163   }
8164   return str;
8165 }
8166 
AltitudeTextChange(TexT t)8167 static void AltitudeTextChange (TexT t)
8168 {
8169   AltitudeDlgPtr dlg;
8170 
8171   dlg = (AltitudeDlgPtr) GetObjectExtra (t);
8172   if (dlg == NULL) return;
8173 
8174 
8175   if (dlg->change_notify != NULL)
8176   {
8177     (dlg->change_notify) (dlg->change_userdata);
8178   }
8179 }
8180 
8181 
AltitudeDialog(GrouP h,TaglistCallback change_notify,Pointer change_userdata)8182 static DialoG AltitudeDialog (GrouP h, TaglistCallback change_notify, Pointer change_userdata)
8183 {
8184   AltitudeDlgPtr dlg;
8185   GrouP        p;
8186 
8187   p = HiddenGroup (h, 2, 0, NULL);
8188   SetGroupSpacing (p, 10, 10);
8189   dlg = (AltitudeDlgPtr) MemNew (sizeof(AltitudeDlgData));
8190 
8191   SetObjectExtra (p, dlg, StdCleanupExtraProc);
8192   dlg->dialog = (DialoG) p;
8193   dlg->todialog = StringToAltitudeDlg;
8194   dlg->fromdialog = AltitudeDlgToString;
8195   dlg->testdialog = NULL;
8196   dlg->dialogmessage = NULL;
8197   dlg->change_notify = change_notify;
8198   dlg->change_userdata = change_userdata;
8199 
8200   dlg->val = DialogText (p, "", 3, AltitudeTextChange);
8201   SetObjectExtra (dlg->val, dlg, NULL);
8202   StaticPrompt (p, "meters", 0, 0, systemFont, 'l');
8203 
8204   return (DialoG) p;
8205 }
8206 
8207 
ParseAltitudeOk(CharPtr str)8208 static Boolean ParseAltitudeOk (CharPtr str)
8209 {
8210   CharPtr cp;
8211   Boolean any_digit = FALSE;
8212 
8213   if (StringHasNoText (str))
8214   {
8215     return TRUE;
8216   }
8217   cp = str;
8218   if (*cp == '-') {
8219     /* allow negative */
8220     cp++;
8221   }
8222   while (isdigit(*cp)) {
8223     any_digit = TRUE;
8224     cp++;
8225   }
8226   if (*cp == '.') {
8227     cp++;
8228     while (isdigit(*cp)) {
8229       cp++;
8230       any_digit = TRUE;
8231     }
8232   }
8233   if (!any_digit) {
8234     return FALSE;
8235   }
8236   while (isspace(*cp)) {
8237     cp++;
8238   }
8239   if (StringCmp (cp, "m") == 0
8240       || StringCmp (cp, "m.") == 0
8241       || StringCmp (cp, "meters") == 0
8242       || StringCmp (cp, "metres") == 0) {
8243     return TRUE;
8244   } else {
8245     return FALSE;
8246   }
8247 }
8248 
8249 
ValueListAltitudeDialog(GrouP h,Int2 width,ValueListParentPtr parent,TaglistCallback change_notify,Pointer change_userdata)8250 static DialoG ValueListAltitudeDialog (GrouP h, Int2 width, ValueListParentPtr parent, TaglistCallback change_notify, Pointer change_userdata)
8251 {
8252   StructuredValueEditDlgPtr dlg;
8253   GrouP           p;
8254   ButtoN          b;
8255 
8256 
8257   p = HiddenGroup (h, 2, 0, NULL);
8258   SetGroupSpacing (p, 10, 10);
8259   dlg = (StructuredValueEditDlgPtr) MemNew (sizeof(StructuredValueEditDlgData));
8260 
8261   SetObjectExtra (p, dlg, StdCleanupExtraProc);
8262   dlg->dialog = (DialoG) p;
8263   dlg->todialog = StringToStructuredValueEditDialog;
8264   dlg->fromdialog = StructuredValueEditDialogToString;
8265   dlg->testdialog = NULL;
8266   dlg->dialogmessage = NULL;
8267   dlg->change_notify = change_notify;
8268   dlg->change_userdata = change_userdata;
8269   dlg->parent = parent;
8270 
8271   dlg->dlg = AltitudeDialog (p, change_notify, change_userdata);
8272   dlg->parse_func = ParseAltitudeOk;
8273 
8274   dlg->unparsable = HiddenGroup (p, 3, 0, NULL);
8275   SetGroupSpacing (dlg->unparsable, 10, 10);
8276   dlg->text = DialogText (dlg->unparsable, "", width - 15, StructuredValueEditChange);
8277   SetObjectExtra (dlg->text, dlg, NULL);
8278 
8279   b = PushButton (dlg->unparsable, "Copy to Note", CopyUnparsableToNote);
8280   SetObjectExtra (b, dlg, NULL);
8281 
8282   b = PushButton (dlg->unparsable, "Erase", EraseUnparsable);
8283   SetObjectExtra (b, dlg, NULL);
8284 
8285   Hide (dlg->unparsable);
8286 
8287   return (DialoG) p;
8288 }
8289 
8290 
8291 typedef DialoG (*MakeValueEditDialogFunc) PROTO ((GrouP, Int2, ValueListParentPtr, TaglistCallback, Pointer));
8292 
8293 static MakeValueEditDialogFunc value_edit_dialog_list[] = {
8294   SimpleTextValueEditDialog,
8295   TrueFalseValueEditDialog,
8296   ValueListLatLonDialog,
8297   SpecimenVoucherDialog,
8298   ValueListAltitudeDialog
8299 };
8300 
8301 
NameValuePairFree(NameValuePairPtr nvp)8302 extern NameValuePairPtr NameValuePairFree (NameValuePairPtr nvp)
8303 {
8304   if (nvp != NULL)
8305   {
8306     nvp->name_vnp = ValNodeFreeData (nvp->name_vnp);
8307     nvp->value = MemFree (nvp->value);
8308     nvp = MemFree (nvp);
8309   }
8310   return nvp;
8311 }
8312 
8313 
NameValuePairCopy(NameValuePairPtr nvp)8314 extern NameValuePairPtr NameValuePairCopy (NameValuePairPtr nvp)
8315 {
8316   NameValuePairPtr cpy = NULL;
8317 
8318   if (nvp != NULL)
8319   {
8320     cpy = (NameValuePairPtr) MemNew (sizeof (NameValuePairData));
8321     if (nvp->name_vnp != NULL)
8322     {
8323       cpy->name_vnp = ValNodeNew (NULL);
8324       cpy->name_vnp->choice = nvp->name_vnp->choice;
8325       cpy->name_vnp->data.ptrvalue = StringSave (nvp->name_vnp->data.ptrvalue);
8326     }
8327     cpy->value = StringSave (nvp->value);
8328   }
8329   return cpy;
8330 }
8331 
8332 
NameValuePairListFree(ValNodePtr vnp)8333 extern ValNodePtr NameValuePairListFree (ValNodePtr vnp)
8334 {
8335   ValNodePtr vnp_next;
8336 
8337   while (vnp != NULL)
8338   {
8339     vnp->data.ptrvalue = NameValuePairFree (vnp->data.ptrvalue);
8340     vnp_next = vnp->next;
8341     vnp->next= NULL;
8342     vnp = ValNodeFree (vnp);
8343     vnp = vnp_next;
8344   }
8345   return vnp;
8346 }
8347 
8348 
8349 typedef struct valuelistrowdialog {
8350   DIALOG_MESSAGE_BLOCK
8351 
8352   TaglistCallback change_notify;
8353   Pointer         change_userdata;
8354   DialoG          parent_dlg;
8355   DialoG          name_dlg;
8356   DialoG          editors[eNumValueEditors];
8357   Int4            current_editor;
8358 } ValueListRowDialogData, PNTR ValueListRowDialogPtr;
8359 
8360 
ChangeValueListRowName(Pointer data)8361 static void ChangeValueListRowName (Pointer data)
8362 {
8363   ValueListRowDialogPtr dlg;
8364   ValNodePtr            vnp;
8365   Int4                  i;
8366   CharPtr               value = NULL;
8367 
8368   dlg = (ValueListRowDialogPtr) data;
8369   if (dlg == NULL) return;
8370 
8371   if (dlg->current_editor > -1)
8372   {
8373     value = (CharPtr) DialogToPointer (dlg->editors[dlg->current_editor]);
8374   }
8375   for (i = 0; i < eNumValueEditors; i++)
8376   {
8377     Hide (dlg->editors[i]);
8378   }
8379   vnp = (ValNodePtr) DialogToPointer (dlg->name_dlg);
8380   if (vnp != NULL && vnp->choice > 0)
8381   {
8382     dlg->current_editor = vnp->choice - 1;
8383     Show (dlg->editors[dlg->current_editor]);
8384     PointerToDialog (dlg->editors[dlg->current_editor], value);
8385     vnp = ValNodeFree (vnp);
8386   } else {
8387     dlg->current_editor = -1;
8388   }
8389   value = MemFree (value);
8390 
8391   if (dlg->change_notify != NULL)
8392   {
8393     (dlg->change_notify) (dlg->change_userdata);
8394   }
8395 }
8396 
8397 
NameValuePairToDialog(DialoG d,Pointer data)8398 static void NameValuePairToDialog (DialoG d, Pointer data)
8399 {
8400   ValueListRowDialogPtr dlg;
8401   NameValuePairPtr      nvp;
8402   ValNode               vn;
8403   Int4                  i;
8404 
8405   dlg = (ValueListRowDialogPtr) GetObjectExtra (d);
8406   nvp = (NameValuePairPtr) data;
8407 
8408   if (dlg == NULL) return;
8409   if (nvp == NULL)
8410   {
8411     vn.next = NULL;
8412     vn.choice = 0;
8413     vn.data.ptrvalue = " ";
8414     PointerToDialog (dlg->name_dlg, &vn);
8415     for (i = 0; i < eNumValueEditors; i++)
8416     {
8417       PointerToDialog (dlg->editors[i], NULL);
8418     }
8419     ChangeValueListRowName (dlg);
8420   }
8421   else
8422   {
8423     PointerToDialog (dlg->name_dlg, nvp->name_vnp);
8424     ChangeValueListRowName (dlg);
8425     if (dlg->current_editor > -1)
8426     {
8427       PointerToDialog (dlg->editors[dlg->current_editor], nvp->value);
8428       if (dlg->change_notify != NULL)
8429       {
8430         (dlg->change_notify) (dlg->change_userdata);
8431       }
8432     }
8433   }
8434 }
8435 
8436 
DialogToNameValuePair(DialoG d)8437 static Pointer DialogToNameValuePair (DialoG d)
8438 {
8439   ValueListRowDialogPtr dlg;
8440   NameValuePairPtr      nvp;
8441   ValNodePtr            name_vnp;
8442 
8443   dlg = (ValueListRowDialogPtr) GetObjectExtra (d);
8444   if (dlg == NULL || dlg->current_editor < 0) return NULL;
8445 
8446   name_vnp = DialogToPointer (dlg->name_dlg);
8447   if (name_vnp == NULL) return NULL;
8448 
8449   nvp = (NameValuePairPtr) MemNew (sizeof (NameValuePairData));
8450   nvp->name_vnp = name_vnp;
8451   nvp->value = DialogToPointer (dlg->editors[dlg->current_editor]);
8452   return nvp;
8453 }
8454 
8455 
CopyChoiceList(ValNodePtr orig)8456 static ValNodePtr CopyChoiceList (ValNodePtr orig)
8457 {
8458   ValNodePtr vnp, cpy = NULL, prev = NULL;
8459 
8460   while (orig != NULL)
8461   {
8462     vnp = ValNodeNew (NULL);
8463     vnp->choice = orig->choice;
8464     vnp->data.ptrvalue = StringSave (orig->data.ptrvalue);
8465     if (prev == NULL)
8466     {
8467       cpy = vnp;
8468     }
8469     else
8470     {
8471       prev->next = vnp;
8472     }
8473     prev = vnp;
8474     orig = orig->next;
8475   }
8476   return cpy;
8477 }
8478 
TestValueListRowDialog(DialoG d)8479 static ValNodePtr TestValueListRowDialog (DialoG d)
8480 {
8481   ValueListRowDialogPtr dlg;
8482   ValNodePtr            name_vnp, err_list = NULL;
8483   CharPtr               val, err_str;
8484   CharPtr               err_fmt = "No modifier type selected for data %s";
8485 
8486   dlg = (ValueListRowDialogPtr) GetObjectExtra (d);
8487   if (dlg == NULL || dlg->current_editor < 0) return NULL;
8488 
8489   val = DialogToPointer (dlg->editors[dlg->current_editor]);
8490   if (!StringHasNoText (val))
8491   {
8492     name_vnp = DialogToPointer (dlg->name_dlg);
8493     if (name_vnp == NULL || name_vnp->choice == 0)
8494     {
8495       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (err_fmt) + StringLen (val)));
8496       sprintf (err_str, err_fmt, val);
8497       err_list = ValNodeNew(NULL);
8498       err_list->choice = 0;
8499       err_list->data.ptrvalue = err_str;
8500     }
8501     name_vnp = ValNodeFree (name_vnp);
8502   }
8503   val = MemFree (val);
8504   return err_list;
8505 }
8506 
8507 
ClearValueListRow(ButtoN b)8508 static void ClearValueListRow (ButtoN b)
8509 {
8510   ValueListRowDialogPtr dlg;
8511 
8512   dlg = (ValueListRowDialogPtr) GetObjectExtra (b);
8513 
8514   if (dlg != NULL)
8515   {
8516     PointerToDialog (dlg->dialog, NULL);
8517     if (dlg->change_notify != NULL)
8518     {
8519       (dlg->change_notify) (dlg->change_userdata);
8520     }
8521     SendMessageToDialog (dlg->parent_dlg, VIB_MSG_REDRAW);
8522   }
8523 }
8524 
8525 
ValueListRowDialog(GrouP h,Int2 width,ValNodePtr choice_list,ValueListParentPtr parent,TaglistCallback change_notify,Pointer change_userdata,DialoG parent_dlg)8526 static DialoG ValueListRowDialog (GrouP h, Int2 width, ValNodePtr choice_list, ValueListParentPtr parent,
8527                                   TaglistCallback change_notify, Pointer change_userdata, DialoG parent_dlg)
8528 {
8529   ValueListRowDialogPtr dlg;
8530   GrouP           p, g;
8531   Int4            i;
8532   ValNode         vn;
8533   ButtoN          b;
8534 
8535   p = HiddenGroup (h, 3, 0, NULL);
8536   SetGroupSpacing (p, 2, 2);
8537   dlg = (ValueListRowDialogPtr) MemNew (sizeof(ValueListRowDialogData));
8538 
8539   SetObjectExtra (p, dlg, StdCleanupExtraProc);
8540   dlg->dialog = (DialoG) p;
8541   dlg->todialog = NameValuePairToDialog;
8542   dlg->fromdialog = DialogToNameValuePair;
8543   dlg->testdialog = TestValueListRowDialog;
8544   dlg->dialogmessage = NULL;
8545   dlg->change_notify = change_notify;
8546   dlg->change_userdata = change_userdata;
8547   dlg->parent_dlg = parent_dlg;
8548 
8549   dlg->name_dlg = ValNodeSelectionDialog (p, CopyChoiceList(choice_list), 1,
8550                                      ValNodeStringName,
8551                                      ValNodeSimpleDataFree, ValNodeStringCopy,
8552                                      ValNodeStringMatch, NULL,
8553                                      ChangeValueListRowName, dlg, FALSE);
8554   vn.next = NULL;
8555   vn.choice = 0;
8556   vn.data.ptrvalue = " ";
8557   PointerToDialog (dlg->name_dlg, &vn);
8558 
8559   g = HiddenGroup (p, 0, 0, NULL);
8560   for (i = 0; i < eNumValueEditors; i++)
8561   {
8562     dlg->editors[i] = (value_edit_dialog_list[i]) (g, width, parent, change_notify, change_userdata);
8563   }
8564 
8565   b = PushButton (p, "X", ClearValueListRow);
8566   SetObjectExtra (b, dlg, NULL);
8567 
8568   ChangeValueListRowName (dlg);
8569 
8570   return (DialoG) p;
8571 }
8572 
8573 typedef struct valuelistdialog {
8574   DIALOG_MESSAGE_BLOCK
8575   TaglistCallback change_notify;
8576   Pointer         change_userdata;
8577   Int4            num_rows;
8578   DialoG *        rows;
8579   BaR             left_bar;
8580   BaR             right_bar;
8581   ValNodePtr      choice_list;
8582   ValNodePtr      value_list;
8583   Int4            scroll_pos;
8584   Boolean         suppress_notify;
8585 } ValueListDialogData, PNTR ValueListDialogPtr;
8586 
8587 
CleanupValueListDialog(GraphiC g,VoidPtr data)8588 static void CleanupValueListDialog (GraphiC g, VoidPtr data)
8589 
8590 {
8591   ValueListDialogPtr dlg;
8592 
8593   dlg = (ValueListDialogPtr) data;
8594   if (dlg != NULL)
8595   {
8596     dlg->rows = MemFree (dlg->rows);
8597   }
8598 
8599   StdCleanupExtraProc (g, data);
8600 }
8601 
8602 
GetNthNameValuePair(Int4 n,ValNodePtr list)8603 static NameValuePairPtr GetNthNameValuePair (Int4 n, ValNodePtr list)
8604 {
8605   while (n > 0 && list != NULL)
8606   {
8607     n--;
8608     list = list->next;
8609   }
8610   if (list == NULL)
8611   {
8612     return NULL;
8613   }
8614   else
8615   {
8616     return (NameValuePairPtr) list->data.ptrvalue;
8617   }
8618 }
8619 
PopulateValueListRows(ValueListDialogPtr dlg)8620 static void PopulateValueListRows (ValueListDialogPtr dlg)
8621 {
8622   Int4 n;
8623   ValNodePtr vnp;
8624 
8625   n = dlg->scroll_pos;
8626   vnp = dlg->value_list;
8627 
8628   dlg->suppress_notify = TRUE;
8629 
8630   while (n > 0 && vnp != NULL)
8631   {
8632     n--;
8633     vnp = vnp->next;
8634   }
8635   for (n = 0; n < dlg->num_rows; n++)
8636   {
8637     if (vnp == NULL)
8638     {
8639       PointerToDialog (dlg->rows[n], NULL);
8640     }
8641     else
8642     {
8643       PointerToDialog (dlg->rows[n], vnp->data.ptrvalue);
8644       vnp = vnp->next;
8645     }
8646   }
8647   dlg->suppress_notify = FALSE;
8648 }
8649 
8650 
IsNameValuePairEmpty(NameValuePairPtr nvp)8651 static Boolean IsNameValuePairEmpty (NameValuePairPtr nvp)
8652 {
8653   if (nvp == NULL)
8654   {
8655     return TRUE;
8656   }
8657   else if ((nvp->name_vnp == NULL || nvp->name_vnp->choice == 0 || StringHasNoText (nvp->name_vnp->data.ptrvalue)) /* no choice */
8658             && StringHasNoText (nvp->value)) /* no value */
8659   {
8660     return TRUE;
8661   }
8662   else
8663   {
8664     return FALSE;
8665   }
8666 }
8667 
8668 /* Only trim blanks from the end of the list */
RemoveBlanks(ValNodePtr PNTR pvnp)8669 static void RemoveBlanks (ValNodePtr PNTR pvnp)
8670 {
8671   ValNodePtr vnp, last_non_blank = NULL;
8672 
8673   if (pvnp == NULL) return;
8674 
8675   vnp = *pvnp;
8676   while (vnp != NULL)
8677   {
8678     if (!IsNameValuePairEmpty ((NameValuePairPtr) vnp->data.ptrvalue))
8679     {
8680       last_non_blank = vnp;
8681     }
8682     vnp = vnp->next;
8683   }
8684   if (last_non_blank != NULL) {
8685     last_non_blank->next = NameValuePairListFree (last_non_blank->next);
8686   }
8687 }
8688 
ValueListPairToDialog(DialoG d,Pointer data)8689 static void ValueListPairToDialog (DialoG d, Pointer data)
8690 {
8691   ValueListDialogPtr dlg;
8692   Int4               num_vals;
8693 
8694   dlg = (ValueListDialogPtr) GetObjectExtra (d);
8695   if (dlg == NULL) return;
8696 
8697   dlg->value_list = NameValuePairListFree (dlg->value_list);
8698   dlg->value_list = (ValNodePtr) data;
8699   RemoveBlanks (&(dlg->value_list));
8700 
8701   num_vals = ValNodeLen (dlg->value_list);
8702   if (num_vals >= dlg->num_rows)
8703   {
8704     SetBarMax (dlg->left_bar, num_vals + 1 - dlg->num_rows);
8705     SetBarMax (dlg->right_bar, num_vals + 1 - dlg->num_rows);
8706   }
8707   else
8708   {
8709     SetBarMax (dlg->left_bar, 0);
8710     SetBarMax (dlg->right_bar, 0);
8711   }
8712   if (GetValue (dlg->left_bar) > GetBarMax (dlg->left_bar))
8713   {
8714     CorrectBarValue (dlg->left_bar, 0);
8715     CorrectBarValue (dlg->right_bar, 0);
8716   }
8717   PopulateValueListRows (dlg);
8718 }
8719 
8720 
ScrollValueListProc(BaR b,GraphiC g,Int2 _new,Int2 _old)8721 static void ScrollValueListProc (BaR b, GraphiC g, Int2 _new, Int2 _old)
8722 {
8723   ValueListDialogPtr dlg;
8724 
8725   dlg = (ValueListDialogPtr) GetObjectExtra (b);
8726   if (dlg == NULL) return;
8727 
8728   /* synchronize left and right scroll bars */
8729   if (b == dlg->right_bar && dlg->left_bar != NULL)
8730   {
8731     CorrectBarValue (dlg->left_bar, GetBarValue (dlg->right_bar));
8732   }
8733   else if (b == dlg->left_bar && dlg->right_bar != NULL)
8734   {
8735     CorrectBarValue (dlg->right_bar, GetBarValue (dlg->left_bar));
8736   }
8737 
8738   dlg->scroll_pos = _new;
8739   PopulateValueListRows (dlg);
8740 }
8741 
8742 
ValueListDialogMessage(DialoG d,Int2 mssg)8743 static void ValueListDialogMessage (DialoG d, Int2 mssg)
8744 
8745 {
8746   ValNodePtr         new_value_list;
8747 
8748   switch (mssg) {
8749     case VIB_MSG_REDRAW :
8750       new_value_list = DialogToPointer (d);
8751       PointerToDialog (d, new_value_list);
8752       break;
8753     default :
8754       break;
8755   }
8756 }
8757 
8758 
ChangeValueRow(Pointer data)8759 static void ChangeValueRow (Pointer data)
8760 {
8761   ValueListDialogPtr dlg;
8762   NameValuePairPtr   nvp;
8763   Int4               max, i;
8764   ValNodePtr         vnp;
8765 
8766   dlg = (ValueListDialogPtr) data;
8767 
8768   if (dlg == NULL) return;
8769 
8770   if (dlg->suppress_notify) return;
8771 
8772   /* copy values into list */
8773   /* first, skip over rows scrolled past */
8774   vnp = dlg->value_list;
8775   i = 0;
8776   while (i < dlg->scroll_pos)
8777   {
8778     if (vnp == NULL)
8779     {
8780       vnp = ValNodeAddPointer (&dlg->value_list, 0, NULL);
8781     }
8782     vnp = vnp->next;
8783     i++;
8784   }
8785 
8786   /* now copy in rows we can see */
8787   for (i = 0; i < dlg->num_rows; i++)
8788   {
8789     if (vnp == NULL)
8790     {
8791       vnp = ValNodeAddPointer (&dlg->value_list, 0, DialogToPointer (dlg->rows[i]));
8792     }
8793     else
8794     {
8795       vnp->data.ptrvalue = NameValuePairFree (vnp->data.ptrvalue);
8796       vnp->data.ptrvalue = DialogToPointer (dlg->rows[i]);
8797     }
8798     vnp = vnp->next;
8799   }
8800 
8801 
8802   /* if editing last row, extend scrollbar for new row */
8803   max = GetBarMax (dlg->left_bar);
8804   if (dlg->scroll_pos == max)
8805   {
8806     nvp = DialogToPointer (dlg->rows[dlg->num_rows - 1]);
8807     if (!IsNameValuePairEmpty (nvp))
8808     {
8809       SetBarMax (dlg->left_bar, max + 1);
8810       SetBarMax (dlg->right_bar, max + 1);
8811     }
8812     nvp = NameValuePairFree(nvp);
8813   }
8814 
8815   if (dlg->change_notify != NULL)
8816   {
8817     (dlg->change_notify)(dlg->change_userdata);
8818   }
8819 }
8820 
8821 
DialogToNameValuePairList(DialoG d)8822 static Pointer DialogToNameValuePairList (DialoG d)
8823 {
8824   ValueListDialogPtr dlg;
8825   ValNodePtr         value_list = NULL, vnp;
8826 
8827   dlg = (ValueListDialogPtr) GetObjectExtra (d);
8828   if (dlg == NULL) return NULL;
8829 
8830   for (vnp = dlg->value_list; vnp != NULL; vnp = vnp->next)
8831   {
8832     if (vnp->data.ptrvalue != NULL)
8833     {
8834       ValNodeAddPointer (&value_list, 0, NameValuePairCopy (vnp->data.ptrvalue));
8835     }
8836   }
8837   return (Pointer) value_list;
8838 }
8839 
8840 
TestValueListDialog(DialoG d)8841 static ValNodePtr TestValueListDialog (DialoG d)
8842 {
8843   ValNodePtr       err_list = NULL, value_list = NULL, vnp;
8844   NameValuePairPtr nvp;
8845   CharPtr          err_fmt = "No modifier type selected for data %s";
8846   CharPtr          err_str;
8847 
8848   value_list = DialogToPointer (d);
8849 
8850   for (vnp = value_list; vnp != NULL; vnp = vnp->next)
8851   {
8852     nvp = (NameValuePairPtr) vnp->data.ptrvalue;
8853     if (nvp != NULL
8854         && !StringHasNoText (nvp->value)
8855         && (nvp->name_vnp == NULL || StringHasNoText (nvp->name_vnp->data.ptrvalue)))
8856     {
8857       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (err_fmt) + StringLen (nvp->value)));
8858       sprintf (err_str, err_fmt, nvp->value);
8859       ValNodeAddPointer (&err_list, 0, err_str);
8860     }
8861   }
8862   value_list = NameValuePairListFree (value_list);
8863   return err_list;
8864 }
8865 
ValueListDialog(GrouP h,Uint2 num_rows,Int2 width,ValNodePtr choice_list,ValueListParentPtr parent,TaglistCallback change_notify,Pointer change_userdata)8866 extern DialoG ValueListDialog (GrouP h, Uint2 num_rows, Int2 width, ValNodePtr choice_list, ValueListParentPtr parent, TaglistCallback change_notify, Pointer change_userdata)
8867 {
8868   ValueListDialogPtr dlg;
8869   GrouP           p, g;
8870   Int4            i;
8871 
8872   p = HiddenGroup (h, 3, 0, NULL);
8873   SetGroupSpacing (p, 3, 3);
8874   dlg = (ValueListDialogPtr) MemNew (sizeof(ValueListDialogData));
8875 
8876   SetObjectExtra (p, dlg, CleanupValueListDialog);
8877   dlg->dialog = (DialoG) p;
8878   dlg->todialog = ValueListPairToDialog;
8879   dlg->fromdialog = DialogToNameValuePairList;
8880   dlg->testdialog = TestValueListDialog;
8881   dlg->dialogmessage = ValueListDialogMessage;
8882   dlg->change_notify = change_notify;
8883   dlg->change_userdata = change_userdata;
8884 
8885   dlg->num_rows = num_rows;
8886 
8887   /* navigation bar on left */
8888   dlg->left_bar = ScrollBar (p, 0, dlg->num_rows, ScrollValueListProc);
8889   SetObjectExtra (dlg->left_bar, dlg, NULL);
8890   CorrectBarPage (dlg->left_bar, dlg->num_rows - 1, dlg->num_rows - 1);
8891 
8892   g = HiddenGroup (p, 1, 0, NULL);
8893   dlg->rows = (DialoG *) MemNew (num_rows * sizeof (DialoG));
8894   for (i = 0; i < dlg->num_rows; i++)
8895   {
8896     dlg->rows[i] = ValueListRowDialog (g, width, choice_list, parent, ChangeValueRow, dlg, (DialoG) p);
8897 
8898   }
8899 
8900   /* navigation bar on right */
8901   dlg->right_bar = ScrollBar (p, 0, dlg->num_rows, ScrollValueListProc);
8902   SetObjectExtra (dlg->right_bar, dlg, NULL);
8903   CorrectBarPage (dlg->right_bar, dlg->num_rows - 1, dlg->num_rows - 1);
8904 
8905   AlignObjects (ALIGN_LOWER, (HANDLE) g, (HANDLE) dlg->left_bar, (HANDLE) dlg->right_bar, NULL);
8906 
8907 
8908   return (DialoG) p;
8909 }
8910 
8911 
8912 typedef struct modifierlistdlg {
8913   VALUE_LIST_PARENT_FIELDS
8914 
8915   DialoG dlg;
8916   ButtoN type_strain;
8917   TexT   taxname;
8918 
8919   EnumFieldAssocPtr al;
8920 } ModifierListDlgData, PNTR ModifierListDlgPtr;
8921 
8922 
TestModifierListDlg(DialoG d)8923 static ValNodePtr TestModifierListDlg (DialoG d)
8924 {
8925   ModifierListDlgPtr dlg = (ModifierListDlgPtr) GetObjectExtra (d);
8926   if (dlg == NULL) return NULL;
8927   return TestDialog (dlg->dlg);
8928 }
8929 
8930 
8931 
SubSourceListToNameValueList(SubSourcePtr ssp)8932 static ValNodePtr SubSourceListToNameValueList (SubSourcePtr ssp)
8933 {
8934   ValNodePtr val_list = NULL;
8935   NameValuePairPtr nvp;
8936 
8937   while (ssp != NULL)
8938   {
8939     if (ssp->subtype != SUBSRC_other)
8940     {
8941       nvp = (NameValuePairPtr) MemNew (sizeof (NameValuePairData));
8942       nvp->name_vnp = ValNodeNew(NULL);
8943       nvp->name_vnp->choice = 1;
8944       nvp->name_vnp->data.ptrvalue = StringSave (GetSubsourceQualName (ssp->subtype));
8945       nvp->value = StringSave (ssp->name);
8946       ValNodeAddPointer (&val_list, 0, nvp);
8947     }
8948     ssp = ssp->next;
8949   }
8950   return val_list;
8951 
8952 }
8953 
8954 
SubSourceListToDialog(DialoG d,Pointer data)8955 static void SubSourceListToDialog (DialoG d, Pointer data)
8956 {
8957   ModifierListDlgPtr dlg;
8958   SubSourcePtr ssp;
8959   ValNodePtr   vnp;
8960   CharPtr      note_txt = NULL;
8961 
8962   dlg = (ModifierListDlgPtr) GetObjectExtra (d);
8963 
8964   if (dlg == NULL) return;
8965 
8966   ssp = (SubSourcePtr) data;
8967 
8968   vnp = SubSourceListToNameValueList (ssp);
8969   PointerToDialog (dlg->dlg, vnp);
8970 
8971   while (ssp != NULL)
8972   {
8973     if (ssp->subtype == SUBSRC_other)
8974     {
8975       note_txt = combine_strings (note_txt, ssp->name);
8976     }
8977     ssp = ssp->next;
8978   }
8979   SetTitle (dlg->note, note_txt);
8980 
8981 }
8982 
8983 
DialogToSubSourceList(DialoG d)8984 static Pointer DialogToSubSourceList (DialoG d)
8985 {
8986   ModifierListDlgPtr dlg;
8987   ValNodePtr   val_list, vnp;
8988   NameValuePairPtr nvp;
8989   SubSourcePtr     ssp_list = NULL, ssp_prev = NULL, ssp_new;
8990   Uint1            subtype;
8991   CharPtr          comment_str;
8992 
8993   dlg = (ModifierListDlgPtr) GetObjectExtra (d);
8994 
8995   if (dlg == NULL) return NULL;
8996 
8997   val_list = (ValNodePtr) DialogToPointer (dlg->dlg);
8998   for (vnp = val_list; vnp != NULL; vnp = vnp->next)
8999   {
9000     if (vnp->data.ptrvalue != NULL)
9001     {
9002       nvp = (NameValuePairPtr) vnp->data.ptrvalue;
9003       if (nvp != NULL && nvp->name_vnp != NULL)
9004       {
9005         subtype = EquivalentSubSourceEx (nvp->name_vnp->data.ptrvalue, TRUE);
9006         if (subtype != 0)
9007         {
9008           ssp_new = SubSourceNew ();
9009           ssp_new->subtype = subtype;
9010           ssp_new->name = StringSave (nvp->value == NULL ? "" : nvp->value);
9011           if (ssp_prev == NULL)
9012           {
9013             ssp_list = ssp_new;
9014           }
9015           else
9016           {
9017             ssp_prev->next = ssp_new;
9018           }
9019           ssp_prev = ssp_new;
9020         }
9021       }
9022     }
9023   }
9024   val_list = NameValuePairListFree (val_list);
9025 
9026   /* add comment */
9027   comment_str = SaveStringFromText (dlg->note);
9028   if (!StringHasNoText (comment_str))
9029   {
9030     ssp_new = SubSourceNew();
9031     ssp_new->subtype = SUBSRC_other;
9032     ssp_new->name = StringSave (comment_str);
9033     if (ssp_prev == NULL)
9034     {
9035       ssp_list = ssp_new;
9036     }
9037     else
9038     {
9039       ssp_prev->next = ssp_new;
9040     }
9041     ssp_prev = ssp_new;
9042   }
9043 
9044   return ssp_list;
9045 }
9046 
9047 
GetSubSourceChoicesForValueList(EnumFieldAssocPtr al)9048 static ValNodePtr GetSubSourceChoicesForValueList (EnumFieldAssocPtr al)
9049 {
9050   ValNodePtr choice_list = NULL;
9051   EnumFieldAssocPtr efap;
9052 
9053   efap = al;
9054   while (efap->name != NULL)
9055   {
9056     if (StringHasNoText (efap->name))
9057     {
9058       ValNodeAddStr (&choice_list, eValueEditSimpleText + 1, StringSave (efap->name));
9059     }
9060     else if (efap->value == SUBSRC_lat_lon)
9061     {
9062       ValNodeAddStr (&choice_list, eValueEditLatLon + 1, StringSave (efap->name));
9063     }
9064     else if (efap->value == SUBSRC_altitude)
9065     {
9066       ValNodeAddStr (&choice_list, eValueEditAltitude + 1, StringSave (efap->name));
9067     }
9068     else if (IsNonTextModifier (efap->name))
9069     {
9070       ValNodeAddStr (&choice_list, eValueEditTrueFalse + 1, StringSave (efap->name));
9071     }
9072     else
9073     {
9074       ValNodeAddStr (&choice_list, eValueEditSimpleText + 1, StringSave (efap->name));
9075     }
9076     efap ++;
9077   }
9078   return choice_list;
9079 }
9080 
9081 
9082 static CharPtr subsource_extra_prompts [] = {
9083   "Additional", "Source", "Information", NULL
9084 };
9085 
9086 
CreateSubSourceDialog(GrouP h,EnumFieldAssocPtr al)9087 extern DialoG CreateSubSourceDialog (GrouP h, EnumFieldAssocPtr al)
9088 {
9089   ModifierListDlgPtr dlg;
9090   GrouP        p, g, x;
9091   ValNodePtr   choice_list;
9092   Int2         max;
9093   ButtoN       b;
9094 
9095 
9096   p = HiddenGroup (h, -1, 0, NULL);
9097   SetGroupSpacing (p, 10, 10);
9098   dlg = (ModifierListDlgPtr) MemNew (sizeof(ModifierListDlgData));
9099 
9100   SetObjectExtra (p, dlg, StdCleanupExtraProc);
9101   dlg->dialog = (DialoG) p;
9102   dlg->todialog = SubSourceListToDialog;
9103   dlg->fromdialog = DialogToSubSourceList;
9104   dlg->testdialog = TestModifierListDlg;
9105   dlg->dialogmessage = NULL;
9106 
9107   choice_list = GetSubSourceChoicesForValueList (al);
9108   dlg->dlg = ValueListDialog (p, 3, 23, choice_list, (ValueListParentPtr) dlg, NULL, NULL);
9109   choice_list = ValNodeFreeData (choice_list);
9110 
9111   g = HiddenGroup (p, 3, 0, NULL);
9112   SelectFont (programFont);
9113   max = MaxStringWidths (subsource_extra_prompts) + 2;
9114   x = MultiLinePrompt (g, "Additional Source Information", max, programFont);
9115   dlg->note = ScrollText (g, 20, 3, programFont, TRUE, NULL);
9116   b = PushButton (g, "X", ClearTextBtn);
9117   SetObjectExtra (b, dlg->note, NULL);
9118 
9119   AlignObjects (ALIGN_MIDDLE, (HANDLE) x, (HANDLE) dlg->note, (HANDLE) b, NULL);
9120 
9121   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->dlg, (HANDLE) g, NULL);
9122 
9123   return (DialoG) p;
9124 }
9125 
9126 
OrgModListToNameValueList(OrgModPtr mod)9127 static ValNodePtr OrgModListToNameValueList (OrgModPtr mod)
9128 {
9129   ValNodePtr val_list = NULL;
9130   NameValuePairPtr nvp;
9131 
9132   while (mod != NULL)
9133   {
9134     if (mod->subtype != ORGMOD_gb_acronym
9135         && mod->subtype != ORGMOD_gb_anamorph
9136         && mod->subtype != ORGMOD_gb_synonym
9137         && mod->subtype != ORGMOD_type_material
9138         && mod->subtype != ORGMOD_other)
9139     {
9140       nvp = (NameValuePairPtr) MemNew (sizeof (NameValuePairData));
9141       nvp->name_vnp = ValNodeNew(NULL);
9142       nvp->name_vnp->choice = 1;
9143       nvp->name_vnp->data.ptrvalue = StringSave (GetOrgModQualName (mod->subtype));
9144       nvp->value = StringSave (mod->subname);
9145       ValNodeAddPointer (&val_list, 0, nvp);
9146     }
9147     mod = mod->next;
9148   }
9149   return val_list;
9150 
9151 }
9152 
9153 
OrgModListToDialog(DialoG d,Pointer data)9154 static void OrgModListToDialog (DialoG d, Pointer data)
9155 {
9156   ModifierListDlgPtr dlg;
9157   OrgModPtr          mod;
9158   ValNodePtr         vnp;
9159   CharPtr            note_txt = NULL;
9160 
9161   dlg = (ModifierListDlgPtr) GetObjectExtra (d);
9162 
9163   if (dlg == NULL) return;
9164 
9165   mod = (OrgModPtr) data;
9166 
9167   vnp = OrgModListToNameValueList (mod);
9168   PointerToDialog (dlg->dlg, vnp);
9169 
9170   while (mod != NULL)
9171   {
9172     if (mod->subtype == ORGMOD_other)
9173     {
9174       note_txt = combine_strings (note_txt, mod->subname);
9175     }
9176     mod = mod->next;
9177   }
9178   SetTitle (dlg->note, note_txt);
9179 
9180 }
9181 
9182 
DialogToOrgModList(DialoG d)9183 static Pointer DialogToOrgModList (DialoG d)
9184 {
9185   ModifierListDlgPtr dlg;
9186   ValNodePtr   val_list, vnp;
9187   NameValuePairPtr nvp;
9188   OrgModPtr        mod_list = NULL, mod_prev = NULL, mod_new;
9189   Uint1            subtype;
9190   CharPtr          comment_str;
9191 
9192   dlg = (ModifierListDlgPtr) GetObjectExtra (d);
9193 
9194   if (dlg == NULL) return NULL;
9195 
9196   val_list = (ValNodePtr) DialogToPointer (dlg->dlg);
9197   for (vnp = val_list; vnp != NULL; vnp = vnp->next)
9198   {
9199     if (vnp->data.ptrvalue != NULL)
9200     {
9201       nvp = (NameValuePairPtr) vnp->data.ptrvalue;
9202       if (nvp != NULL && nvp->name_vnp != NULL)
9203       {
9204         subtype = EquivalentOrgModEx (nvp->name_vnp->data.ptrvalue, TRUE);
9205         if (subtype != 0)
9206         {
9207           mod_new = OrgModNew ();
9208           mod_new->subtype = subtype;
9209           mod_new->subname = StringSave (nvp->value == NULL ? "" : nvp->value);
9210           if (mod_prev == NULL)
9211           {
9212             mod_list = mod_new;
9213           }
9214           else
9215           {
9216             mod_prev->next = mod_new;
9217           }
9218           mod_prev = mod_new;
9219         }
9220       }
9221     }
9222   }
9223   val_list = NameValuePairListFree (val_list);
9224 
9225   /* add comment */
9226   comment_str = SaveStringFromText (dlg->note);
9227   if (!StringHasNoText (comment_str))
9228   {
9229     mod_new = OrgModNew();
9230     mod_new->subtype = ORGMOD_other;
9231     mod_new->subname = StringSave (comment_str);
9232     if (mod_prev == NULL)
9233     {
9234       mod_list = mod_new;
9235     }
9236     else
9237     {
9238       mod_prev->next = mod_new;
9239     }
9240     mod_prev = mod_new;
9241   }
9242 
9243   return mod_list;
9244 }
9245 
9246 
IsNonTextModifier(CharPtr mod_name)9247 extern Boolean IsNonTextModifier (CharPtr mod_name)
9248 {
9249   if (StringICmp (mod_name, "transgenic") == 0
9250       || StringICmp (mod_name, "germline") == 0
9251       || StringICmp (mod_name, "metagenomic") == 0
9252       || StringICmp (mod_name, "environmental-sample") ==0
9253       || StringICmp (mod_name, "rearranged") == 0)
9254   {
9255     return TRUE;
9256   }
9257   else
9258   {
9259     return FALSE;
9260   }
9261 }
9262 
9263 
GetOrgModChoicesForValueList(EnumFieldAssocPtr al)9264 static ValNodePtr GetOrgModChoicesForValueList (EnumFieldAssocPtr al)
9265 {
9266   ValNodePtr choice_list = NULL;
9267   EnumFieldAssocPtr efap;
9268 
9269   efap = al;
9270   while (efap->name != NULL)
9271   {
9272     if (StringHasNoText (efap->name))
9273     {
9274       ValNodeAddStr (&choice_list, eValueEditSimpleText + 1, StringSave (efap->name));
9275     }
9276     else if (IsNonTextModifier (efap->name))
9277     {
9278       ValNodeAddStr (&choice_list, eValueEditTrueFalse + 1, StringSave (efap->name));
9279     }
9280     else if (efap->value == ORGMOD_specimen_voucher || efap->value == ORGMOD_culture_collection || efap->value == ORGMOD_bio_material)
9281     {
9282       ValNodeAddStr (&choice_list, eValueEditSpecimenVoucher + 1, StringSave (efap->name));
9283     }
9284     else
9285     {
9286       ValNodeAddStr (&choice_list, eValueEditSimpleText + 1, StringSave (efap->name));
9287     }
9288     efap ++;
9289   }
9290   return choice_list;
9291 }
9292 
9293 
9294 static CharPtr orgmod_extra_prompts [] = {
9295   "Additional", "Organism", "Information", NULL
9296 };
9297 
ChangeOrgmodComment(TexT t)9298 static void ChangeOrgmodComment (TexT t)
9299 {
9300   ModifierListDlgPtr dlg;
9301   CharPtr str;
9302 
9303   dlg = (ModifierListDlgPtr) GetObjectExtra (t);
9304   if (dlg == NULL) return;
9305 
9306   str = SaveStringFromText (t);
9307   if ( StringStr (str, "type strain of ")) {
9308     Disable (dlg->type_strain);
9309   }
9310 
9311 }
9312 
9313 
AddTypeStrainProc(ButtoN b)9314 static void AddTypeStrainProc (ButtoN b)
9315 {
9316   ModifierListDlgPtr dlg;
9317   CharPtr        old_orgcomment;
9318   Int4           old_orgcomment_len;
9319   CharPtr        org_name;
9320   Int4           org_name_len;
9321   const CharPtr  ts = "type strain of ";
9322   const CharPtr  sep = "; ";
9323   CharPtr        new_orgcomment;
9324 
9325   dlg = (ModifierListDlgPtr) GetObjectExtra (b);
9326   if (dlg == NULL) return;
9327 
9328   old_orgcomment_len = TextLength (dlg->note) + 1;
9329   old_orgcomment = MemNew (old_orgcomment_len + 1);
9330   if (old_orgcomment == NULL) return;
9331   org_name_len = TextLength (dlg->taxname) + 1;
9332   org_name = MemNew (org_name_len + 1);
9333   if (org_name == NULL)
9334   {
9335     MemFree (old_orgcomment);
9336     return;
9337   }
9338   new_orgcomment = MemNew (old_orgcomment_len
9339             + StringLen (sep)
9340             + StringLen (ts)
9341             + org_name_len
9342             + 1);
9343   if (new_orgcomment == NULL)
9344   {
9345     MemFree (old_orgcomment);
9346     MemFree (org_name);
9347   }
9348 
9349   GetTitle (dlg->note, old_orgcomment, old_orgcomment_len);
9350   TrimSpacesAroundString (old_orgcomment);
9351   GetTitle (dlg->taxname, org_name, org_name_len);
9352   TrimSpacesAroundString (org_name);
9353   if (old_orgcomment[0] != 0)
9354   {
9355     StringCpy(new_orgcomment, old_orgcomment);
9356     StringCat(new_orgcomment, sep);
9357   }
9358   else if (new_orgcomment != NULL)
9359   {
9360     new_orgcomment[0] = 0;
9361   }
9362 
9363   StringCat (new_orgcomment, ts);
9364   StringCat (new_orgcomment, org_name);
9365   SetTitle (dlg->note, new_orgcomment);
9366   MemFree (org_name);
9367   MemFree (old_orgcomment);
9368   MemFree (new_orgcomment);
9369   Disable (b);
9370 }
9371 
9372 
CreateOrgModDialog(GrouP h,EnumFieldAssocPtr al,TexT taxname)9373 extern DialoG CreateOrgModDialog (GrouP h, EnumFieldAssocPtr al, TexT taxname)
9374 {
9375   ModifierListDlgPtr dlg;
9376   GrouP        p, g, x;
9377   ValNodePtr   choice_list;
9378   Int2         max;
9379   ButtoN       b;
9380 
9381 
9382   p = HiddenGroup (h, -1, 0, NULL);
9383   SetGroupSpacing (p, 10, 10);
9384   dlg = (ModifierListDlgPtr) MemNew (sizeof(ModifierListDlgData));
9385 
9386   SetObjectExtra (p, dlg, StdCleanupExtraProc);
9387   dlg->dialog = (DialoG) p;
9388   dlg->todialog = OrgModListToDialog;
9389   dlg->fromdialog = DialogToOrgModList;
9390   dlg->testdialog = TestModifierListDlg;
9391   dlg->dialogmessage = NULL;
9392 
9393   choice_list = GetOrgModChoicesForValueList (al);
9394   dlg->dlg = ValueListDialog (p, 3, 23, choice_list, (ValueListParentPtr) dlg, NULL, NULL);
9395   choice_list = ValNodeFreeData (choice_list);
9396 
9397   g = HiddenGroup (p, 3, 0, NULL);
9398   SelectFont (programFont);
9399   max = MaxStringWidths (orgmod_extra_prompts) + 2;
9400   x = MultiLinePrompt (g, "Additional Organism Information", max, programFont);
9401   dlg->note = ScrollText (g, 20, 3, programFont, TRUE, ChangeOrgmodComment);
9402   SetObjectExtra (dlg->note, dlg, NULL);
9403   b = PushButton (g, "X", ClearTextBtn);
9404   SetObjectExtra (b, dlg->note, NULL);
9405   AlignObjects (ALIGN_MIDDLE, (HANDLE) x, (HANDLE) dlg->note, (HANDLE) b, NULL);
9406 
9407   dlg->taxname = taxname;
9408   if (dlg->taxname != NULL)
9409   {
9410     dlg->type_strain = PushButton (p, "Add type strain to comment", AddTypeStrainProc);
9411     SetObjectExtra (dlg->type_strain, dlg, NULL);
9412   }
9413   else
9414   {
9415     dlg->type_strain = NULL;
9416   }
9417 
9418   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->dlg, (HANDLE) g, (HANDLE) dlg->type_strain, NULL);
9419 
9420   return (DialoG) p;
9421 }
9422 
9423 
CreateStandardEditMenu(WindoW w)9424 extern void CreateStandardEditMenu (WindoW w)
9425 {
9426   MenU m;
9427   IteM i;
9428 
9429   /* Edit Menu */
9430   m = PulldownMenu (w, "Edit");
9431   i = CommandItem (m, "Cut", StdCutTextProc);
9432   i = CommandItem (m, "Copy", StdCopyTextProc);
9433   i = CommandItem (m, "Paste", StdPasteTextProc);
9434   i = CommandItem (m, "Clear", StdDeleteTextProc);
9435 }
9436 
9437 
9438 static ValNodePtr sqnTempFiles = NULL;
9439 
RememberSqnTempFile(CharPtr file)9440 extern void RememberSqnTempFile (CharPtr file)
9441 
9442 {
9443   ValNodePtr  vnp;
9444 
9445   if (StringHasNoText (file)) return;
9446 
9447   vnp = ValNodeCopyStr (NULL, 0, file);
9448   if (vnp == NULL) return;
9449 
9450   vnp->next = sqnTempFiles;
9451   sqnTempFiles = vnp;
9452 }
9453 
FreeSqnTempFiles(void)9454 extern void FreeSqnTempFiles (void)
9455 
9456 {
9457   CharPtr     file;
9458   ValNodePtr  list;
9459   ValNodePtr  vnp;
9460 
9461   if (sqnTempFiles == NULL) return;
9462 
9463   list = sqnTempFiles;
9464   sqnTempFiles = NULL;
9465 
9466   for (vnp = list; vnp != NULL; vnp = vnp->next) {
9467     file = (CharPtr) vnp->data.ptrvalue;
9468     if (StringHasNoText (file)) continue;
9469     FileRemove (file);
9470   }
9471 
9472   ValNodeFreeData (list);
9473 }
9474 
9475 
9476 /* This gets a list of the open views */
GetBaseFormList(void)9477 NLM_EXTERN ValNodePtr GetBaseFormList (void)
9478 
9479 {
9480   Uint4          j;
9481   Uint4          num;
9482   ObjMgrPtr      omp;
9483   ObjMgrDataPtr  omdp;
9484   ObjMgrDataPtr  PNTR omdpp;
9485   OMUserDataPtr  omudp;
9486   BaseFormPtr    bfp;
9487   ValNodePtr     base_form_list = NULL;
9488 
9489   omp = ObjMgrGet ();
9490   if (omp == NULL) return NULL;
9491   num = omp->currobj;
9492   for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
9493     omdp = *omdpp;
9494     if (omdp->parentptr == NULL) {
9495       for (omudp = omdp->userdata; omudp != NULL; omudp = omudp->next) {
9496         if (omudp->proctype == OMPROC_VIEW) {
9497           bfp = (BaseFormPtr) omudp->userdata.ptrvalue;
9498           ValNodeAddPointer (&base_form_list, 0, bfp);
9499         }
9500       }
9501     }
9502   }
9503   return base_form_list;
9504 }
9505 
9506 
9507 /* This gets a list of the top SeqEntry for each open view */
GetViewedSeqEntryList(void)9508 NLM_EXTERN ValNodePtr GetViewedSeqEntryList (void)
9509 {
9510   ValNodePtr  sep_list = NULL, base_form_list, vnp;
9511   BaseFormPtr bfp;
9512   SeqEntryPtr sep;
9513 
9514   base_form_list = GetBaseFormList();
9515   for (vnp = base_form_list; vnp != NULL; vnp = vnp->next) {
9516     bfp = (BaseFormPtr) vnp->data.ptrvalue;
9517     if (bfp != NULL && bfp->input_entityID != 0) {
9518       sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
9519       ValNodeAddPointer (&sep_list, 0, sep);
9520     }
9521   }
9522   base_form_list = ValNodeFree (base_form_list);
9523   return sep_list;
9524 }
9525 
9526 
AddCitSubFromSeqSubmit(SeqEntryPtr sep,SeqSubmitPtr ssp)9527 static void AddCitSubFromSeqSubmit (SeqEntryPtr sep, SeqSubmitPtr ssp)
9528 {
9529   SeqDescPtr    sdp;
9530   PubdescPtr    pdp;
9531 
9532   if (sep == NULL || ssp == NULL || ssp->sub == NULL || ssp->sub->cit == NULL) {
9533     return;
9534   }
9535 
9536   pdp = PubdescNew ();
9537   ValNodeAddPointer (&(pdp->pub), PUB_Sub, ssp->sub->cit);
9538   ssp->sub->cit = NULL;
9539 
9540   sdp = CreateNewDescriptor (sep, Seq_descr_pub);
9541   sdp->data.ptrvalue = pdp;
9542 }
9543 
9544 
RestoreFromFileEx(CharPtr path,Boolean convert_seqsubmit_to_pub)9545 NLM_EXTERN SeqEntryPtr RestoreFromFileEx (CharPtr path, Boolean convert_seqsubmit_to_pub)
9546 
9547 {
9548   BioseqPtr     bsp;
9549   BioseqSetPtr  bssp;
9550   Pointer       dataptr;
9551   Uint2         datatype;
9552   Uint2         entityID;
9553   SeqEntryPtr   rsult;
9554   SeqEntryPtr   sep;
9555   SeqSubmitPtr  ssp;
9556 
9557   rsult = NULL;
9558   if (path != NULL && path [0] != '\0') {
9559     dataptr = ObjMgrGenericAsnTextFileRead (path, &datatype, &entityID);
9560     if (dataptr != NULL && entityID > 0) {
9561       if (datatype == OBJ_SEQSUB || datatype == OBJ_SEQENTRY ||
9562           datatype == OBJ_BIOSEQ || datatype == OBJ_BIOSEQSET) {
9563         WatchCursor ();
9564         sep = GetTopSeqEntryForEntityID (entityID);
9565         if (sep == NULL) {
9566           sep = SeqEntryNew ();
9567           if (sep != NULL) {
9568             if (datatype == OBJ_BIOSEQ) {
9569               bsp = (BioseqPtr) dataptr;
9570               sep->choice = 1;
9571               sep->data.ptrvalue = bsp;
9572               SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, sep);
9573             } else if (datatype == OBJ_BIOSEQSET) {
9574               bssp = (BioseqSetPtr) dataptr;
9575               sep->choice = 2;
9576               sep->data.ptrvalue = bssp;
9577               SeqMgrSeqEntry (SM_BIOSEQSET, (Pointer) bssp, sep);
9578             } else {
9579               sep = SeqEntryFree (sep);
9580             }
9581           }
9582           sep = GetTopSeqEntryForEntityID (entityID);
9583         }
9584         if (sep != NULL) {
9585           rsult = SeqEntryNew ();
9586           if (rsult != NULL) {
9587             rsult->choice = sep->choice;
9588             rsult->data.ptrvalue = sep->data.ptrvalue;
9589             sep->data.ptrvalue = NULL;
9590             if (datatype == OBJ_SEQSUB) {
9591               ssp = (SeqSubmitPtr) dataptr;
9592               if (convert_seqsubmit_to_pub) {
9593                 AddCitSubFromSeqSubmit(rsult, ssp);
9594               }
9595               SeqSubmitFree ((SeqSubmitPtr) dataptr);
9596             } else {
9597               SeqEntryFree (sep);
9598             }
9599             /*Message (MSG_OK, "Call new object manager free function");*/
9600           }
9601         }
9602         ArrowCursor ();
9603       }
9604       /*
9605       ObjMgrDelete (entityID);
9606       */
9607     }
9608   }
9609   return rsult;
9610 }
9611 
9612 
RestoreFromFile(CharPtr path)9613 NLM_EXTERN SeqEntryPtr RestoreFromFile (CharPtr path)
9614 {
9615   return RestoreFromFileEx (path, FALSE);
9616 }
9617 
9618 
RestoreEntityIDFromFileEx(CharPtr path,Uint2 entityID,Boolean convert_seqsubmit_to_pub)9619 NLM_EXTERN Uint2 RestoreEntityIDFromFileEx (CharPtr path, Uint2 entityID, Boolean convert_seqsubmit_to_pub)
9620 {
9621   SeqEntryPtr scope, oldsep, currsep;
9622   Uint2 newid = 0;
9623 
9624   scope = SeqEntrySetScope (NULL);
9625   oldsep = RestoreFromFileEx (path, convert_seqsubmit_to_pub);
9626   currsep = GetTopSeqEntryForEntityID (entityID);
9627   if (oldsep == NULL || currsep == NULL) {
9628     SeqEntrySetScope (scope);
9629   } else {
9630     ReplaceSeqEntryWithSeqEntry (currsep, oldsep, TRUE);
9631     SeqEntrySetScope (NULL);
9632     newid = ObjMgrGetEntityIDForChoice (currsep);
9633   }
9634   return newid;
9635 }
9636 
9637 
RestoreEntityIDFromFile(CharPtr path,Uint2 entityID)9638 NLM_EXTERN Uint2 RestoreEntityIDFromFile (CharPtr path, Uint2 entityID)
9639 {
9640   return RestoreEntityIDFromFileEx (path, entityID, FALSE);
9641 }
9642 
9643 
CloseLog(LogInfoPtr lip)9644 NLM_EXTERN void CloseLog (LogInfoPtr lip)
9645 {
9646   if (lip == NULL || lip->fp == NULL)
9647   {
9648     return;
9649   }
9650   FileClose (lip->fp);
9651   lip->fp = NULL;
9652   if (lip->data_in_log)
9653   {
9654     LaunchGeneralTextViewer (lip->path, lip->display_title);
9655   }
9656   FileRemove (lip->path);
9657 }
9658 
9659 
ShowLog(LogInfoPtr lip)9660 NLM_EXTERN void ShowLog (LogInfoPtr lip)
9661 {
9662   if (lip == NULL || lip->fp == NULL)
9663   {
9664     return;
9665   }
9666   FileClose (lip->fp);
9667   lip->fp = NULL;
9668   if (lip->data_in_log)
9669   {
9670     LaunchGeneralTextViewer (lip->path, lip->display_title);
9671   }
9672   lip->fp = FileOpen (lip->path, "a");
9673 }
9674 
9675 
EditIdList(SeqIdPtr PNTR sip_list,SeqIdPtr all_list)9676 static Boolean EditIdList (SeqIdPtr PNTR sip_list, SeqIdPtr all_list)
9677 {
9678   ModalAcceptCancelData acd;
9679   DialoG                dlg;
9680   WindoW                w;
9681   ButtoN                b;
9682   GrouP                 h, c;
9683   ValNodePtr            tmp;
9684 
9685   if (sip_list == NULL || *sip_list == NULL) return FALSE;
9686 
9687   w = MovableModalWindow(-20, -13, -10, -10, "Constraint", NULL);
9688   h = HiddenGroup (w, -1, 0, NULL);
9689   SetGroupSpacing (h, 10, 10);
9690 
9691   /* create dialog with list of sequence IDs */
9692   dlg = ValNodeSelectionDialogExEx (h, ValNodeSeqIdListCopy(all_list), TALL_SELECTION_LIST, ValNodeSeqIdName,
9693                                            ValNodeSeqIdFree, ValNodeSeqIdCopy,
9694                                            ValNodeSeqIdMatch, "location",
9695                                            NULL, NULL, TRUE, TRUE, FALSE, NULL);
9696 
9697   /* populate */
9698   tmp = SeqIdListToValNodeSeqIdList (*sip_list);
9699   PointerToDialog (dlg, tmp);
9700   tmp = ValNodeSeqIdListFree(tmp);
9701 
9702   c = HiddenGroup (h, 2, 0, NULL);
9703   SetGroupSpacing (c, 10, 10);
9704   b = PushButton (c, "Accept", ModalAcceptButton);
9705   SetObjectExtra (b, &acd, NULL);
9706   b = PushButton (c, "Cancel", ModalCancelButton);
9707   SetObjectExtra (b, &acd, NULL);
9708   AlignObjects (ALIGN_CENTER, (HANDLE) dlg,
9709                               (HANDLE) c,
9710                               NULL);
9711 
9712   Show (w);
9713   Select (w);
9714   acd.accepted = FALSE;
9715   acd.cancelled = FALSE;
9716   while (!acd.accepted && ! acd.cancelled)
9717   {
9718     ProcessExternalEvent ();
9719     Update ();
9720   }
9721   ProcessAnEvent ();
9722   if (!acd.cancelled)
9723   {
9724     tmp = DialogToPointer (dlg);
9725     *sip_list = ValNodeSeqIdListToSeqIdList (tmp);
9726     tmp = ValNodeSeqIdListFree(tmp);
9727   }
9728   Remove (w);
9729   return acd.accepted;
9730 }
9731 
9732 
EditOneDescriptor(SeqDescPtr sdp)9733 static Boolean EditOneDescriptor (SeqDescPtr sdp)
9734 {
9735   Boolean rval = FALSE;
9736 
9737   if (sdp == NULL)
9738   {
9739     return FALSE;
9740   }
9741   else if (sdp->choice == Seq_descr_pub)
9742   {
9743     rval = EditPubdescInPlace(sdp);
9744   }
9745   return rval;
9746 }
9747 
9748 typedef struct descriptorstreameditordlg {
9749   DIALOG_MESSAGE_BLOCK
9750 
9751   DoC    pub_doc;
9752 
9753   ValNodePtr               desc_stream_list;
9754   ValNodePtr               sip_list;
9755   Nlm_ChangeNotifyProc     change_notify;
9756   Pointer                  change_userdata;
9757 } DescriptorStreamEditorDlgData, PNTR DescriptorStreamEditorDlgPtr;
9758 
9759 
9760 #define k_WideColumnWidth 50
9761 
9762 
GetDescriptorFlatFileText(SeqDescPtr sdp)9763 static CharPtr GetDescriptorFlatFileText (SeqDescPtr sdp)
9764 {
9765   Asn2gbJobPtr   ajp;
9766   BaseBlockPtr   bbp;
9767   XtraBlock      extra;
9768   BioseqPtr      bsp;
9769   ErrSev         level;
9770   CharPtr        desc_text = NULL, cp;
9771   Int4           index;
9772 
9773 
9774   if (sdp == NULL)
9775   {
9776     return NULL;
9777   }
9778   bsp = BioseqNew ();
9779   bsp->descr = AsnIoMemCopy (sdp, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite);
9780   bsp->repr = Seq_repr_raw;
9781 
9782   level = ErrSetMessageLevel (SEV_MAX);
9783 
9784   MemSet ((Pointer) &extra, 0, sizeof (XtraBlock));
9785   ajp = asn2gnbk_setup (bsp, NULL, NULL, (FmtType)GENBANK_FMT, SEQUIN_MODE, NORMAL_STYLE, 0, 0, 0, &extra);
9786   if (ajp != NULL)
9787   {
9788     for (index = 0; index < ajp->numParagraphs; index++)
9789     {
9790       bbp = ajp->paragraphArray [index];
9791       if (bbp->blocktype == REFERENCE_BLOCK)
9792       {
9793         desc_text = asn2gnbk_format (ajp, (Int4) index);
9794         if (desc_text != NULL) {
9795           /* skip first line */
9796           cp = StringChr (desc_text, 10);
9797           if (cp != NULL) {
9798             StringCpy (desc_text, cp + 1);
9799             while ((cp = StringChr (desc_text, 10)) != NULL) {
9800               *cp = '~';
9801             }
9802           }
9803         }
9804       }
9805     }
9806   }
9807 
9808   ErrSetMessageLevel (level);
9809 
9810   ajp = asn2gnbk_cleanup (ajp);
9811   bsp = BioseqFree (bsp);
9812   return desc_text;
9813 }
9814 
9815 
GetDescriptorText(SeqDescPtr sdp,StdPrintOptionsPtr spop)9816 static CharPtr GetDescriptorText (SeqDescPtr sdp, StdPrintOptionsPtr spop)
9817 {
9818   CharPtr text = NULL, tmp;
9819   ValNode pub_field;
9820   PubdescPtr pdp;
9821 
9822   if (sdp == NULL) {
9823     return NULL;
9824   } else if (sdp->choice == Seq_descr_pub) {
9825     MemSet (&pub_field, 0, sizeof (ValNode));
9826     pub_field.choice = FieldType_pub;
9827     pub_field.data.intvalue = Publication_field_title;
9828     text = GetFieldValueForObject (OBJ_SEQDESC, sdp, &pub_field, NULL);
9829     if (text == NULL) {
9830       pub_field.data.intvalue = Publication_field_cit;
9831       text = GetFieldValueForObject (OBJ_SEQDESC, sdp, &pub_field, NULL);
9832       if (text == NULL) {
9833         pub_field.data.intvalue = Publication_field_authors;
9834         text = GetFieldValueForObject (OBJ_SEQDESC, sdp, &pub_field, NULL);
9835       }
9836     }
9837     if ((pdp = (PubdescPtr) sdp->data.ptrvalue) != NULL
9838         && pdp->pub != NULL
9839         && pdp->pub->choice == PUB_Sub) {
9840       if (text == NULL) {
9841         text = StringSave ("CitSub");
9842       } else {
9843         tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (text) + 8));
9844         sprintf (tmp, "CitSub:%s", text);
9845         text = MemFree (text);
9846         text = tmp;
9847       }
9848     }
9849     if (text == NULL) {
9850       text = StringSave ("No information for pub");
9851     }
9852   } else {
9853     text = GetDescriptorFlatFileText (sdp);
9854     if (text == NULL)
9855     {
9856       if (StdFormatPrint ((Pointer) sdp, (AsnWriteFunc) SeqDescAsnWrite,
9857                                         "StdSeqDesc", spop))
9858       {
9859         if (StringNICmp (spop->ptr, "citation;", 9) == 0)
9860         {
9861           text = StringSave (spop->ptr + 9);
9862         }
9863         else
9864         {
9865           text = StringSave (spop->ptr);
9866         }
9867         spop->ptr = MemFree (spop->ptr);
9868       } else {
9869         text = StringSave ("Unable to format");
9870       }
9871     }
9872   }
9873   return text;
9874 }
9875 
9876 
AddOnePublicationToPubDoc(DoC doc,DescStreamPtr d,ParPtr ParFmt,ColPtr ColFmt)9877 static void AddOnePublicationToPubDoc (DoC doc,  DescStreamPtr d, ParPtr ParFmt, ColPtr ColFmt)
9878 {
9879   Char    txt[300];
9880   CharPtr tmp;
9881   Char    buf[k_WideColumnWidth];
9882 
9883   if (doc == NULL || d == NULL) {
9884     return;
9885   }
9886 
9887 
9888   if (d->replace == NULL) {
9889     sprintf (txt, " \tUndelete\t");
9890   } else {
9891     sprintf (txt, "Edit\tDelete\t");
9892   }
9893 
9894   if (d->orig == NULL) {
9895     StringCat (txt, "New\t");
9896   } else {
9897     tmp = GetDescriptorText (d->orig, spop);
9898     if (StringLen (tmp) > k_WideColumnWidth) {
9899       tmp[k_WideColumnWidth] = 0;
9900     }
9901     StringCat (txt, tmp);
9902     StringCat (txt, "\t");
9903     tmp = MemFree (tmp);
9904   }
9905 
9906   if (d->replace == NULL) {
9907     StringCat (txt, "Deleted\t");
9908   } else {
9909     tmp = GetDescriptorText (d->replace, spop);
9910     if (StringLen (tmp) > k_WideColumnWidth) {
9911       tmp[k_WideColumnWidth] = 0;
9912     }
9913     StringCat (txt, tmp);
9914     StringCat (txt, "\t");
9915     tmp = MemFree (tmp);
9916   }
9917 
9918   if (d->owners == NULL) {
9919     StringCat (txt, "No owners - will be deleted\t");
9920   } else if (d->on_all) {
9921     StringCat (txt, "All\t");
9922   } else {
9923     SeqIdWrite (d->owners, buf, PRINTID_FASTA_ALL, sizeof (buf) - 1);
9924     StringCat (txt, buf);
9925     StringCat (txt, "\t");
9926   }
9927 
9928   if (d->num_dependent == 0) {
9929     StringCat (txt, " \n");
9930   } else {
9931     sprintf (buf, "%d featcit\n", d->num_dependent);
9932     StringCat (txt, buf);
9933   }
9934 
9935   AppendText (doc, txt, ParFmt, ColFmt, programFont);
9936 }
9937 
PublicationListDialogRedraw(DescriptorStreamEditorDlgPtr dlg)9938 static void PublicationListDialogRedraw (DescriptorStreamEditorDlgPtr dlg)
9939 {
9940   ValNodePtr         vnp;
9941   RecT               r;
9942   WindoW             temport;
9943   Int4               i;
9944   ParData            ParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
9945   ColData            ColFmt[] =
9946   {
9947     {0, 0, 5, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, FALSE},
9948     {0, 0, 9, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, FALSE},
9949     {0, 0, k_WideColumnWidth, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, FALSE},
9950     {0, 0, k_WideColumnWidth, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, FALSE},
9951     {0, 0, k_WideColumnWidth, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, FALSE},
9952     {0, 0, k_WideColumnWidth, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, FALSE},
9953     {0, 0, 20, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE}
9954   };
9955 
9956   if (dlg == NULL)
9957   {
9958     return;
9959   }
9960 
9961   Reset (dlg->pub_doc);
9962 
9963   SelectFont (programFont);
9964   for (i = 0; i < sizeof (ColFmt) / sizeof (ColData); i++) {
9965     ColFmt[i].pixWidth = ColFmt[i].charWidth * CharWidth('0');
9966   }
9967 
9968   /* make row list for table display and update table display */
9969   for (vnp = dlg->desc_stream_list;
9970        vnp != NULL;
9971        vnp = vnp->next)
9972   {
9973     AddOnePublicationToPubDoc (dlg->pub_doc, vnp->data.ptrvalue, &ParFmt, ColFmt);
9974   }
9975   AppendText (dlg->pub_doc, " \t \tAdd new publication\n", &ParFmt, ColFmt, programFont);
9976 
9977 
9978   temport = SavePort (dlg->pub_doc);
9979   Select (dlg->pub_doc);
9980   ObjectRect (dlg->pub_doc, &r);
9981   InvalRect (&r);
9982   RestorePort (temport);
9983   Update ();
9984 
9985 
9986 }
9987 
9988 
ShadePubButtons(DoC d,Int2 item,Int2 row,Int2 col)9989 static Boolean ShadePubButtons (DoC d, Int2 item, Int2 row, Int2 col)
9990 
9991 {
9992   DescriptorStreamEditorDlgPtr dlg;
9993   Boolean    shade = FALSE;
9994 
9995   dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
9996   if (dlg == NULL || dlg->desc_stream_list == NULL) {
9997     return FALSE;
9998   }
9999   if (item < 1) {
10000     shade = FALSE;
10001   } else if (item == ValNodeLen (dlg->desc_stream_list) + 1) {
10002     if (col == 3) {
10003       shade = TRUE;
10004     } else {
10005       shade = FALSE;
10006     }
10007   } else if (col == 1 || col == 2) {
10008     shade = TRUE;
10009   }
10010   return shade;
10011 }
10012 
10013 
ClickPubDoc(DoC d,PoinT pt)10014 static void ClickPubDoc (DoC d, PoinT pt)
10015 {
10016   DescriptorStreamEditorDlgPtr dlg;
10017   Int2                         item, row, col;
10018   RecT                         rct;
10019   DescStreamPtr                ds;
10020   ValNodePtr                   vnp;
10021   Boolean                      changed = FALSE;
10022   Int2                         d_num;
10023 
10024   dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
10025   if (dlg == NULL) return;
10026 
10027   MapDocPoint (d, pt, &item, &row, &col, &rct);
10028   if (item == 0) return;
10029   for (vnp = dlg->desc_stream_list, d_num = 1;
10030        vnp != NULL && d_num < item;
10031        vnp = vnp->next, d_num++)
10032   {
10033   }
10034 
10035   if (vnp == NULL || (ds = (DescStreamPtr) vnp->data.ptrvalue) == NULL) {
10036     /* add new publication */
10037     ds = DescStreamNew (NULL, NULL);
10038     ds->replace = SeqDescrNew (NULL);
10039     ds->replace->choice = Seq_descr_pub;
10040     ds->replace->data.ptrvalue = PubdescNew ();
10041     if (EditOneDescriptor (ds->replace))
10042     {
10043       ds->owners = ValNodeSeqIdListToSeqIdList (dlg->sip_list);
10044       ValNodeAddPointer (&(dlg->desc_stream_list), 0, ds);
10045       changed = TRUE;
10046     }
10047     else
10048     {
10049       ds = DescStreamFree (ds);
10050     }
10051   } else {
10052 
10053     switch (col) {
10054       case 1:
10055       case 3:
10056       case 4:
10057         /* edit */
10058         changed = EditOneDescriptor (ds->replace);
10059         break;
10060       case 2:
10061         /* delete */
10062         if (ds->replace == NULL) {
10063           ds->replace = AsnIoMemCopy (ds->orig, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite);
10064         } else {
10065           if (ANS_YES != Message (MSG_YN, "Are you sure you want to delete the publication?"))
10066           {
10067             return;
10068           }
10069           ds->replace = SeqDescFree (ds->replace);
10070           changed = TRUE;
10071         }
10072         break;
10073       case 5:
10074         /* edit owner list */
10075         if (EditIdList (&(ds->owners), dlg->sip_list)) {
10076           ds->on_all = IdListsMatch(ds->owners, dlg->sip_list);
10077           changed = TRUE;
10078         }
10079         break;
10080     }
10081   }
10082 
10083 
10084   if (changed) {
10085     PublicationListDialogRedraw (dlg);
10086   }
10087 }
10088 
10089 
DescriptorStreamToDialog(DialoG d,Pointer userdata)10090 static void DescriptorStreamToDialog (DialoG d, Pointer userdata)
10091 {
10092   DescriptorStreamEditorDlgPtr dlg;
10093 
10094   dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
10095   if (dlg == NULL)
10096   {
10097     return;
10098   }
10099 
10100   dlg->desc_stream_list = (ValNodePtr) userdata;
10101 
10102   PublicationListDialogRedraw(dlg);
10103 
10104 
10105 }
10106 
DialogToDescriptorStream(DialoG d)10107 static Pointer DialogToDescriptorStream (DialoG d)
10108 {
10109   DescriptorStreamEditorDlgPtr dlg;
10110   ValNodePtr                   list = NULL;
10111 
10112   dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
10113   if (dlg == NULL)
10114   {
10115     return NULL;
10116   }
10117 
10118   return (Pointer) list;
10119 }
10120 
10121 
CleanupDescriptorStreamEditorDlg(GraphiC g,VoidPtr data)10122 static void CleanupDescriptorStreamEditorDlg (GraphiC g, VoidPtr data)
10123 {
10124   DescriptorStreamEditorDlgPtr dlg;
10125 
10126   dlg = (DescriptorStreamEditorDlgPtr) data;
10127   if (dlg != NULL) {
10128     dlg->sip_list = ValNodeSeqIdListFree(dlg->sip_list);
10129   }
10130   StdCleanupExtraProc (g, data);
10131 }
10132 
10133 
DescriptorStreamEditor(GrouP h,Nlm_ChangeNotifyProc change_notify,Pointer change_userdata)10134 NLM_EXTERN DialoG DescriptorStreamEditor (GrouP h,  Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
10135 {
10136   DescriptorStreamEditorDlgPtr dlg;
10137   GrouP           p;
10138 
10139   dlg = (DescriptorStreamEditorDlgPtr) MemNew (sizeof (DescriptorStreamEditorDlgData));
10140   if (dlg == NULL)
10141   {
10142     return NULL;
10143   }
10144 
10145   p = HiddenGroup (h, -1, 0, NULL);
10146   SetObjectExtra (p, dlg, CleanupDescriptorStreamEditorDlg);
10147   SetGroupSpacing (p, 10, 10);
10148 
10149   dlg->dialog = (DialoG) p;
10150   dlg->todialog = DescriptorStreamToDialog;
10151   dlg->fromdialog = DialogToDescriptorStream;
10152   dlg->change_notify = change_notify;
10153   dlg->change_userdata = change_userdata;
10154   SelectFont (programFont);
10155 
10156   dlg->pub_doc = DocumentPanel (p, CharWidth('0') * 150, stdLineHeight * 12);
10157   SetObjectExtra (dlg->pub_doc, dlg, NULL);
10158   SetDocProcs (dlg->pub_doc, ClickPubDoc, NULL, NULL, NULL);
10159   SetDocShade (dlg->pub_doc, NULL, NULL, ShadePubButtons, NULL);
10160 
10161   return (DialoG) p;
10162 }
10163 
10164 
SetDescriptorStreamEditorIdList(DialoG d,SeqIdPtr sip_list)10165 NLM_EXTERN void SetDescriptorStreamEditorIdList (DialoG d, SeqIdPtr sip_list)
10166 {
10167   DescriptorStreamEditorDlgPtr dlg;
10168 
10169   dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
10170   if (dlg != NULL) {
10171     dlg->sip_list = ValNodeSeqIdListFree (dlg->sip_list);
10172     dlg->sip_list = SeqIdListToValNodeSeqIdList (sip_list);
10173   }
10174 }
10175 
10176 
10177